From 013710c6b348e46723ccc4c2cb4f1c92b4abe4b9 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Fri, 25 Jan 2019 12:04:35 +0100 Subject: [PATCH] #981 Login bugs fixed, cookies disabled, session remember by default --- back/methods/account/validate-token.js | 20 ++------ back/models/account.json | 2 +- front/core/lib/index.js | 1 - front/core/{lib => services}/app.js | 12 ++--- front/core/services/auth.js | 66 ++++++++++++++------------ front/core/services/index.js | 2 + front/core/services/token.js | 21 +------- front/salix/components/app/app.html | 4 +- front/salix/components/app/app.js | 41 ++++++++++++---- front/salix/components/login/login.js | 15 +++--- loopback/server/application.json | 4 -- loopback/server/server.js | 5 -- 12 files changed, 92 insertions(+), 101 deletions(-) rename front/core/{lib => services}/app.js (73%) delete mode 100644 loopback/server/application.json diff --git a/back/methods/account/validate-token.js b/back/methods/account/validate-token.js index f1264855d..7bccfe0b1 100644 --- a/back/methods/account/validate-token.js +++ b/back/methods/account/validate-token.js @@ -1,14 +1,6 @@ module.exports = Self => { Self.remoteMethod('validateToken', { - description: 'Get the user information and permissions', - accepts: [ - { - arg: 'token', - type: 'String', - description: 'The token to validate', - required: true - } - ], + description: 'Validates the current logged user token', returns: { type: 'Boolean', root: true @@ -19,13 +11,7 @@ module.exports = Self => { } }); - Self.validateToken = function(tokenId, cb) { - Self.app.models.AccessToken.findById(tokenId, (err, token) => { - if (err) return cb(err); - if (token) - token.validate((_, isValid) => cb(null, isValid === true)); - else - cb(null, false); - }); + Self.validateToken = async function() { + return true; }; }; diff --git a/back/models/account.json b/back/models/account.json index 5e1398587..1ec9d789f 100644 --- a/back/models/account.json +++ b/back/models/account.json @@ -52,7 +52,7 @@ "property": "validateToken", "accessType": "EXECUTE", "principalType": "ROLE", - "principalId": "$everyone", + "principalId": "$authenticated", "permission": "ALLOW" } ] diff --git a/front/core/lib/index.js b/front/core/lib/index.js index a50603d4c..e7f610e57 100644 --- a/front/core/lib/index.js +++ b/front/core/lib/index.js @@ -1,6 +1,5 @@ import './module-loader'; import './crud'; -import './app'; import './acl-service'; import './storage-services'; import './template'; diff --git a/front/core/lib/app.js b/front/core/services/app.js similarity index 73% rename from front/core/lib/app.js rename to front/core/services/app.js index ac744be9d..6b2cd1d2a 100644 --- a/front/core/lib/app.js +++ b/front/core/services/app.js @@ -13,18 +13,18 @@ export default class App { } showMessage(message) { - if (this.snackbar) - this.snackbar.show({message: message}); + if (this.logger) + this.logger.showMessage(message); } showSuccess(message) { - if (this.snackbar) - this.snackbar.showSuccess({message: message}); + if (this.logger) + this.logger.showSuccess(message); } showError(message) { - if (this.snackbar) - this.snackbar.showError({message: message}); + if (this.logger) + this.logger.showError(message); } pushLoader() { diff --git a/front/core/services/auth.js b/front/core/services/auth.js index f3e5d76ff..30b199c2c 100644 --- a/front/core/services/auth.js +++ b/front/core/services/auth.js @@ -16,29 +16,29 @@ export default class Auth { vnToken, vnModules, aclService, - token: null, - loggedIn: false, - dataLoaded: false + loggedIn: false }); } initialize() { - this.loggedIn = this.vnToken.token != null; - let criteria = { to: state => state.name != 'login' }; this.$transitions.onStart(criteria, transition => { - if (!this.loggedIn) { - let params = {continue: this.$window.location.hash}; - return transition.router.stateService.target('login', params); - } - if (!this.dataLoaded) { - this.resetData(); - this.dataLoaded = true; - return this.aclService.load(); - } + if (this.loggedIn) + return true; - return true; + let redirectToLogin = () => { + return transition.router.stateService.target('login', { + continue: this.$window.location.hash + }); + }; + + if (this.vnToken.token) { + return this.loadAcls() + .then(() => true) + .catch(redirectToLogin); + } else + return redirectToLogin(); }); } login(user, password, remember) { @@ -49,22 +49,21 @@ export default class Auth { user, password: password || undefined }; + return this.$http.post('/api/Accounts/login', params).then( json => this.onLoginOk(json, remember), - json => this.onLoginErr(json) - ); + json => this.onLoginErr(json)); } onLoginOk(json, remember) { - this.resetData(); this.vnToken.set(json.data.token, remember); - this.loggedIn = true; - let continueHash = this.$state.params.continue; - - if (continueHash) - this.$window.location = continueHash; - else - this.$state.go('home'); + return this.loadAcls().then(() => { + let continueHash = this.$state.params.continue; + if (continueHash) + this.$window.location = continueHash; + else + this.$state.go('home'); + }); } onLoginErr(json) { let message; @@ -89,15 +88,22 @@ export default class Auth { this.vnToken.unset(); this.loggedIn = false; - this.resetData(); + this.vnModules.reset(); + this.aclService.reset(); this.$state.go('login'); return promise; } - resetData() { - this.aclService.reset(); - this.vnModules.reset(); - this.dataLoaded = false; + loadAcls() { + return this.aclService.load() + .then(() => { + this.loggedIn = true; + this.vnModules.reset(); + }) + .catch(err => { + this.vnToken.unset(); + throw err; + }); } } Auth.$inject = ['$http', '$state', '$transitions', '$window', 'vnToken', 'vnModules', 'aclService']; diff --git a/front/core/services/index.js b/front/core/services/index.js index f9ca51b3f..6cffd4501 100644 --- a/front/core/services/index.js +++ b/front/core/services/index.js @@ -1,3 +1,5 @@ + +import './app'; import './auth'; import './token'; import './modules'; diff --git a/front/core/services/token.js b/front/core/services/token.js index 15585a5fc..126fbb604 100644 --- a/front/core/services/token.js +++ b/front/core/services/token.js @@ -6,17 +6,12 @@ import ngModule from '../module'; * @property {String} token The current login token or %null */ export default class Token { - constructor($cookies) { - this.$cookies = $cookies; - + constructor() { try { this.token = sessionStorage.getItem('vnToken'); if (!this.token) this.token = localStorage.getItem('vnToken'); } catch (e) {} - - if (!this.token) - this.token = this.$cookies.get('vnToken'); } set(value, remember) { this.unset(); @@ -25,27 +20,15 @@ export default class Token { localStorage.setItem('vnToken', value); else sessionStorage.setItem('vnToken', value); - } catch (e) { - let options = {}; + } catch (e) {} - if (location.protocol == 'https:') - options.secure = true; - if (remember) { - let now = new Date().getTime(); - options.expires = new Date(now + 7 * 86400000); - } - - this.$cookies.put('vnToken', value, options); - } this.token = value; } unset() { localStorage.removeItem('vnToken'); sessionStorage.removeItem('vnToken'); - this.$cookies.remove('vnToken'); this.token = null; } } -Token.$inject = ['$cookies']; ngModule.service('vnToken', Token); diff --git a/front/salix/components/app/app.html b/front/salix/components/app/app.html index fe9c45937..1e6ca04d4 100644 --- a/front/salix/components/app/app.html +++ b/front/salix/components/app/app.html @@ -1,4 +1,4 @@ - + @@ -12,7 +12,7 @@
+ ng-class="{'padding': $ctrl.showTopbar}">
{ if (this.menuShown) this.hideMenu(); }); } + $postLink() { - this.background = this.$element[0].querySelector('.background'); - this.vnApp.snackbar = this.$.snackbar; + this.vnApp.logger = this; } - // TODO: Temporary fix to hide the topbar when login is displayed - get inApp() { + + $onDestroy() { + this.vnApp.logger = null; + } + + get showTopbar() { let state = this.$state.current.name; return state && state != 'login'; } + get leftBlock() { return this.$element[0].querySelector('.left-block'); } + showMenu() { let leftBlock = this.leftBlock; if (!leftBlock) return; leftBlock.classList.add('shown'); this.menuShown = true; } + hideMenu() { this.menuShown = false; let leftBlock = this.leftBlock; if (!leftBlock) return; leftBlock.classList.remove('shown'); } + + showMessage(message) { + this.$.snackbar.show({message: message}); + } + + showSuccess(message) { + this.$.snackbar.showSuccess({message: message}); + } + + showError(message) { + this.$.snackbar.showError({message: message}); + } } -App.$inject = ['$element', '$scope', 'vnApp', '$state', '$transitions']; +App.$inject = ['$scope', '$element', 'vnApp', '$state', '$transitions']; ngModule.component('vnApp', { template: require('./app.html'), diff --git a/front/salix/components/login/login.js b/front/salix/components/login/login.js index 1b823e44d..49df6a701 100644 --- a/front/salix/components/login/login.js +++ b/front/salix/components/login/login.js @@ -5,11 +5,14 @@ import './style.scss'; * A simple login form. */ export default class Controller { - constructor($element, $scope, vnAuth) { - this.$element = $element; - this.$ = $scope; - this.vnAuth = vnAuth; - this.user = localStorage.getItem('lastUser'); + constructor($, $element, vnAuth) { + Object.assign(this, { + $, + $element, + vnAuth, + user: localStorage.getItem('lastUser'), + remember: true + }); } submit() { this.loading = true; @@ -30,7 +33,7 @@ export default class Controller { this.$.userField.focus(); } } -Controller.$inject = ['$element', '$scope', 'vnAuth']; +Controller.$inject = ['$scope', '$element', 'vnAuth']; ngModule.component('vnLogin', { template: require('./login.html'), diff --git a/loopback/server/application.json b/loopback/server/application.json deleted file mode 100644 index 8dfbe63d7..000000000 --- a/loopback/server/application.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "default": "/login", - "salix": "/login" -} \ No newline at end of file diff --git a/loopback/server/server.js b/loopback/server/server.js index 33c778b44..7ced048cf 100644 --- a/loopback/server/server.js +++ b/loopback/server/server.js @@ -36,11 +36,6 @@ let buildDir = `${appDir}/dist`; let servicesDir = `${appDir}/modules`; let modulesPath = `${appDir}/modules.yml`; -// TODO: It should be stored at some config file -app.set('api key', 'salix'); -app.set('url auth', '/auth'); -app.set('applications', require('./application.json')); - app.use(cookieParser()); // Internationalization