front/auth: implement privileges + top nav auth
This commit is contained in:
parent
28c90a25f3
commit
d8f11d87e5
|
@ -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() {
|
||||||
|
|
|
@ -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 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
@ -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. '''
|
||||||
|
|
Loading…
Reference in New Issue