forked from external-repos/noisedash
Add basic login and register functionality
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -102,3 +102,9 @@ dist
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Local dev certs
|
||||
certs/*
|
||||
|
||||
# SQLite DB
|
||||
db.sqlite3
|
||||
|
||||
43
package-lock.json
generated
43
package-lock.json
generated
@@ -7,10 +7,12 @@
|
||||
"": {
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"axios": "^0.21.1",
|
||||
"body-parser": "^1.19.0",
|
||||
"connect-ensure-login": "^0.1.1",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"core-js": "^3.6.5",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.17.1",
|
||||
"express-session": "^1.17.2",
|
||||
"passport": "^0.4.1",
|
||||
@@ -3147,6 +3149,14 @@
|
||||
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
|
||||
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-eslint": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
|
||||
@@ -4841,6 +4851,18 @@
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"node_modules/cors": {
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
|
||||
"dependencies": {
|
||||
"object-assign": "^4",
|
||||
"vary": "^1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/cosmiconfig": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
|
||||
@@ -7443,7 +7465,6 @@
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
|
||||
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -19132,6 +19153,14 @@
|
||||
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
|
||||
"devOptional": true
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
|
||||
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"babel-eslint": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
|
||||
@@ -20503,6 +20532,15 @@
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"cors": {
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
|
||||
"requires": {
|
||||
"object-assign": "^4",
|
||||
"vary": "^1"
|
||||
}
|
||||
},
|
||||
"cosmiconfig": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
|
||||
@@ -22561,8 +22599,7 @@
|
||||
"follow-redirects": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
|
||||
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
|
||||
},
|
||||
"for-in": {
|
||||
"version": "1.0.2",
|
||||
|
||||
@@ -4,14 +4,17 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"server": "node server/bin/www",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.21.1",
|
||||
"body-parser": "^1.19.0",
|
||||
"connect-ensure-login": "^0.1.1",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"core-js": "^3.6.5",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.17.1",
|
||||
"express-session": "^1.17.2",
|
||||
"passport": "^0.4.1",
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
const express = require('express');
|
||||
const session = require('express-session')
|
||||
const cors = require('cors')
|
||||
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 bodyParser = require("body-parser")
|
||||
|
||||
const indexRouter = require('./routes/index');
|
||||
const authRouter = require('./routes/auth');
|
||||
const myaccountRouter = require('./routes/myaccount');
|
||||
const usersRouter = require('./routes/users');
|
||||
const db = require('./db');
|
||||
|
||||
const app = express();
|
||||
|
||||
@@ -20,7 +22,7 @@ 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(session({ secret: "cats", resave: false, saveUninitialized: false }));
|
||||
app.use(function(req, res, next) {
|
||||
const msgs = req.session.messages || [];
|
||||
res.locals.messages = msgs;
|
||||
@@ -28,8 +30,10 @@ app.use(function(req, res, next) {
|
||||
req.session.messages = [];
|
||||
next();
|
||||
});
|
||||
app.use(bodyParser.json());
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.authenticate('session'));
|
||||
app.use(cors())
|
||||
|
||||
// Define routes
|
||||
app.use('/', indexRouter);
|
||||
|
||||
93
server/bin/www
Normal file
93
server/bin/www
Normal file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
const app = require('../app');
|
||||
const debug = require('debug')('example:server');
|
||||
const http = require('http');
|
||||
const https = require('https')
|
||||
const fs = require('fs')
|
||||
|
||||
/**
|
||||
* Get port from environment and store in Express.
|
||||
*/
|
||||
const port = normalizePort(process.env.PORT || '3000');
|
||||
app.set('port', port);
|
||||
|
||||
/**
|
||||
* HTTPS options.
|
||||
*/
|
||||
const httpsOptions = {
|
||||
key: fs.readFileSync('./certs/key.pem'),
|
||||
cert: fs.readFileSync('./certs/cert.pem')
|
||||
}
|
||||
|
||||
/**
|
||||
* Create HTTP server.
|
||||
*/
|
||||
const server = https.createServer(httpsOptions, app);
|
||||
|
||||
/**
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
server.listen(port);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
|
||||
/**
|
||||
* Normalize a port into a number, string, or false.
|
||||
*/
|
||||
function normalizePort(val) {
|
||||
const port = parseInt(val, 10);
|
||||
|
||||
if (isNaN(port)) {
|
||||
// named pipe
|
||||
return val;
|
||||
}
|
||||
|
||||
if (port >= 0) {
|
||||
// port number
|
||||
return port;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "error" event.
|
||||
*/
|
||||
function onError(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
const bind = typeof port === 'string'
|
||||
? 'Pipe ' + port
|
||||
: 'Port ' + port;
|
||||
|
||||
// handle specific listen errors with friendly messages
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(bind + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error(bind + ' is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "listening" event.
|
||||
*/
|
||||
function onListening() {
|
||||
const addr = server.address();
|
||||
const bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + addr.port;
|
||||
debug('Listening on ' + bind);
|
||||
}
|
||||
@@ -3,20 +3,16 @@ 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'), function(req, res, next) {
|
||||
if(req.user) {
|
||||
res.json(req.user);
|
||||
} else {
|
||||
res.statusCode = 403;
|
||||
}
|
||||
});
|
||||
|
||||
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;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
/* GET home page. */
|
||||
router.get('/', function(req, res, next) {
|
||||
res.render('index', { user: req.user });
|
||||
res.json({ user: req.user });
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -4,11 +4,8 @@ const db = require('../db');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.get('/new', function(req, res, next) {
|
||||
res.render('signup');
|
||||
});
|
||||
|
||||
router.post('/', function(req, res, next) {
|
||||
console.log("REQ: ", req.body)
|
||||
const salt = crypto.randomBytes(16);
|
||||
crypto.pbkdf2(req.body.password, salt, 10000, 32, 'sha256', function(err, hashedPassword) {
|
||||
if (err) { return next(err); }
|
||||
@@ -28,7 +25,6 @@ router.post('/', function(req, res, next) {
|
||||
};
|
||||
req.login(user, function(err) {
|
||||
if (err) { return next(err); }
|
||||
res.redirect('/');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
<template>
|
||||
<v-form v-model="valid">
|
||||
<v-container>
|
||||
<v-col cols="12" class="mb-4">
|
||||
<v-col
|
||||
cols="12"
|
||||
class="mb-4"
|
||||
>
|
||||
<h1 class="display-2 font-weight-bold mb-3">
|
||||
Login
|
||||
</h1>
|
||||
@@ -31,6 +34,13 @@
|
||||
required
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<v-btn
|
||||
class="mx-3 mb-5"
|
||||
@click="login"
|
||||
>
|
||||
Login
|
||||
</v-btn>
|
||||
</v-container>
|
||||
</v-form>
|
||||
</template>
|
||||
@@ -47,6 +57,22 @@ export default {
|
||||
passwordRules: [
|
||||
v => !!v || 'Password is required'
|
||||
]
|
||||
})
|
||||
}),
|
||||
methods: {
|
||||
login () {
|
||||
this.$http.post('https://localhost:3000/login/password', {
|
||||
username: this.username,
|
||||
password: this.password
|
||||
})
|
||||
.then(response => {
|
||||
if (response.status === 200) {
|
||||
this.$router.push('/')
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.error(error.response)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
89
src/components/Register.vue
Normal file
89
src/components/Register.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<v-form v-model="valid">
|
||||
<v-container>
|
||||
<v-col
|
||||
cols="12"
|
||||
class="mb-4"
|
||||
>
|
||||
<h1 class="display-2 font-weight-bold mb-3">
|
||||
Register
|
||||
</h1>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
cols="12"
|
||||
md="4"
|
||||
>
|
||||
<v-text-field
|
||||
v-model="name"
|
||||
:rules="[rules.required]"
|
||||
label="Name"
|
||||
required
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
cols="12"
|
||||
md="4"
|
||||
>
|
||||
<v-text-field
|
||||
v-model="username"
|
||||
:rules="[rules.required]"
|
||||
label="Username"
|
||||
required
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
cols="12"
|
||||
md="4"
|
||||
>
|
||||
<v-text-field
|
||||
v-model="password"
|
||||
type="password"
|
||||
:rules="[rules.required]"
|
||||
label="Password"
|
||||
required
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<v-btn
|
||||
class="mx-3 mb-5"
|
||||
@click="register"
|
||||
>
|
||||
Register
|
||||
</v-btn>
|
||||
</v-container>
|
||||
</v-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data: () => ({
|
||||
valid: false,
|
||||
name: '',
|
||||
username: '',
|
||||
password: '',
|
||||
rules: {
|
||||
required: v => !!v || 'Required'
|
||||
}
|
||||
}),
|
||||
methods: {
|
||||
register () {
|
||||
this.$http.post('https://localhost:3000/users', {
|
||||
name: this.name,
|
||||
username: this.username,
|
||||
password: this.password
|
||||
})
|
||||
.then(response => {
|
||||
if (response.status === 200) {
|
||||
this.$router.push('/')
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.error(error.response)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -2,6 +2,9 @@ import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import vuetify from './plugins/vuetify'
|
||||
import Axios from 'axios'
|
||||
|
||||
Vue.prototype.$http = Axios
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
|
||||
@@ -17,6 +17,14 @@ const routes = [
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import(/* webpackChunkName: "about" */ '../views/Signin.vue')
|
||||
},
|
||||
{
|
||||
path: '/register',
|
||||
name: 'Signup',
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import(/* webpackChunkName: "about" */ '../views/Signup.vue')
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
15
src/views/Signup.vue
Normal file
15
src/views/Signup.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<Register />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Register from '../components/Register'
|
||||
|
||||
export default {
|
||||
name: 'Signup',
|
||||
|
||||
components: {
|
||||
Register
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user