1
0
mirror of https://github.com/Foltik/Shimapan synced 2024-09-21 11:11:22 -04:00
shimapan/app/routes/auth.js

123 lines
3.8 KiB
JavaScript
Raw Normal View History

2018-07-25 01:45:05 -04:00
'use strict';
2017-10-11 10:15:19 -04:00
2018-07-25 01:45:05 -04:00
const express = require('express');
const router = express.Router();
const User = require('../models/User.js');
const Invite = require('../models/Invite.js');
const passport = require('passport');
const config = require('config');
2018-07-25 18:45:38 -04:00
const canonicalizeRequest = require('../util/canonicalize').canonicalizeRequest;
const requireAuth = require('../util/requireAuth').requireAuth;
const wrap = require('../util/wrap.js').wrap;
2018-07-25 01:45:05 -04:00
2018-07-25 18:45:38 -04:00
// Wraps passport.authenticate to return a promise
function authenticate(req, res, next) {
return new Promise((resolve) => {
passport.authenticate('local', (err, user) => {
resolve(user);
})(req, res, next);
});
}
2018-07-25 01:45:05 -04:00
2018-07-25 18:45:38 -04:00
// Wraps passport session creation for async usage
function login(user, req) {
return new Promise((resolve) => {
req.login(user, resolve);
});
}
2018-07-25 01:45:05 -04:00
// Check if a canonical name is valid
async function validateUsername(username, canonicalName, sanitize) {
if (canonicalName.length > config.get('User.Username.maxLength'))
2018-07-25 01:45:05 -04:00
return {valid: false, message: 'Username too long.'};
const restrictedRegex = new RegExp(config.get('User.Username.restrictedChars'), 'g');
if (canonicalName !== sanitize(canonicalName).replace(restrictedRegex, ''))
2018-07-25 01:45:05 -04:00
return {valid: false, message: 'Username contains invalid characters.'};
const count = await User.countDocuments({canonicalname: canonicalName});
if (count !== 0)
return {valid: false, message: 'Username in use.'};
return {valid: true};
2017-10-12 12:50:02 -04:00
}
2018-07-25 01:45:05 -04:00
// Query the database for a valid invite code. An error message property is set if invalid.
async function validateInvite(code) {
const invite = await Invite.findOne({code: code});
if (!invite)
return {valid: false, message: 'Invalid invite code.'};
if (invite.used)
return {valid: false, message: 'Invite already used.'};
if (invite.exp < Date.now())
return {valid: false, message: 'Invite expired.'};
return {valid: true, invite: invite};
2017-10-11 12:55:46 -04:00
}
2018-07-25 01:45:05 -04:00
router.post('/register', canonicalizeRequest, wrap(async (req, res, next) => {
2018-07-25 01:45:05 -04:00
// Validate the invite and username
2018-07-25 18:45:38 -04:00
const [inviteStatus, usernameStatus] =
await Promise.all([
validateInvite(req.body.invite),
validateUsername(req.body.username, req.body.canonicalname, req.sanitize)
]);
2018-07-25 01:45:05 -04:00
2018-07-25 18:45:38 -04:00
// Error if validation failed
2018-07-25 01:45:05 -04:00
if (!inviteStatus.valid)
return res.status(422).json({'message': inviteStatus.message});
if (!usernameStatus.valid)
return res.status(422).json({'message': usernameStatus.message});
2018-07-25 18:45:38 -04:00
// Update the database
await Promise.all([
User.register({
username: req.body.username,
canonicalname: req.body.canonicalname,
scope: inviteStatus.invite.scope,
date: Date.now()
}, req.body.password),
Invite.updateOne({code: inviteStatus.invite.code}, {recipient: req.body.canonicalname, used: Date.now()})
]);
2018-07-25 01:45:05 -04:00
res.status(200).json({'message': 'Registration successful.'});
}));
2017-10-11 10:15:19 -04:00
router.post('/login', canonicalizeRequest, wrap(async (req, res, next) => {
2018-07-25 18:45:38 -04:00
// Authenticate
const user = await authenticate(req, res, next);
if (!user)
return res.status(401).json({'message': 'Unauthorized.'});
// Create session
await login(user, req);
// Set session vars
req.session.passport.display = user.username;
2018-07-25 18:45:38 -04:00
req.session.passport.scope = user.scope;
res.status(200).json({'message': 'Logged in.'});
}));
2017-10-11 10:15:19 -04:00
router.post('/logout', function (req, res) {
2017-10-18 13:31:08 -04:00
req.logout();
res.status(200).json({'message': 'Logged out.'});
2017-10-14 17:49:11 -04:00
});
router.get('/whoami', requireAuth(), (req, res) => {
2018-07-25 18:45:38 -04:00
res.status(200).json({
user: req.authUser,
display: req.authDisplay,
scope: req.authScope,
key: req.authKey
2018-07-25 18:45:38 -04:00
});
2017-10-18 13:31:08 -04:00
});
2017-10-11 10:15:19 -04:00
module.exports = router;