Add initial server setup

This commit is contained in:
Kevin Thomas
2021-07-20 22:44:00 -07:00
parent 5585d81690
commit 413925131d
11 changed files with 1572 additions and 357 deletions

1690
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,15 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"body-parser": "^1.19.0",
"connect-ensure-login": "^0.1.1",
"cookie-parser": "^1.4.5",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"express": "^4.17.1",
"express-session": "^1.17.2",
"passport": "^0.4.1",
"passport-local": "^1.0.0",
"sqlite3": "^5.0.2",
"tone": "^14.7.77", "tone": "^14.7.77",
"vue": "^2.6.11", "vue": "^2.6.11",
"vuetify": "^2.4.0" "vuetify": "^2.4.0"

41
server/app.js Normal file
View File

@@ -0,0 +1,41 @@
const express = require('express');
const passport = require('passport');
const path = require('path');
const cookieParser = require('cookie-parser');
const db = require('./db');
const ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn;
const crypto = require('crypto');
const indexRouter = require('./routes/index');
const authRouter = require('./routes/auth');
const myaccountRouter = require('./routes/myaccount');
const usersRouter = require('./routes/users');
const app = express();
require('./boot/db')();
require('./boot/auth')();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false }));
app.use(function(req, res, next) {
const msgs = req.session.messages || [];
res.locals.messages = msgs;
res.locals.hasMessages = !! msgs.length;
req.session.messages = [];
next();
});
app.use(passport.initialize());
app.use(passport.authenticate('session'));
// Define routes
app.use('/', indexRouter);
app.use('/', authRouter);
app.use('/myaccount', myaccountRouter);
app.use('/users', usersRouter);
module.exports = app;

55
server/boot/auth.js Normal file
View File

@@ -0,0 +1,55 @@
const passport = require('passport');
const Strategy = require('passport-local');
const crypto = require('crypto');
const db = require('../db');
module.exports = function() {
// Configure the local strategy for use by Passport.
//
// The local strategy requires a `verify` function which receives the credentials
// (`username` and `password`) submitted by the user. The function must verify
// that the password is correct and then invoke `cb` with a user object, which
// will be set at `req.user` in route handlers after authentication.
passport.use(new Strategy(function(username, password, cb) {
db.get('SELECT rowid AS id, * FROM users WHERE username = ?', [ username ], function(err, row) {
if (err) { return cb(err); }
if (!row) { return cb(null, false, { message: 'Incorrect username or password.' }); }
crypto.pbkdf2(password, row.salt, 10000, 32, 'sha256', function(err, hashedPassword) {
if (err) { return cb(err); }
if (!crypto.timingSafeEqual(row.hashed_password, hashedPassword)) {
return cb(null, false, { message: 'Incorrect username or password.' });
}
const user = {
id: row.id.toString(),
username: row.username,
displayName: row.name
};
return cb(null, user);
});
});
}));
// Configure Passport authenticated session persistence.
//
// In order to restore authentication state across HTTP requests, Passport needs
// to serialize users into and deserialize users out of the session. The
// typical implementation of this is as simple as supplying the user ID when
// serializing, and querying the user record by ID from the database when
// deserializing.
passport.serializeUser(function(user, cb) {
process.nextTick(function() {
cb(null, { id: user.id, username: user.username });
});
});
passport.deserializeUser(function(user, cb) {
process.nextTick(function() {
return cb(null, user);
});
});
};

15
server/boot/db.js Normal file
View File

@@ -0,0 +1,15 @@
const db = require('../db');
module.exports = function() {
db.serialize(function() {
db.run("CREATE TABLE IF NOT EXISTS users ( \
username TEXT UNIQUE, \
hashed_password BLOB, \
salt BLOB, \
name TEXT \
)");
});
//db.close();
};

3
server/db.js Normal file
View File

@@ -0,0 +1,3 @@
const sqlite3 = require('sqlite3');
module.exports = new sqlite3.Database('db.sqlite3');

22
server/routes/auth.js Normal file
View File

@@ -0,0 +1,22 @@
const express = require('express');
const passport = require('passport');
const router = express.Router();
/* GET users listing. */
router.get('/login', function(req, res, next) {
res.render('login');
});
router.post('/login/password', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureMessage: true
}));
router.get('/logout', function(req, res, next) {
req.logout();
res.redirect('/');
});
module.exports = router;

9
server/routes/index.js Normal file
View File

@@ -0,0 +1,9 @@
const express = require('express');
const router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { user: req.user });
});
module.exports = router;

View File

@@ -0,0 +1,23 @@
const express = require('express');
const ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn;
const db = require('../db');
const router = express.Router();
/* GET users listing. */
router.get('/',
ensureLoggedIn(),
function(req, res, next) {
db.get('SELECT rowid AS id, username, name FROM users WHERE rowid = ?', [ req.user.id ], function(err, row) {
if (err) { return next(err); }
const user = {
id: row.id.toString(),
username: row.username,
displayName: row.name
};
res.render('profile', { user: user });
});
});
module.exports = router;

37
server/routes/users.js Normal file
View File

@@ -0,0 +1,37 @@
const express = require('express');
const crypto = require('crypto');
const db = require('../db');
const router = express.Router();
router.get('/new', function(req, res, next) {
res.render('signup');
});
router.post('/', function(req, res, next) {
const salt = crypto.randomBytes(16);
crypto.pbkdf2(req.body.password, salt, 10000, 32, 'sha256', function(err, hashedPassword) {
if (err) { return next(err); }
db.run('INSERT INTO users (username, hashed_password, salt, name) VALUES (?, ?, ?, ?)', [
req.body.username,
hashedPassword,
salt,
req.body.name
], function(err) {
if (err) { return next(err); }
const user = {
id: this.lastID.toString(),
username: req.body.username,
displayName: req.body.name
};
req.login(user, function(err) {
if (err) { return next(err); }
res.redirect('/');
});
});
});
});
module.exports = router;

26
src/App.vue.backup Normal file
View File

@@ -0,0 +1,26 @@
<template>
<v-app>
<v-main>
<AppBar />
<Noise />
</v-main>
</v-app>
</template>
<script>
import Noise from './components/Noise'
import AppBar from './components/AppBar'
export default {
name: 'App',
components: {
AppBar,
Noise,
},
data: () => ({
//
}),
}
</script>