1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-08-08 06:55:28 +02:00

Refactor login to use ember-simple-auth

This commit is contained in:
zinyando 2016-06-28 22:15:03 +02:00
parent 10dbeeefbb
commit cbac8d2d59
10 changed files with 196 additions and 281 deletions

View file

@ -0,0 +1,33 @@
import Ember from 'ember';
import Base from 'ember-simple-auth/authenticators/base';
import encodingUtil from '../utils/encoding';
import netUtil from '../utils/net';
import models from '../utils/model';
const {
isPresent
} = Ember;
export default Base.extend({
serverTokenEndpoint: `public/authenticate`,
ajax: Ember.inject.service(),
authenticate({password, email}) {
let domain = netUtil.getSubdomain();
if (!isPresent(password) || !isPresent(email)) {
return Ember.RSVP.reject("invalid");
}
var encoded = encodingUtil.Base64.encode(`${domain}:${email}:${password}`);
var headers = {
'Authorization': 'Basic ' + encoded
};
return this.get('ajax').post('public/authenticate', {
headers
});
}
});

View file

@ -13,6 +13,10 @@ import Ember from 'ember';
import NotifierMixin from '../../mixins/notifier'; import NotifierMixin from '../../mixins/notifier';
import TooltipMixin from '../../mixins/tooltip'; import TooltipMixin from '../../mixins/tooltip';
const {
computed
} = Ember;
export default Ember.Component.extend(NotifierMixin, TooltipMixin, { export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
documentService: Ember.inject.service('document'), documentService: Ember.inject.service('document'),
templateService: Ember.inject.service('template'), templateService: Ember.inject.service('template'),
@ -22,7 +26,7 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
busy: false, busy: false,
importedDocuments: [], importedDocuments: [],
savedTemplates: [], savedTemplates: [],
isFolderOwner: false, isFolderOwner: computed.equal('folder.userId', 'session.user.id'),
moveFolderId: "", moveFolderId: "",
didReceiveAttrs() { didReceiveAttrs() {

View file

@ -15,15 +15,16 @@ import netUtil from '../../utils/net';
export default Ember.Component.extend({ export default Ember.Component.extend({
folderService: Ember.inject.service('folder'), folderService: Ember.inject.service('folder'),
folder: null, folder: null,
appMeta: Ember.inject.service(),
didInitAttrs() { didInitAttrs() {
let self = this; if (this.get("session.authenticated")) {
if (this.session.authenticated) { this.get("session.user.accounts").forEach((account)=>{
this.session.user.accounts.forEach(function(account) { // TODO: do not mutate account.active here
account.active = account.orgId === self.session.appMeta.orgId; account.active = account.orgId === this.get("appMeta.orgId");
}); });
} }
}, },
didReceiveAttrs() { didReceiveAttrs() {
if (this.get('folder') === null) { if (this.get('folder') === null) {
@ -31,10 +32,10 @@ export default Ember.Component.extend({
} }
}, },
actions: { actions: {
switchAccount(domain) { switchAccount(domain) {
this.audit.record('switched-account'); this.audit.record('switched-account');
window.location.href = netUtil.getAppUrl(domain); window.location.href = netUtil.getAppUrl(domain);
} }
} }
}); });

View file

@ -4,6 +4,8 @@ export default Ember.Controller.extend({
email: "", email: "",
password: "", password: "",
invalidCredentials: false, invalidCredentials: false,
session: Ember.inject.service('session'),
audit: Ember.inject.service('audit'),
reset() { reset() {
this.setProperties({ this.setProperties({
@ -20,24 +22,13 @@ export default Ember.Controller.extend({
actions: { actions: {
login() { login() {
let self = this;
let creds = this.getProperties('email', 'password'); let creds = this.getProperties('email', 'password');
this.session.login(creds).then(function() { this.get('session').authenticate('authenticator:documize', creds)
self.set('invalidCredentials', false); .then((response) => {
self.audit.record("logged-in"); this.get('audit').record("logged-in");
return response;
var previousTransition = self.session.get('previousTransition'); });
if (previousTransition) {
previousTransition.retry();
self.session.set('previousTransition', null);
} else {
self.transitionToRoute('folders.folder');
}
}, function() {
self.set('invalidCredentials', true);
});
} }
} }
}); });

View file

@ -11,26 +11,28 @@
import Ember from 'ember'; import Ember from 'ember';
import netUtil from '../utils/net'; import netUtil from '../utils/net';
import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin';
const { const {
inject: { service } inject: { service }
} = Ember; } = Ember;
export default Ember.Route.extend({ export default Ember.Route.extend(ApplicationRouteMixin, {
userService: service('user'), userService: service('user'),
sessionService: service('session'), session: service('session'),
appMeta: service(), appMeta: service(),
transitioning: false, transitioning: false,
beforeModel: function(transition) { beforeModel: function(transition) {
let self = this; let self = this;
let session = this.get('sessionService'); let session = this.get('session');
let appMeta = this.get('appMeta');
// Session ready? // Session ready?
return this.get('appMeta').boot().then(function() { return this.get('appMeta').boot().then(function() {
// Need to authenticate? // Need to authenticate?
if (!session.get("appMeta.allowAnonymousAccess") && !session.get("authenticated") && if (!appMeta.get("allowAnonymousAccess") && !session.get("isAuthenticated") &&
is.not.startWith(transition.targetName, 'auth.')) { is.not.startWith(transition.targetName, 'auth.')) {
if (!self.transitioning) { if (!self.transitioning) {
session.set('previousTransition', transition); session.set('previousTransition', transition);

View file

@ -1,7 +1,25 @@
import AjaxService from 'ember-ajax/services/ajax'; import AjaxService from 'ember-ajax/services/ajax';
import config from '../config/environment'; import config from '../config/environment';
const {
computed,
inject: { service }
} = Ember;
export default AjaxService.extend({ export default AjaxService.extend({
session: service(),
host: config.apiHost, host: config.apiHost,
namespace: config.apiNamespace namespace: config.apiNamespace,
headers: Ember.computed('session.session.content.authenticated.token', {
get() {
let headers = {};
const token = this.get('session.session.content.authenticated.token');
if (token) {
headers['authorization'] = token;
}
return headers;
}
})
}); });

View file

@ -15,7 +15,7 @@ export default Ember.Service.extend({
title: '', title: '',
version: '', version: '',
message: '', message: '',
allowAnonymousAccess: false, allowAnonymousAccess: null,
boot() { boot() {
let dbhash; let dbhash;

View file

@ -13,6 +13,10 @@ import Ember from 'ember';
import models from '../utils/model'; import models from '../utils/model';
import BaseService from '../services/base'; import BaseService from '../services/base';
const {
get
} = Ember;
export default BaseService.extend({ export default BaseService.extend({
sessionService: Ember.inject.service('session'), sessionService: Ember.inject.service('session'),
ajax: Ember.inject.service(), ajax: Ember.inject.service(),
@ -155,10 +159,10 @@ export default BaseService.extend({
} }
this.set('currentFolder', folder); this.set('currentFolder', folder);
this.get('sessionService').storeSessionItem("folder", folder.get('id')); this.get('sessionService').storeSessionItem("folder", get(folder, 'id'));
this.set('canEditCurrentFolder', false); this.set('canEditCurrentFolder', false);
let userId = this.get('sessionService').user.get('id'); let userId = this.get('sessionService.user.id');
if (userId === "") { if (userId === "") {
userId = "0"; userId = "0";
} }
@ -194,7 +198,7 @@ export default BaseService.extend({
} }
}); });
Ember.run(() => { Ember.run(() => {
this.set('canEditCurrentFolder', canEdit && this.get('sessionService').authenticated); this.set('canEditCurrentFolder', canEdit && this.get('sessionService.authenticated'));
}); });
}); });
}, },

View file

@ -13,18 +13,31 @@ import Ember from 'ember';
import encodingUtil from '../utils/encoding'; import encodingUtil from '../utils/encoding';
import netUtil from '../utils/net'; import netUtil from '../utils/net';
import models from '../utils/model'; import models from '../utils/model';
import SimpleAuthSession from 'ember-simple-auth/services/session';
export default Ember.Service.extend({ const {
ready: false, inject: { service },
appMeta: null, computed: { oneWay }
isMac: false, } = Ember;
isMobile: false,
previousTransition: null, export default SimpleAuthSession.extend({
user: null, ajax: service(),
authenticated: false, appMeta: service(),
authenticated: oneWay('isAuthenticated'),
user: oneWay('session.content.authenticated.user'),
folderPermissions: null, folderPermissions: null,
currentFolder: null, currentFolder: null,
ajax: Ember.inject.service(),
authenticate() {
return this._super(...arguments)
.then(function({token, user}){
return {
token,
user: models.User.create(user)
};
});
},
isAdmin: function() { isAdmin: function() {
if (this.authenticated && is.not.null(this.user) && this.user.id !== "") { if (this.authenticated && is.not.null(this.user) && this.user.id !== "") {
@ -40,86 +53,8 @@ export default Ember.Service.extend({
return false; return false;
}.property('user'), }.property('user'),
// Boot up
init: function() {
this.set('user', models.UserModel.create());
this.appMeta = models.AppMeta.create();
this.set('isMac', is.mac());
this.set('isMobile', is.mobile());
},
// Authentication
login: function(credentials) {
let domain = netUtil.getSubdomain();
this.clearSession();
if (is.empty(credentials.email) || is.empty(credentials.password)) {
return Ember.RSVP.reject("invalid");
}
var encoded = encodingUtil.Base64.encode(domain + ":" + credentials.email + ":" + credentials.password);
var headers = {
'Authorization': 'Basic ' + encoded
};
return this.get('ajax').post('public/authenticate', {
headers
}).then((response)=>{
this.setSession(response.token, models.UserModel.create(response.user));
this.get('ready', true);
return response;
});
},
// SSO in the form of 'domain:email:password'
sso: function(credentials) {
this.clearSession();
if (is.empty(credentials.email) || is.empty(credentials.password)) {
return Ember.RSVP.reject("invalid");
}
var headers = {
'Authorization': 'Basic ' + credentials
};
return this.get('ajax').post('public/authenticate', {
headers
}).then((response)=>{
this.setSession(response.token, models.UserModel.create(response.user));
this.get('ready', true);
return response;
});
},
// Goodbye
logout: function() {
this.clearSession();
},
// Session management
setSession: function(token, user) {
this.set('user', user);
this.set('authenticated', true);
this.storeSessionItem('token', token);
this.storeSessionItem('user', JSON.stringify(user));
let self = this;
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
// We only tack on auth header for Documize API calls
if (is.startWith(options.url, self.get('appMeta.url'))) {
jqXHR.setRequestHeader('Authorization', 'Bearer ' + token);
}
});
},
clearSession: function() { clearSession: function() {
this.set('user', null); // TODO: clear session properly with ESA
this.set('authenticated', false);
localStorage.clear(); localStorage.clear();
}, },
@ -133,82 +68,5 @@ export default Ember.Service.extend({
clearSessionItem: function(key) { clearSessionItem: function(key) {
delete localStorage[key]; delete localStorage[key];
},
// Application boot process
boot() {
let token = this.getSessionItem('token');
// TODO: the rest should be done through ESA
if (is.not.undefined(token)) {
// We now validate current token
return this.get('ajax').request(`public/validate?token=${token}`, {
method: 'GET',
contentType: 'json'
}).then((user) => {
this.setSession(token, models.UserModel.create(user));
this.set('ready', true);
}).catch((reason) => {
if (netUtil.isAjaxAccessError(reason)) {
localStorage.clear();
window.location.href = "/auth/login";
}
});
}
let self = this;
let dbhash = "";
if (is.not.null(document.head.querySelector("[property=dbhash]"))) {
dbhash = document.head.querySelector("[property=dbhash]").content;
}
if (dbhash.length > 0 && dbhash !== "{{.DBhash}}") {
self.get('appMeta').set('orgId', "response.orgId");
self.get('appMeta').setSafe('title', "Documize Setup");
self.get('appMeta').set('version', "response.version");
self.get('appMeta').setSafe('message', "response.message");
self.get('appMeta').set('allowAnonymousAccess', false);
self.set('ready', true);
return new Ember.RSVP.Promise(function(resolve) {
resolve();
});
}
if (this.get('ready')) {
return new Ember.RSVP.Promise(function(resolve) {
resolve();
});
}
return this.get('ajax').request("public/meta")
.then((response) => {
this.get('appMeta').set('orgId', response.orgId);
this.get('appMeta').setSafe('title', response.title);
this.get('appMeta').set('version', response.version);
this.get('appMeta').setSafe('message', response.message);
this.get('appMeta').set('allowAnonymousAccess', response.allowAnonymousAccess);
let token = this.getSessionItem('token');
if (is.not.undefined(token)) {
// We now validate current token
let tokenCheckUrl = `public/validate?token=${token}`;
return this.get('ajax').request(tokenCheckUrl, {
method: 'GET',
contentType: 'json'
}).then((user) => {
this.setSession(token, models.UserModel.create(user));
this.set('ready', true);
}).catch((reason) => {
if (netUtil.isAjaxAccessError(reason)) {
localStorage.clear();
window.location.href = "/auth/login";
}
});
}
});
} }
}); });

View file

@ -13,83 +13,87 @@
module.exports = function(environment) { module.exports = function(environment) {
var ENV = { var ENV = {
modulePrefix: 'documize', modulePrefix: 'documize',
podModulePrefix: 'documize/pods', podModulePrefix: 'documize/pods',
locationType: 'auto', locationType: 'auto',
environment: environment, environment: environment,
baseURL: '/', baseURL: '/',
apiHost: '', apiHost: '',
apiNamespace: '', apiNamespace: '',
contentSecurityPolicyHeader: 'Content-Security-Policy-Report-Only', contentSecurityPolicyHeader: 'Content-Security-Policy-Report-Only',
EmberENV: { EmberENV: {
FEATURES: {} FEATURES: {}
}, },
"ember-cli-mirage": { "ember-cli-mirage": {
enabled: false enabled: false
}, },
APP: { 'ember-simple-auth': {
// Allows to disable audit service in tests authenticationRoute: 'auth.login',
auditEnabled: true, routeAfterAuthentication: 'folders.folder'
intercomKey: "" },
} APP: {
// Allows to disable audit service in tests
auditEnabled: true,
intercomKey: ""
}
};
if (environment === 'development') {
ENV.APP.LOG_TRANSITIONS = true;
ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
ENV['ember-cli-mirage'] = {
enabled: false
}; };
if (environment === 'development') { ENV.apiHost = "https://localhost:5001";
ENV.APP.LOG_TRANSITIONS = true;
ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
ENV['ember-cli-mirage'] = {
enabled: false
};
ENV.apiHost = "https://localhost:5001";
ENV.apiNamespace = "api";
}
if (environment === 'test') {
ENV.APP.LOG_RESOLVER = false;
ENV.APP.LOG_ACTIVE_GENERATION = false;
ENV.APP.LOG_VIEW_LOOKUPS = false;
// ENV.APP.LOG_TRANSITIONS = false;
// ENV.APP.LOG_TRANSITIONS_INTERNAL = false;
ENV.baseURL = '/';
ENV.locationType = 'none';
ENV.APP.rootElement = '#ember-testing';
ENV['ember-cli-mirage'] = {
enabled: true
};
ENV.APP.auditEnabled = false;
ENV.apiHost = "https://localhost:5001";
}
if (environment === 'production') {
ENV.APP.LOG_RESOLVER = false;
ENV.APP.LOG_ACTIVE_GENERATION = false;
ENV.APP.LOG_VIEW_LOOKUPS = false;
ENV.APP.LOG_TRANSITIONS = false;
ENV.APP.LOG_TRANSITIONS_INTERNAL = false;
ENV.apiHost = "";
}
process.argv.forEach(function(element) {
if (element !== undefined) {
if (element.startsWith("intercom=")) {
element = element.replace("intercom=", "");
ENV.APP.intercomKey = element;
}
if (element.startsWith("apiHost=")) {
element = element.replace("apiHost=", "");
ENV.apiHost = element;
}
}
});
ENV.apiNamespace = "api"; ENV.apiNamespace = "api";
ENV.contentSecurityPolicy = null; }
return ENV; if (environment === 'test') {
}; ENV.APP.LOG_RESOLVER = false;
ENV.APP.LOG_ACTIVE_GENERATION = false;
ENV.APP.LOG_VIEW_LOOKUPS = false;
// ENV.APP.LOG_TRANSITIONS = false;
// ENV.APP.LOG_TRANSITIONS_INTERNAL = false;
ENV.baseURL = '/';
ENV.locationType = 'none';
ENV.APP.rootElement = '#ember-testing';
ENV['ember-cli-mirage'] = {
enabled: true
};
ENV.APP.auditEnabled = false;
ENV.apiHost = "https://localhost:5001";
}
if (environment === 'production') {
ENV.APP.LOG_RESOLVER = false;
ENV.APP.LOG_ACTIVE_GENERATION = false;
ENV.APP.LOG_VIEW_LOOKUPS = false;
ENV.APP.LOG_TRANSITIONS = false;
ENV.APP.LOG_TRANSITIONS_INTERNAL = false;
ENV.apiHost = "";
}
process.argv.forEach(function(element) {
if (element !== undefined) {
if (element.startsWith("intercom=")) {
element = element.replace("intercom=", "");
ENV.APP.intercomKey = element;
}
if (element.startsWith("apiHost=")) {
element = element.replace("apiHost=", "");
ENV.apiHost = element;
}
}
});
ENV.apiNamespace = "api";
ENV.contentSecurityPolicy = null;
return ENV;
};