start backend

This commit is contained in:
Tyler Murphy 2023-01-21 09:08:22 -05:00
parent 773c5ed3db
commit a50ccedcaa
18 changed files with 2677 additions and 49 deletions

View file

@ -5,7 +5,7 @@ const port = 8080
app.use(express.json());
app.use(express.static('public'))
app.get('/', (req, res) => {
app.get('/login', (req, res) => {
res.sendFile('login.html', { root: './public' })
})
@ -17,6 +17,13 @@ app.get('/people', (req, res) => {
res.sendFile('people.html', { root: './public' })
})
app.get('/profile', (req, res) => {
res.sendFile('profile.html', { root: './public' })
})
const api = require('./src/api.js')
app.use('/api', api);
app.use((req, res, next) => {
res.status(404).sendFile('404.html', { root: './public' })
})

2076
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,7 @@
"author": "Tyler Murphy",
"license": "WTFPL",
"dependencies": {
"express": "^4.18.2"
"express": "^4.18.2",
"sqlite3": "^5.1.4"
}
}

View file

@ -1,12 +1,17 @@
#header {
height: 3.5em;
background-color: white;
position: absolute;
position: fixed;
width: 100vw;
box-shadow: 0 2px 4px rgba(0, 0, 0, .05), 0 8px 16px rgba(0, 0, 0, .05);
display: flex;
align-items: center;
justify-content: space-between;
z-index: 5;
}
.spacer {
margin-bottom: 5em;
}
#header .logo {
@ -34,7 +39,17 @@
color: #606770;
}
#header .buttons a:hover {
background-color: #dddfe2;
}
.selected {
color: #1778f2 !important;
border-bottom: 3px solid #1778f2;
}
#header .pfp, #header .pfp img {
position: absolute;
right: 1em;
top: .5em;
}

File diff suppressed because one or more lines are too long

View file

@ -56,10 +56,22 @@ body {
}
.stext {
font-family: sfpro;
font-size: 10px;
}
.mtext {
font-family: sfpro;
font-size: 15px;
}
.ltext {
font-family: sfpro;
font-size: 22px;
}
.ctext {
display: block;
font-family: sfpro;
text-align: center;
}
@ -252,3 +264,23 @@ footer {
visibility: hidden;
pointer-events: none;
}
.pfp, .pfp img {
display: block;
width: 2.5em;
height: 2.5em;
border-radius: 3em;
background-color: #e4e6e8;
flex-shrink: 0;
}
.nb {
margin-bottom: 0;
}
form {
all: unset;
border-radius: 10px;
margin-left: 10px;
width: 100%;
}

3
public/css/people.css Normal file
View file

@ -0,0 +1,3 @@
body {
background-color: #f0f2f5;
}

3
public/css/profile.css Normal file
View file

@ -0,0 +1,3 @@
body {
background-color: #f0f2f5;
}

View file

@ -2,28 +2,14 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="css/header.css">
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/home.css">
<link rel="stylesheet" href="css/header.css">
<title>XSSBook - Home</title>
</head>
<body>
<div id="header">
<span class="logo">xssbook</span>
<div class="buttons">
<a id="home" class="selected" href="home">
<svg viewBox="0 0 28 28" fill="currentColor" height="28" width="28">
<path d="M25.825 12.29C25.824 12.289 25.823 12.288 25.821 12.286L15.027 2.937C14.752 2.675 14.392 2.527 13.989 2.521 13.608 2.527 13.248 2.675 13.001 2.912L2.175 12.29C1.756 12.658 1.629 13.245 1.868 13.759 2.079 14.215 2.567 14.479 3.069 14.479L5 14.479 5 23.729C5 24.695 5.784 25.479 6.75 25.479L11 25.479C11.552 25.479 12 25.031 12 24.479L12 18.309C12 18.126 12.148 17.979 12.33 17.979L15.67 17.979C15.852 17.979 16 18.126 16 18.309L16 24.479C16 25.031 16.448 25.479 17 25.479L21.25 25.479C22.217 25.479 23 24.695 23 23.729L23 14.479 24.931 14.479C25.433 14.479 25.921 14.215 26.132 13.759 26.371 13.245 26.244 12.658 25.825 12.29"></path>
</svg>
</a>
<a id="people" href="people">
<svg viewBox="0 0 28 28" fill="currentColor" height="28" width="28">
<path d="M10.5 4.5c-2.272 0-2.75 1.768-2.75 3.25C7.75 9.542 8.983 11 10.5 11s2.75-1.458 2.75-3.25c0-1.482-.478-3.25-2.75-3.25zm0 8c-2.344 0-4.25-2.131-4.25-4.75C6.25 4.776 7.839 3 10.5 3s4.25 1.776 4.25 4.75c0 2.619-1.906 4.75-4.25 4.75zm9.5-6c-1.41 0-2.125.841-2.125 2.5 0 1.378.953 2.5 2.125 2.5 1.172 0 2.125-1.122 2.125-2.5 0-1.659-.715-2.5-2.125-2.5zm0 6.5c-1.999 0-3.625-1.794-3.625-4 0-2.467 1.389-4 3.625-4 2.236 0 3.625 1.533 3.625 4 0 2.206-1.626 4-3.625 4zm4.622 8a.887.887 0 00.878-.894c0-2.54-2.043-4.606-4.555-4.606h-1.86c-.643 0-1.265.148-1.844.413a6.226 6.226 0 011.76 4.336V21h5.621zm-7.122.562v-1.313a4.755 4.755 0 00-4.749-4.749H8.25A4.755 4.755 0 003.5 20.249v1.313c0 .518.421.938.937.938h12.125c.517 0 .938-.42.938-.938zM20.945 14C24.285 14 27 16.739 27 20.106a2.388 2.388 0 01-2.378 2.394h-5.81a2.44 2.44 0 01-2.25 1.5H4.437A2.44 2.44 0 012 21.562v-1.313A6.256 6.256 0 018.25 14h4.501a6.2 6.2 0 013.218.902A5.932 5.932 0 0119.084 14h1.861z"></path>
</svg>
</a>
</div>
</div>
<p>
b
</p>
<script src="./js/main.js"></script>
<script src="./js/header.js"></script>
<script src="./js/home.js"></script>
</body>
</html>

25
public/js/header.js Normal file
View file

@ -0,0 +1,25 @@
function header(home, people) {
const html = `
<div id="header">
<span class="logo">xssbook</span>
<div class="buttons">
<a id="home" ${home ? 'class="selected"' : ''} href="home">
<svg viewBox="0 0 28 28" fill="currentColor" height="28" width="28">
<path d="M25.825 12.29C25.824 12.289 25.823 12.288 25.821 12.286L15.027 2.937C14.752 2.675 14.392 2.527 13.989 2.521 13.608 2.527 13.248 2.675 13.001 2.912L2.175 12.29C1.756 12.658 1.629 13.245 1.868 13.759 2.079 14.215 2.567 14.479 3.069 14.479L5 14.479 5 23.729C5 24.695 5.784 25.479 6.75 25.479L11 25.479C11.552 25.479 12 25.031 12 24.479L12 18.309C12 18.126 12.148 17.979 12.33 17.979L15.67 17.979C15.852 17.979 16 18.126 16 18.309L16 24.479C16 25.031 16.448 25.479 17 25.479L21.25 25.479C22.217 25.479 23 24.695 23 23.729L23 14.479 24.931 14.479C25.433 14.479 25.921 14.215 26.132 13.759 26.371 13.245 26.244 12.658 25.825 12.29"></path>
</svg>
</a>
<a id="people" ${people ? 'class="selected"' : ''} href="people">
<svg viewBox="0 0 28 28" fill="currentColor" height="28" width="28">
<path d="M10.5 4.5c-2.272 0-2.75 1.768-2.75 3.25C7.75 9.542 8.983 11 10.5 11s2.75-1.458 2.75-3.25c0-1.482-.478-3.25-2.75-3.25zm0 8c-2.344 0-4.25-2.131-4.25-4.75C6.25 4.776 7.839 3 10.5 3s4.25 1.776 4.25 4.75c0 2.619-1.906 4.75-4.25 4.75zm9.5-6c-1.41 0-2.125.841-2.125 2.5 0 1.378.953 2.5 2.125 2.5 1.172 0 2.125-1.122 2.125-2.5 0-1.659-.715-2.5-2.125-2.5zm0 6.5c-1.999 0-3.625-1.794-3.625-4 0-2.467 1.389-4 3.625-4 2.236 0 3.625 1.533 3.625 4 0 2.206-1.626 4-3.625 4zm4.622 8a.887.887 0 00.878-.894c0-2.54-2.043-4.606-4.555-4.606h-1.86c-.643 0-1.265.148-1.844.413a6.226 6.226 0 011.76 4.336V21h5.621zm-7.122.562v-1.313a4.755 4.755 0 00-4.749-4.749H8.25A4.755 4.755 0 003.5 20.249v1.313c0 .518.421.938.937.938h12.125c.517 0 .938-.42.938-.938zM20.945 14C24.285 14 27 16.739 27 20.106a2.388 2.388 0 01-2.378 2.394h-5.81a2.44 2.44 0 01-2.25 1.5H4.437A2.44 2.44 0 012 21.562v-1.313A6.256 6.256 0 018.25 14h4.501a6.2 6.2 0 013.218.902A5.932 5.932 0 0119.084 14h1.861z"></path>
</svg>
</a>
</div>
<a class="pfp" id="profile" hreF="profile">
</a>
</div>
<div class="spacer"></div>
`
add(html, 'header')
}

207
public/js/home.js Normal file
View file

@ -0,0 +1,207 @@
function parseDate(date) {
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
return months[date.getUTCMonth()] + ' ' + date.getUTCDate() + ', ' + date.getUTCFullYear() + ' ' + date.toLocaleTimeString();
}
function parseComment(data) {
const html = `
<div class="comment">
<a class="pfp">
</a>
<span>
<span class="bold mtext">${data.firstname + ' ' + data.lastname}</span>
<p class="mtext">${data.content}</p>
</span>
</div>
`
return html
}
function parsePost(post, likes) {
const html = `
<div class="post" postid=${post.id}>
<div class="postheader">
<a class="pfp">
</a>
<div class="postname">
<span class="bold">${post.author.firstname + ' ' + post.author.lastname}</span>
<span class="gtext mtext">${parseDate(new Date(post.time))}</span>
</div>
</div>
<p class="mtext">
${post.content}
</p>
<span class="gtext mtext">
${post.likes} Likes
</span>
<div class="fullline nb"></div>
<div class="postbuttons">
<span onclick="like(this)">
<i class="icons like ${likes.includes(post.id) ? 'blue' : ''}"></i>
<span class="bold ${likes.includes(post.id) ? 'blue' : ''}">Like</span>
</span>
<span onclick="this.parentElement.parentElement.getElementsByClassName('newcomment')[0].focus()">
<i class="icons comm"></i>
<span class="bold">Comment</span>
</span>
</div>
<div id="comments">
<div class="fullline" style="margin-top: 0"></div>
${post.comments.map(parseComment).join('')}
<div class="comment">
<a class="pfp" href="profile">
</a>
<form onsubmit="comment(event)">
<input type="text" name="text" placeholder="Write a comment..." id="newcomment" class="newcomment">
</form>
</div>
</div>
</div>
`
return html
}
function getPost(id) {
for (let i = 0; i < data.posts.length; i++) {
if (data.posts[i].id === id) {
return i
}
}
return -1
}
function like(span) {
const id = parseInt(span.parentElement.parentElement.getAttribute('postid'))
const index = data.user.likes.indexOf(id)
if (index === -1) {
data.user.likes.push(id)
data.posts[getPost(id)].likes++
} else {
data.user.likes.splice(index, 1)
data.posts[getPost(id)].likes--
}
load()
}
function comment(event) {
event.preventDefault();
const text = event.target.elements.text.value.trim();
if (text.length < 1) return;
const id = parseInt(event.target.parentElement.parentElement.parentElement.getAttribute('postid'))
var index = getPost(id);
console.log(index)
if (index === -1) return;
data.posts[index].comments.push({
firstname: data.user.firstname,
lastname: data.user.lastname,
content: text
})
load()
}
function post(event) {
const text = document.getElementById("text").value.trim()
if (text.length < 1) return;
data.posts.unshift({
id: data.posts[0].id + 1,
author: {
firstname: data.user.firstname,
lastname: data.user.lastname
},
time: Date.now(),
content: text,
likes: 0,
comments: []
})
load()
}
function load() {
const html = `
<div id="posts">
<div class="create">
<a class="pfp" href="profile">
</a>
<button class="pfp">
<p class="gtext" onclick="document.getElementById('popup').classList.remove('hidden')">
What's on your mind, ${data.user.firstname}?
</p>
</button>
</div>
${data.posts.map(p => parsePost(p, data.user.likes)).join('')}
</div>
`
add(html, 'posts')
const popup = `
<div id="popup" class="hidden">
<div class="createpost">
<div class="close" onclick="document.getElementById('popup').classList.add('hidden')"></div>
<span class="ltext ctext bold">Create post</span>
<div class="fullline"></div>
<div class="postheader">
<a class="pfp" style="cursor: auto">
</a>
<div class="postname">
<span class="bold">${data.user.firstname + ' ' + data.user.lastname}</span>and ho
<span class="gtext mtext">Now</span>
</div>
</div>
<textarea type="text" name="text" id="text" placeholder="What's on your mind, ${data.user.firstname}?"></textarea>
<button class="primary" onclick="post(this)">Post</button>
</div>
</div>
`
add(popup, 'popup')
}
var data = {
user: {
firstname: 'John',
lastname: 'Doe',
likes: [1]
},
posts: [
{
id: 1,
author: {
firstname: 'Joe',
lastname: 'Biden',
},
time: 1674269687905,
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
likes: 2,
comments: [],
},
{
id: 0,
author: {
firstname: 'Amazon',
lastname: 'Employee',
},
time: 0,
content: 'I dont like working at amazon >:(',
likes: 69,
comments: [
{
firstname: 'Jeff',
lastname: 'Bezos',
content: 'You\'re fired.'
},
],
}
]
}
header(true, false)
load();

View file

@ -0,0 +1,15 @@
var range;
function add(html, id) {
const old = document.getElementById(id)
if (old !== null) {
old.remove()
}
if (range === undefined) {
var range = document.createRange()
range.setStart(document.body, 0)
}
document.body.appendChild(
range.createContextualFragment(html)
)
}

1
public/js/people.js Normal file
View file

@ -0,0 +1 @@
header(false, true)

View file

@ -5,25 +5,10 @@
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/home.css">
<link rel="stylesheet" href="css/header.css">
<title>XSSBook - Home</title>
<title>XSSBook - People</title>
</head>
<body>
<div id="header">
<span class="logo">xssbook</span>
<div class="buttons">
<a id="home" href="home">
<svg viewBox="0 0 28 28" fill="currentColor" height="28" width="28">
<path d="M25.825 12.29C25.824 12.289 25.823 12.288 25.821 12.286L15.027 2.937C14.752 2.675 14.392 2.527 13.989 2.521 13.608 2.527 13.248 2.675 13.001 2.912L2.175 12.29C1.756 12.658 1.629 13.245 1.868 13.759 2.079 14.215 2.567 14.479 3.069 14.479L5 14.479 5 23.729C5 24.695 5.784 25.479 6.75 25.479L11 25.479C11.552 25.479 12 25.031 12 24.479L12 18.309C12 18.126 12.148 17.979 12.33 17.979L15.67 17.979C15.852 17.979 16 18.126 16 18.309L16 24.479C16 25.031 16.448 25.479 17 25.479L21.25 25.479C22.217 25.479 23 24.695 23 23.729L23 14.479 24.931 14.479C25.433 14.479 25.921 14.215 26.132 13.759 26.371 13.245 26.244 12.658 25.825 12.29"></path>
</svg>
</a>
<a id="people" class="selected" href="people">
<svg viewBox="0 0 28 28" fill="currentColor" height="28" width="28">
<path d="M10.5 4.5c-2.272 0-2.75 1.768-2.75 3.25C7.75 9.542 8.983 11 10.5 11s2.75-1.458 2.75-3.25c0-1.482-.478-3.25-2.75-3.25zm0 8c-2.344 0-4.25-2.131-4.25-4.75C6.25 4.776 7.839 3 10.5 3s4.25 1.776 4.25 4.75c0 2.619-1.906 4.75-4.25 4.75zm9.5-6c-1.41 0-2.125.841-2.125 2.5 0 1.378.953 2.5 2.125 2.5 1.172 0 2.125-1.122 2.125-2.5 0-1.659-.715-2.5-2.125-2.5zm0 6.5c-1.999 0-3.625-1.794-3.625-4 0-2.467 1.389-4 3.625-4 2.236 0 3.625 1.533 3.625 4 0 2.206-1.626 4-3.625 4zm4.622 8a.887.887 0 00.878-.894c0-2.54-2.043-4.606-4.555-4.606h-1.86c-.643 0-1.265.148-1.844.413a6.226 6.226 0 011.76 4.336V21h5.621zm-7.122.562v-1.313a4.755 4.755 0 00-4.749-4.749H8.25A4.755 4.755 0 003.5 20.249v1.313c0 .518.421.938.937.938h12.125c.517 0 .938-.42.938-.938zM20.945 14C24.285 14 27 16.739 27 20.106a2.388 2.388 0 01-2.378 2.394h-5.81a2.44 2.44 0 01-2.25 1.5H4.437A2.44 2.44 0 012 21.562v-1.313A6.256 6.256 0 018.25 14h4.501a6.2 6.2 0 013.218.902A5.932 5.932 0 0119.084 14h1.861z"></path>
</svg>
</a>
</div>
</div>
<p>
b
</p>
<script src="./js/main.js"></script>
<script src="./js/header.js"></script>
<script src="./js/people.js"></script>
</body>

29
public/profile.html Normal file
View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/profile.css">
<link rel="stylesheet" href="css/header.css">
<title>XSSBook - Profile</title>
</head>
<body>
<div id="header">
<span class="logo">xssbook</span>
<div class="buttons">
<a id="home" href="home">
<svg viewBox="0 0 28 28" fill="currentColor" height="28" width="28">
<path d="M25.825 12.29C25.824 12.289 25.823 12.288 25.821 12.286L15.027 2.937C14.752 2.675 14.392 2.527 13.989 2.521 13.608 2.527 13.248 2.675 13.001 2.912L2.175 12.29C1.756 12.658 1.629 13.245 1.868 13.759 2.079 14.215 2.567 14.479 3.069 14.479L5 14.479 5 23.729C5 24.695 5.784 25.479 6.75 25.479L11 25.479C11.552 25.479 12 25.031 12 24.479L12 18.309C12 18.126 12.148 17.979 12.33 17.979L15.67 17.979C15.852 17.979 16 18.126 16 18.309L16 24.479C16 25.031 16.448 25.479 17 25.479L21.25 25.479C22.217 25.479 23 24.695 23 23.729L23 14.479 24.931 14.479C25.433 14.479 25.921 14.215 26.132 13.759 26.371 13.245 26.244 12.658 25.825 12.29"></path>
</svg>
</a>
<a id="people" href="people">
<svg viewBox="0 0 28 28" fill="currentColor" height="28" width="28">
<path d="M10.5 4.5c-2.272 0-2.75 1.768-2.75 3.25C7.75 9.542 8.983 11 10.5 11s2.75-1.458 2.75-3.25c0-1.482-.478-3.25-2.75-3.25zm0 8c-2.344 0-4.25-2.131-4.25-4.75C6.25 4.776 7.839 3 10.5 3s4.25 1.776 4.25 4.75c0 2.619-1.906 4.75-4.25 4.75zm9.5-6c-1.41 0-2.125.841-2.125 2.5 0 1.378.953 2.5 2.125 2.5 1.172 0 2.125-1.122 2.125-2.5 0-1.659-.715-2.5-2.125-2.5zm0 6.5c-1.999 0-3.625-1.794-3.625-4 0-2.467 1.389-4 3.625-4 2.236 0 3.625 1.533 3.625 4 0 2.206-1.626 4-3.625 4zm4.622 8a.887.887 0 00.878-.894c0-2.54-2.043-4.606-4.555-4.606h-1.86c-.643 0-1.265.148-1.844.413a6.226 6.226 0 011.76 4.336V21h5.621zm-7.122.562v-1.313a4.755 4.755 0 00-4.749-4.749H8.25A4.755 4.755 0 003.5 20.249v1.313c0 .518.421.938.937.938h12.125c.517 0 .938-.42.938-.938zM20.945 14C24.285 14 27 16.739 27 20.106a2.388 2.388 0 01-2.378 2.394h-5.81a2.44 2.44 0 01-2.25 1.5H4.437A2.44 2.44 0 012 21.562v-1.313A6.256 6.256 0 018.25 14h4.501a6.2 6.2 0 013.218.902A5.932 5.932 0 0119.084 14h1.861z"></path>
</svg>
</a>
</div>
<a id="profile" hreF="profile">
</a>
</div>
</body>

9
src/api.js Normal file
View file

@ -0,0 +1,9 @@
const express = require('express')
const router = express.Router()
const database = require('./database.js')
router.get('/', (req, res) => {
res.status(200).send( {msg: 'xssbook api'} )
})
module.exports = router;

74
src/database.js Normal file
View file

@ -0,0 +1,74 @@
const sqlite3 = require('sqlite3')
const path = require('path').resolve(__dirname, '../xssbook.db')
let db = new sqlite3.Database(path, sqlite3.OPEN_READWRITE, (err) => {
if (err && err.code == "SQLITE_CANTOPEN") {
createDatabase();
return;
} else if (err) {
console.log(err);
}
addUser('John','Doe','johndoe@gmail.com','password','lettuce',0,'jan',0,69)
})
function createDatabase() {
db = new sqlite3.Database(path, (err) => {
if (err) {
console.log(err);
}
createTables();
});
}
function createTables() {
db.exec(`
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
first VARCHAR(20) NOT NULL,
last VARCHAR(20) NOT NULL,
email VARCHAR(50) NOT NULL,
password VARCHAR(50) NOT NULL,
gender VARCHAR(20) NOT NULL,
date INTEGER NOT NULL,
month VARCHAR(3) NOT NULL,
day INTEGER NOT NULL,
year INTEGER NOT NULL
);
CREATE TABLE posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user INTEGER NOT NULL,
content TEXT NOT NULL,
likes TEXT NOT NULL,
comments TEXT NOT NULL,
date INTEGER NOT NULL,
FOREIGN KEY(user) REFERENCES users(id)
);
CREATE TABLE avatars (
id INTEGER PRIMARY KEY NOT NULL,
avatar BLOB,
banner BLOB,
FOREIGN KEY(id) REFERENCES users(id)
);
`, (err) => {
if(err) {
console.log(err)
}
})
}
function addUser(first, last, email, password, gender, date, month, day, year) {
db.exec(`
INSERT INTO users (first, last, email, password, gender, date, month, day, year) VALUES (?,?,?,?,?,?,?,?,?);
`, [first, last, email, password, gender, date, month, day, year] , (err) => {
if(err) {
console.log(err)
return false
} else {
return true
}
})
}

BIN
xssbook.db Normal file

Binary file not shown.