front/auth: implement privileges + top nav auth

This commit is contained in:
rr- 2016-03-30 22:05:57 +02:00
parent 28c90a25f3
commit d8f11d87e5
5 changed files with 68 additions and 12 deletions

View File

@ -2,11 +2,14 @@
const request = require('superagent'); const request = require('superagent');
const config = require('./config.js'); const config = require('./config.js');
const EventListener = require('./event_listener.js');
class Api { class Api {
constructor() { constructor() {
this.user = null;
this.userName = null; this.userName = null;
this.userPassword = null; this.userPassword = null;
this.authenticated = new EventListener();
} }
get(url) { get(url) {
@ -36,9 +39,25 @@ class Api {
}); });
} }
hasPrivilege() { hasPrivilege(lookup) {
/* TODO: implement */ let minViableRank = null;
return true; for (let privilege of Object.keys(config.privileges)) {
if (!privilege.startsWith(lookup)) {
continue;
}
const rankName = config.privileges[privilege];
const rankIndex = config.service.userRanks.indexOf(rankName);
if (minViableRank === null || rankIndex < minViableRank) {
minViableRank = rankIndex;
}
}
if (minViableRank === null) {
console.error('Bad privilege name: ' + lookup);
}
let myRank = this.user !== null ?
config.service.userRanks.indexOf(this.user.accessRank) :
0;
return myRank >= minViableRank;
} }
login(userName, userPassword) { login(userName, userPassword) {
@ -46,10 +65,14 @@ class Api {
this.userName = userName; this.userName = userName;
this.userPassword = userPassword; this.userPassword = userPassword;
this.get('/user/' + userName) this.get('/user/' + userName)
.then(() => { resolve(); }) .then(response => {
.catch(response => { this.user = response.user;
resolve();
this.authenticated.fire();
}).catch(response => {
reject(response.description); reject(response.description);
this.logout(); this.logout();
this.authenticated.fire();
}); });
}); });
} }
@ -57,6 +80,7 @@ class Api {
logout() { logout() {
this.userName = null; this.userName = null;
this.userPassword = null; this.userPassword = null;
this.authenticated.fire();
} }
isLoggedIn() { isLoggedIn() {

View File

@ -36,7 +36,7 @@ class AuthController {
options); options);
resolve(); resolve();
page('/'); page('/');
/* TODO: notify top navigation */ /* TODO: notify about login */
}).catch(errorMessage => { reject(errorMessage); }); }).catch(errorMessage => { reject(errorMessage); });
}); });
}}); }});
@ -46,7 +46,7 @@ class AuthController {
this.api.logout(); this.api.logout();
cookies.remove('auth'); cookies.remove('auth');
page('/'); page('/');
/* TODO: notify top navigation */ /* TODO: notify about logout */
} }
} }

View File

@ -12,6 +12,7 @@ class TopNavigationController {
constructor(topNavigationView, api) { constructor(topNavigationView, api) {
this.api = api; this.api = api;
this.topNavigationView = topNavigationView; this.topNavigationView = topNavigationView;
this.activeItem = null;
this.items = { this.items = {
'home': new NavigationItem('Home', '/'), 'home': new NavigationItem('Home', '/'),
@ -27,9 +28,15 @@ class TopNavigationController {
'help': new NavigationItem('Help', '/help'), 'help': new NavigationItem('Help', '/help'),
}; };
this.updateVisibility(); this.api.authenticated.listen(() => {
this.updateVisibility();
this.topNavigationView.render(this.items, this.activeItem);
this.topNavigationView.activate(this.activeItem);
});
this.topNavigationView.render(this.items); this.updateVisibility();
this.topNavigationView.render(this.items, this.activeItem);
this.topNavigationView.activate(this.activeItem);
} }
updateVisibility() { updateVisibility() {
@ -40,7 +47,7 @@ class TopNavigationController {
if (!this.api.hasPrivilege('posts:list')) { if (!this.api.hasPrivilege('posts:list')) {
this.items.posts.available = false; this.items.posts.available = false;
} }
if (!this.api.hasPrivilege('posts:upload')) { if (!this.api.hasPrivilege('posts:create')) {
this.items.upload.available = false; this.items.upload.available = false;
} }
if (!this.api.hasPrivilege('comments:list')) { if (!this.api.hasPrivilege('comments:list')) {
@ -62,7 +69,8 @@ class TopNavigationController {
} }
activate(itemName) { activate(itemName) {
this.topNavigationView.activate(itemName); this.activeItem = itemName;
this.topNavigationView.activate(this.activeItem);
} }
} }

View File

@ -0,0 +1,24 @@
class EventListener {
constructor() {
this.listeners = [];
}
listen(callback) {
this.listeners.push(callback);
}
unlisten(callback) {
const index = this.listeners.indexOf(callback);
if (index !== -1) {
this.listeners.splice(index, 1);
}
}
fire(data) {
for (let listener of this.listeners) {
listener(data);
}
}
}
module.exports = EventListener;

View File

@ -73,7 +73,7 @@ class UserDetailApi(object):
self._auth_service.verify_privilege(request.context.user, 'users:view') self._auth_service.verify_privilege(request.context.user, 'users:view')
session = request.context.session session = request.context.session
user = self._user_service.get_by_name(session, user_name) user = self._user_service.get_by_name(session, user_name)
request.context.result = _serialize_user(user) request.context.result = {'user': _serialize_user(user)}
def on_put(self, request, response, user_name): def on_put(self, request, response, user_name):
''' Updates an existing user. ''' ''' Updates an existing user. '''