102 lines
2.9 KiB
TypeScript
102 lines
2.9 KiB
TypeScript
import basicAuth from 'basic-auth';
|
|
import bcrypt from 'bcryptjs';
|
|
import UserModel from '../models/user';
|
|
|
|
|
|
// appends req.auth(res, ['levels'], method = 'all')
|
|
// which returns sends error message and returns false if unauthorized, otherwise true
|
|
// req.authDetails returns eg. {methods: ['basic'], username: 'johndoe', level: 'write'}
|
|
|
|
module.exports = async (req, res, next) => {
|
|
let givenMethod = ''; // authorization method given by client, basic taken preferred
|
|
let user = {name: '', level: '', id: '', location: ''}; // user object
|
|
|
|
// test authentications
|
|
const userBasic = await basic(req, next);
|
|
|
|
if (userBasic) { // basic available
|
|
givenMethod = 'basic';
|
|
user = userBasic;
|
|
}
|
|
else { // if basic not available, test key
|
|
const userKey = await key(req, next);
|
|
if (userKey) {
|
|
givenMethod = 'key';
|
|
user = userKey;
|
|
}
|
|
}
|
|
|
|
req.auth = (res, levels, method = 'all') => {
|
|
if (givenMethod === method || (method === 'all' && givenMethod !== '')) { // method is available
|
|
if (levels.indexOf(user.level) > -1) { // level is available
|
|
return true;
|
|
}
|
|
else {
|
|
res.status(403).json({status: 'Forbidden'});
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
res.status(401).json({status: 'Unauthorized'});
|
|
return false;
|
|
}
|
|
}
|
|
|
|
req.authDetails = {
|
|
method: givenMethod,
|
|
username: user.name,
|
|
level: user.level,
|
|
id: user.id,
|
|
location: user.location
|
|
};
|
|
|
|
next();
|
|
}
|
|
|
|
|
|
function basic (req, next): any { // checks basic auth and returns changed user object
|
|
return new Promise(resolve => {
|
|
const auth = basicAuth(req);
|
|
if (auth !== undefined) { // basic auth available
|
|
UserModel.find({name: auth.name}).lean().exec( (err, data: any) => { // find user
|
|
if (err) return next(err);
|
|
if (data.length === 1) { // one user found
|
|
bcrypt.compare(auth.pass, data[0].pass, (err, res) => { // check password
|
|
if (err) return next(err);
|
|
if (res === true) { // password correct
|
|
resolve({level: data[0].level, name: data[0].name, id: data[0]._id.toString(), location: data[0].location});
|
|
}
|
|
else {
|
|
resolve(null);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
resolve(null);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
resolve(null);
|
|
}
|
|
});
|
|
}
|
|
|
|
function key (req, next): any { // checks API key and returns changed user object
|
|
return new Promise(resolve => {
|
|
if (req.query.key !== undefined) { // key available
|
|
UserModel.find({key: req.query.key}).lean().exec( (err, data: any) => { // find user
|
|
if (err) return next(err);
|
|
if (data.length === 1) { // one user found
|
|
resolve({level: data[0].level, name: data[0].name, id: data[0]._id.toString(), location: data[0].location});
|
|
}
|
|
else {
|
|
resolve(null);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
resolve(null);
|
|
}
|
|
});
|
|
} |