Implemented authorisation checks and logout

This commit is contained in:
Mark van Renswoude 2018-04-26 15:39:21 +02:00
parent 0e10f38383
commit 9defe0746f
9 changed files with 130 additions and 19 deletions

View File

@ -2,9 +2,10 @@ const config = require('../../config');
const express = require('Express');
const asyncHandler = require('express-async-handler');
const jwt = require('jsonwebtoken');
const AuthTokens = require('../authtokens');
async function checkAuthorization(req, res, onVerified)
async function checkAuthorization(req, res, repository, onVerified)
{
if (!req.headers.authorization || req.headers.authorization.split(' ')[0] !== 'Bearer')
{
@ -24,7 +25,16 @@ async function checkAuthorization(req, res, onVerified)
}
if (decoded.userId)
await onVerified(decoded);
{
var user = await repository.users.getUser(decoded.userId);
if (user === null || !user.active)
{
res.sendStatus(403);
return;
}
else
await onVerified(user);
}
else
res.sendStatus(400);
}
@ -42,12 +52,26 @@ module.exports = (repository) =>
{
var router = express.Router();
router.get('/whoami', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, repository, async (user) =>
{
res.send({
userId: user.userId,
username: user.username,
auth: user.auth
});
});
}));
router.get('/codes', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, async (decoded) =>
await checkAuthorization(req, res, repository, async (user) =>
{
var codes = await repository.codes.getCodes(decoded.userId);
var usernames = await repository.users.getUsernames();
var codes = await repository.codes.getCodes(user.hasAuth(AuthTokens.ViewAllCodes) ? null : user.userId);
var usernames = await repository.users.getUserNames();
codes.forEach((item) =>
{
@ -61,10 +85,10 @@ module.exports = (repository) =>
router.get('/uploads', asyncHandler(async (req, res) =>
{
await checkAuthorization(req, res, async (decoded) =>
await checkAuthorization(req, res, repository, async (user) =>
{
var files = await repository.uploads.getUploads(decoded.userId);
var usernames = await repository.users.getUsernames();
var files = await repository.uploads.getUploads(user.hasAuth(AuthTokens.ViewAllUploads) ? null : user.userId);
var usernames = await repository.users.getUserNames();
files.forEach((item) =>
{

View File

@ -47,8 +47,7 @@ module.exports = (repository) =>
if (user !== null)
{
jwt.sign({
userId: user.id,
auth: user.auth
userId: user.id
}, config.jwtSecret, (err, token) =>
{
if (err)

View File

@ -1,5 +1,7 @@
const AuthTokens = {
ManageUsers: 'manageUsers'
ManageUsers: 'manageUsers',
ViewAllUploads: 'viewAllUploads',
ViewAllCodes: 'viewAllCodes'
}
var all = [];

View File

@ -10,6 +10,7 @@ class User
self.id = values.id || values._id || null;
self.username = values.username || null;
self.name = values.name || null;
self.password = values.password || null;
self.email = values.email || null;
self.auth = values.auth || [];
@ -25,6 +26,8 @@ class User
hasAuth(token)
{
var self = this;
return self.auth.includes(token);
}
}
@ -58,6 +61,7 @@ class UserRepository
{
self.addUser(new User({
username: 'admin',
name: 'Administrator',
password: 'changeme',
auth: AuthTokens.all
}))
@ -103,6 +107,32 @@ class UserRepository
}
getUser(userId)
{
var self = this;
return new Promise((resolve, reject) =>
{
self.store.findOne({ _id: userId }, (err, doc) =>
{
if (err)
{
reject(err);
return;
}
if (doc == null)
{
resolve(false);
return;
}
resolve(new User(doc));
});
});
}
addUser(user)
{
var self = this;
@ -119,6 +149,7 @@ class UserRepository
self.store.insert({
username: user.username,
name: user.name,
email: user.email,
hashedPassword: hash,
created: user.created,
@ -140,7 +171,7 @@ class UserRepository
}
getUsernames()
getUserNames()
{
var self = this;
@ -154,13 +185,13 @@ class UserRepository
return;
}
var usernames = {};
var userNames = {};
docs.forEach((dbUser) =>
{
usernames[dbUser._id] = dbUser.username
userNames[dbUser._id] = dbUser.name
});
resolve(usernames);
resolve(userNames);
});
});
}

View File

@ -24,6 +24,7 @@ export default {
admin: {
loading: 'Loading…',
empty: 'No data',
logout: 'Logout',
login: {
usernamePlaceholder: 'Username or e-mail address',

View File

@ -24,6 +24,7 @@ export default {
admin: {
loading: 'Bezig met laden…',
empty: 'Geen gegevens',
logout: 'Uitloggen',
login: {
usernamePlaceholder: 'Gebruikersnaam of e-mail adres',

View File

@ -5,7 +5,11 @@
<ul class="pure-menu-list">
<menu-link route="/admin/uploads" :title="$t('admin.menu.uploads')"></menu-link>
<menu-link route="/admin/codes" :title="$t('admin.menu.codes')"></menu-link>
<menu-link route="/admin/users" :title="$t('admin.menu.users')"></menu-link>
<menu-link route="/admin/users" :title="$t('admin.menu.users')" v-if="hasAuth('manageUsers')"></menu-link>
<li class="pure-menu-item right">
<a class="pure-menu-link" href="#" @click="logout">{{ $t('admin.logout') }}</a>
</li>
</ul>
</div>
</div>
@ -13,6 +17,8 @@
</template>
<script>
import shared from '../../shared';
var menuLink = {
props: ['route', 'title'],
template: '<router-link tag="li" :to="route" class="pure-menu-item" active-class="pure-menu-selected">' +
@ -30,6 +36,22 @@ export default {
components: {
'menu-link': menuLink
},
methods: {
hasAuth(token)
{
return shared.user.auth.indexOf(token) > -1;
},
logout()
{
var self = this;
shared.token = null;
self.$router.push('/admin');
}
}
}
</script>
@ -47,6 +69,11 @@ export default {
background-color: black;
.pure-menu-horizontal .pure-menu-list
{
width: 100%;
}
.pure-menu-link
{
color: white;
@ -64,5 +91,10 @@ export default {
background-color: #228dd4;
}
}
.right
{
float: right;
}
}
</style>

View File

@ -92,7 +92,6 @@ export default {
if (parts.length > 0)
ext = parts.pop();
console.log(ext);
return '/images/fileicons/32px/' + ext + '.png';
}
}

View File

@ -1,10 +1,13 @@
import Vue from 'vue';
import Cookies from 'js-cookie';
import axios from 'axios';
export default new Vue({
data() {
return {
token: null
token: null,
user: []
}
},
@ -20,7 +23,26 @@ export default new Vue({
watch: {
token(newValue)
{
Cookies.set('token', newValue);
var self = this;
if (newValue !== null)
{
Cookies.set('token', newValue);
axios.get('/admin/whoami', {
headers: {
Authorization: 'Bearer ' + self.token
}})
.then((response) =>
{
self.user = response.data;
});
}
else
{
Cookies.remove('token');
self.user = null;
}
}
}
});