Skip to content
Snippets Groups Projects
Commit 9a143ffb authored by Alexander Olofsson's avatar Alexander Olofsson
Browse files

Working on some per-user limits

parent 365339df
No related branches found
No related tags found
No related merge requests found
...@@ -28,11 +28,11 @@ ...@@ -28,11 +28,11 @@
<h4>Add external users</h4> <h4>Add external users</h4>
<p>Employees and students are allowed to create external users for collaboration with actors outside of Linköpings University.<br/> <p>Employees and students are allowed to create external users for collaboration with actors outside of Linköpings University.<br/>
This application will track and allow creation of such external users, up to a number configurable by the administrators.<br/></p> This application will track and allow creation of such external users, up to a number configurable by the administrators.<br/></p>
<button class="btn btn-success" @click="showCreationForm = !showCreationForm">New External User</button> <button class="btn btn-success" :disabled="external.length >= user.user_limit" @click="showCreationForm = !showCreationForm">New External User</button>
</div> </div>
</transition> </transition>
<h2 class="mt-4 mb-3">Existing external users:</h2> <h2 class="mt-4 mb-3">Existing external users: ({{ external.length }}/{{ user.user_limit }})</h2>
<hr/> <hr/>
<transition name="fade" mode="out-in"> <transition name="fade" mode="out-in">
<ul class="list-unstyled" is="transition-group" name="flip-list" v-if="external"> <ul class="list-unstyled" is="transition-group" name="flip-list" v-if="external">
......
...@@ -3,12 +3,13 @@ ...@@ -3,12 +3,13 @@
<img v-bind:src="user.avatar_url" class="d-flex align-self-center mr-3 rounded-circle user-avatar" alt="Avatar"/> <img v-bind:src="user.avatar_url" class="d-flex align-self-center mr-3 rounded-circle user-avatar" alt="Avatar"/>
<div class="media-body"> <div class="media-body">
<h4 class="mt-0">{{ user.name }}</h4> <h4 class="mt-0">{{ user.name }}</h4>
<p class="text-muted"><a v-bind:href="user.web_url">@{{ user.username }}</a> - Created at {{ user.created_at | readable_date }}</p> <p class="text-muted"><a v-bind:href="user.web_url">@{{ user.username }}</a> - {{ user.state }} - Created at {{ user.created_at | readable_date }}</p>
<!-- Read if current user is an admin, show advanced features --> <!-- Read if current user is an admin, show advanced features -->
<template v-if="false"> <template v-if="false">
<a href="#" @click.prevent="user.http.fetch()" class="btn btn-sm btn-primary" title="Reload User Data"><i class="fa fa-cog"></i></a> <a href="#" @click.prevent="user.http.fetch()" class="btn btn-sm btn-outline-primary" title="Reload User Data"><i class="fa fa-cog"></i></a>
<a href="#" @click.prevent="user.http.destroy()" class="btn btn-sm btn-danger" title="Remove User"><i class="fa fa-eraser"></i></a> <a href="#" @click.prevent="user.state == 'blocked' ? user.http.unblock() : user.http.block()" class="btn btn-sm btn-outline-warning" :title="user.state == 'blocked' ? 'Unblock' : 'Block'"><i class="fa" :class="{ 'fa-lock': user.state != 'blocked', 'fa-unlock': user.state == 'blocked' }"></i></a>
<a href="#" @click.prevent="user.http.destroy()" class="btn btn-sm btn-outline-danger" title="Remove User"><i class="fa fa-eraser"></i></a>
</template> </template>
</div> </div>
</li> </li>
......
...@@ -35,6 +35,18 @@ var User = module.exports = { ...@@ -35,6 +35,18 @@ var User = module.exports = {
} }
}, },
update: false, update: false,
block: {
method: 'POST',
route: '{id}/block',
apply: true,
data: false,
},
unblock: {
method: 'POST',
route: '{id}/unblock',
apply: true,
data: false,
}
} }
}, },
}; };
...@@ -40,7 +40,7 @@ router.get('/', (req, res) => { ...@@ -40,7 +40,7 @@ router.get('/', (req, res) => {
console.log('GET: /auth'); console.log('GET: /auth');
if (req.user) { if (req.user) {
res.send(req.user._json); res.send(Object.assign({}, req.user._json, { user_limit: config.external_limit }));
} else { } else {
res.status(401).send({ message: 'Not authenticated' }); res.status(401).send({ message: 'Not authenticated' });
} }
......
...@@ -16,7 +16,7 @@ CREATE TABLE IF NOT EXISTS external_users ( ...@@ -16,7 +16,7 @@ CREATE TABLE IF NOT EXISTS external_users (
user_id INTEGER NOT NULL, user_id INTEGER NOT NULL,
owner_id INTEGER NOT NULL, owner_id INTEGER NOT NULL,
username VARCHAR(256) NOT NULL, username VARCHAR(256) NOT NULL,
active BOOLEAN DEFAULT TRUE, state VARCHAR(16) DEFAULT 'active',
created_at TIMESTAMP DEFAULT NOW(), created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW() updated_at TIMESTAMP DEFAULT NOW()
); );
......
...@@ -13,6 +13,26 @@ const axios = require('axios').create({ ...@@ -13,6 +13,26 @@ const axios = require('axios').create({
} }
}); });
router.get('/audit', async (req, res) => {
console.log('GET: /users/audit');
try {
const queryText = 'SELECT * FROM audit_events WHERE user_id = $1';
console.log('> DB Query:');
console.log(queryText);
const dbResponse = await db.query(queryText, [req.user.id]);
console.log('> DB Response:');
console.log(dbResponse);
var rows = dbResponse.rows;
res.send(rows);
} catch(err) {
console.log("> DB Error:");
console.log(err);
return res.status(500).send({ 'message': "Database error occured" });
}
});
router.get('/', async (req, res) => { router.get('/', async (req, res) => {
console.log('GET: /users'); console.log('GET: /users');
...@@ -25,7 +45,7 @@ router.get('/', async (req, res) => { ...@@ -25,7 +45,7 @@ router.get('/', async (req, res) => {
console.log(dbResponse); console.log(dbResponse);
var rows = dbResponse.rows; var rows = dbResponse.rows;
res.send(rows.map((row) => row.id)); res.send(rows.map((row) => row.user_id));
} catch(err) { } catch(err) {
console.log("> DB Error:"); console.log("> DB Error:");
console.log(err); console.log(err);
...@@ -40,6 +60,22 @@ router.post('/', async (req, res) => { ...@@ -40,6 +60,22 @@ router.post('/', async (req, res) => {
.filter( key => !['admin', 'skip_confirmation'].includes(key) ) .filter( key => !['admin', 'skip_confirmation'].includes(key) )
.reduce( (rs, key) => (rs[key] = req.body[key], rs), {} ); .reduce( (rs, key) => (rs[key] = req.body[key], rs), {} );
try {
const queryText = 'SELECT * FROM external_users WHERE owner_id = $1';
console.log('> DB Query:');
console.log(queryText);
const dbResponse = await db.query(queryText, [req.user.id]);
console.log('> DB Response:');
console.log(dbResponse);
if (dbResponse.rowCount >= config.external_limit) {
return res.status(400).send({ 'message': 'External user limit reached' });
}
} catch(err) {
console.log("> DB Error:");
console.log(err);
return res.status(500).send({ 'message': "Database error occured" });
}
// TODO: Apply further validation on input // TODO: Apply further validation on input
// XXX Make sure user is allowed to create // XXX Make sure user is allowed to create
...@@ -71,7 +107,7 @@ router.post('/', async (req, res) => { ...@@ -71,7 +107,7 @@ router.post('/', async (req, res) => {
const queryText = 'INSERT INTO audit_events(event, user_id, message) VALUES($1, $2, $3)'; const queryText = 'INSERT INTO audit_events(event, user_id, message) VALUES($1, $2, $3)';
console.log('> DB Query:'); console.log('> DB Query:');
console.log(queryText); console.log(queryText);
const auditresp = await db.query(queryText, ['user.create', req.user.id, `Created account: ${dbResponse.name} <${dbResponse.email}>, username: ${dbResponse.username}`]); const auditresp = await db.query(queryText, ['user.create', req.user.id, `Created account: ${data.name} <${data.email}>, username: ${data.username}`]);
console.log('> DB Response:'); console.log('> DB Response:');
console.log(auditresp); console.log(auditresp);
} catch(err) { } catch(err) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment