diff --git a/static/js/api.js b/static/js/api.js index 124a581b..a71d0b1f 100644 --- a/static/js/api.js +++ b/static/js/api.js @@ -2,11 +2,14 @@ const request = require('superagent'); const config = require('./config.js'); +const EventListener = require('./event_listener.js'); class Api { constructor() { + this.user = null; this.userName = null; this.userPassword = null; + this.authenticated = new EventListener(); } get(url) { @@ -36,9 +39,25 @@ class Api { }); } - hasPrivilege() { - /* TODO: implement */ - return true; + hasPrivilege(lookup) { + let minViableRank = null; + 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) { @@ -46,10 +65,14 @@ class Api { this.userName = userName; this.userPassword = userPassword; this.get('/user/' + userName) - .then(() => { resolve(); }) - .catch(response => { + .then(response => { + this.user = response.user; + resolve(); + this.authenticated.fire(); + }).catch(response => { reject(response.description); this.logout(); + this.authenticated.fire(); }); }); } @@ -57,6 +80,7 @@ class Api { logout() { this.userName = null; this.userPassword = null; + this.authenticated.fire(); } isLoggedIn() { diff --git a/static/js/controllers/auth_controller.js b/static/js/controllers/auth_controller.js index 75291360..5c513f14 100644 --- a/static/js/controllers/auth_controller.js +++ b/static/js/controllers/auth_controller.js @@ -36,7 +36,7 @@ class AuthController { options); resolve(); page('/'); - /* TODO: notify top navigation */ + /* TODO: notify about login */ }).catch(errorMessage => { reject(errorMessage); }); }); }}); @@ -46,7 +46,7 @@ class AuthController { this.api.logout(); cookies.remove('auth'); page('/'); - /* TODO: notify top navigation */ + /* TODO: notify about logout */ } } diff --git a/static/js/controllers/top_navigation_controller.js b/static/js/controllers/top_navigation_controller.js index 2db30916..5784718d 100644 --- a/static/js/controllers/top_navigation_controller.js +++ b/static/js/controllers/top_navigation_controller.js @@ -12,6 +12,7 @@ class TopNavigationController { constructor(topNavigationView, api) { this.api = api; this.topNavigationView = topNavigationView; + this.activeItem = null; this.items = { 'home': new NavigationItem('Home', '/'), @@ -27,9 +28,15 @@ class TopNavigationController { '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() { @@ -40,7 +47,7 @@ class TopNavigationController { if (!this.api.hasPrivilege('posts:list')) { this.items.posts.available = false; } - if (!this.api.hasPrivilege('posts:upload')) { + if (!this.api.hasPrivilege('posts:create')) { this.items.upload.available = false; } if (!this.api.hasPrivilege('comments:list')) { @@ -62,7 +69,8 @@ class TopNavigationController { } activate(itemName) { - this.topNavigationView.activate(itemName); + this.activeItem = itemName; + this.topNavigationView.activate(this.activeItem); } } diff --git a/static/js/event_listener.js b/static/js/event_listener.js new file mode 100644 index 00000000..e7eebffb --- /dev/null +++ b/static/js/event_listener.js @@ -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; diff --git a/szurubooru/api/users.py b/szurubooru/api/users.py index a684e6e6..ead769b8 100644 --- a/szurubooru/api/users.py +++ b/szurubooru/api/users.py @@ -73,7 +73,7 @@ class UserDetailApi(object): self._auth_service.verify_privilege(request.context.user, 'users:view') session = request.context.session 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): ''' Updates an existing user. '''