1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-19 13:19:43 +02:00

upgraded ember-data, basic keycloak callback mechanism

This commit is contained in:
Harvey Kandola 2017-03-16 11:46:09 +00:00
parent 9d1af37f6e
commit 74c9e76d09
17 changed files with 352 additions and 31 deletions

View file

@ -21,7 +21,8 @@
"Sortable",
"datetimepicker",
"Waypoint",
"velocity"
"velocity",
"Keycloak"
],
"browser": true,
"boss": true,

View file

@ -21,7 +21,6 @@ const {
} = Ember;
export default Base.extend({
ajax: service(),
appMeta: service(),
@ -30,6 +29,7 @@ export default Base.extend({
if (data) {
return resolve(data);
}
return reject();
},
@ -51,13 +51,9 @@ export default Base.extend({
return Ember.RSVP.reject("invalid");
}
var headers = {
'Authorization': 'Basic ' + encoded
};
let headers = { 'Authorization': 'Basic ' + encoded };
return this.get('ajax').post('public/authenticate', {
headers
});
return this.get('ajax').post('public/authenticate', { headers });
},
invalidate() {

View file

@ -0,0 +1,62 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import Ember from 'ember';
import Base from 'ember-simple-auth/authenticators/base';
import encodingUtil from '../utils/encoding';
import netUtil from '../utils/net';
const {
isPresent,
RSVP: { resolve, reject },
inject: { service }
} = Ember;
export default Base.extend({
ajax: service(),
appMeta: service(),
restore(data) {
// TODO: verify authentication data
if (data) {
return resolve(data);
}
return reject();
},
authenticate(credentials) {
let domain = netUtil.getSubdomain();
let encoded;
if (typeof credentials === 'object') {
let { password, email } = credentials;
if (!isPresent(password) || !isPresent(email)) {
return Ember.RSVP.reject("invalid");
}
encoded = encodingUtil.Base64.encode(`${domain}:${email}:${password}`);
} else if (typeof credentials === 'string') {
encoded = credentials;
} else {
return Ember.RSVP.reject("invalid");
}
let headers = { 'Authorization': 'Basic ' + encoded };
return this.get('ajax').post('public/authenticate', { headers });
},
invalidate() {
return resolve();
}
});

View file

@ -19,8 +19,15 @@ const {
export default Ember.Component.extend({
isDocumizeProvider: computed.equal('authProvider', constants.AuthProvider.Documize),
isKeycloakProvider: computed.equal('authProvider', constants.AuthProvider.Keycloak),
KeycloakConfigError: computed.empty('keycloakConfig'),
keycloakConfig: '',
KeycloakUrlError: computed.empty('keycloakConfig.url'),
KeycloakRealmError: computed.empty('keycloakConfig.realm'),
KeycloakClientIdError: computed.empty('keycloakConfig.clientId'),
keycloakConfig: {
url: '',
realm: '',
clientId: ''
},
didReceiveAttrs() {
this._super(...arguments);
@ -31,7 +38,15 @@ export default Ember.Component.extend({
case constants.AuthProvider.Documize:
break;
case constants.AuthProvider.Keycloak:
this.set('keycloakConfig', this.get('authConfig'));
let config = this.get('authConfig');
if (is.undefined(config) || is.null(config) || is.empty(config) ) {
config = {};
} else {
config = JSON.parse(config);
}
this.set('keycloakConfig', config);
break;
}
},
@ -46,11 +61,6 @@ export default Ember.Component.extend({
},
onSave() {
if (this.get('KeycloakConfigError')) {
this.$("#keycloak-id").focus();
return;
}
let provider = this.get('authProvider');
let config = this.get('authConfig');
@ -59,6 +69,19 @@ export default Ember.Component.extend({
config = {};
break;
case constants.AuthProvider.Keycloak:
if (this.get('KeycloakUrlError')) {
this.$("#keycloak-url").focus();
return;
}
if (this.get('KeycloakRealmError')) {
this.$("#keycloak-realm").focus();
return;
}
if (this.get('KeycloakClientIdError')) {
this.$("#keycloak-clientId").focus();
return;
}
config = this.get('keycloakConfig');
break;
}

View file

@ -0,0 +1,14 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import Ember from 'ember';
export default Ember.Controller.extend({});

View file

@ -0,0 +1,64 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import Ember from 'ember';
import constants from '../../../utils/constants';
export default Ember.Route.extend({
session: Ember.inject.service(),
appMeta: Ember.inject.service(),
kcAuth: Ember.inject.service(),
queryParams: {
mode: {
refreshModel: false
}
},
beforeModel(transition) {
this.set('mode', is.not.undefined(transition.queryParams.mode) ? transition.queryParams.mode : 'login');
let authProvider = this.get('appMeta.authProvider');
let authConfig = this.get('appMeta.authConfig');
if (authProvider !== constants.AuthProvider.Keycloak) {
console.log('Expecting keycloak auth but found ' + authProvider);
return;
}
this.get('kcAuth').boot(JSON.parse(authConfig)).then((kc) => {
if (!kc.authenticated) {
this.get('kcAuth').login().then(() => {
}, (reject) => {
console.log(reject);
});
}
this.get('kcAuth').fetchProfile(kc).then((profile) => {
let data = this.get('kcAuth').mapProfile(kc, profile);
console.log(data);
// this.get("session").authenticate('authenticator:keycloak', data)
// .then(() => {
// this.transitionTo('folders');
// }, () => {
// this.transitionTo('auth.login');
// console.log(">>>>> Documize SSO failure");
// });
}, (err) => {
console.log(err);
});
}, (reason) => {
console.log(reason);
});
},
});

View file

@ -0,0 +1,4 @@
<div class="sso-box">
<p>Keycloak authentication...</p>
<img src="/assets/img/busy-gray.gif" />
</div>

View file

@ -10,18 +10,18 @@
// https://documize.com
import Ember from 'ember';
// import constants from '../../../utils/constants';
export default Ember.Controller.extend({
email: "",
password: "",
appMeta: Ember.inject.service('app-meta'),
invalidCredentials: false,
session: Ember.inject.service('session'),
audit: Ember.inject.service('audit'),
reset() {
this.setProperties({
email: "",
password: ""
email: '',
password: ''
});
let dbhash = document.head.querySelector("[property=dbhash]").content;
@ -43,6 +43,29 @@ export default Ember.Controller.extend({
}).catch(() => {
this.set('invalidCredentials', true);
});
// let authProvider = this.get('appMeta.authProvider');
// let authConfig = this.get('appMeta.authConfig');
// switch (authProvider) {
// case constants.AuthProvider.Documize:
// let creds = this.getProperties('email', 'password');
// this.get('session').authenticate('authenticator:documize', creds)
// .then((response) => {
// this.get('audit').record("logged-in");
// this.transitionToRoute('folders');
// return response;
// }).catch(() => {
// this.set('invalidCredentials', true);
// });
// break;
// case constants.AuthProvider.Keycloak:
// // this.get('session').authenticate('authenticator:keycloak', authConfig);
// break;
// }
}
}
});

View file

@ -10,11 +10,42 @@
// https://documize.com
import Ember from 'ember';
import constants from '../../../utils/constants';
export default Ember.Route.extend({
appMeta: Ember.inject.service(),
kcAuth: Ember.inject.service(),
beforeModel(/*transition*/) {
let authProvider = this.get('appMeta.authProvider');
let authConfig = this.get('appMeta.authConfig');
switch (authProvider) {
case constants.AuthProvider.Keycloak:
this.get('kcAuth').boot(JSON.parse(authConfig)).then(() => {
this.get('kcAuth').login().then(() => {
}, (reject) => {
console.log(reject);
});
}, (reject) => {
console.log(reject);
});
break;
}
},
setupController: function (controller, model) {
controller.set('model', model);
controller.reset();
this.browser.setTitleAsPhrase("Login");
},
activate() {
$('body').addClass('background-color-off-white');
},
deactivate() {
$('body').removeClass('background-color-off-white');
}
});

View file

@ -15,4 +15,12 @@ export default Ember.Route.extend({
model: function (params) {
return params.token;
},
activate() {
$('body').addClass('background-color-off-white');
},
deactivate() {
$('body').removeClass('background-color-off-white');
}
});

View file

@ -14,17 +14,17 @@ import NotifierMixin from "../../../mixins/notifier";
export default Ember.Controller.extend(NotifierMixin, {
global: Ember.inject.service(),
appMeta: Ember.inject.service(),
actions: {
onSave(provider, config) {
if(this.get('session.isGlobalAdmin')) {
let data = { authProvider: provider, authConfig: config };
let data = { authProvider: provider, authConfig: JSON.stringify(config) };
return this.get('global').saveAuthConfig(data).then(() => {
this.showNotification('Saved');
if (this.get('authProvider') !== provider) {
// window.location.reload();
}
this.set('appMeta.authProvider', provider);
this.set('appMeta.authConfig', config);
});
}
}

View file

@ -73,6 +73,9 @@ export default Router.map(function () {
this.route('sso', {
path: 'sso/:token'
});
this.route('keycloak', {
path: 'keycloak'
});
this.route('login', {
path: 'login'
});

View file

@ -11,6 +11,7 @@
import Ember from 'ember';
import config from '../config/environment';
import constants from '../utils/constants';
const {
String: { htmlSafe },
@ -30,7 +31,7 @@ export default Ember.Service.extend({
edition: 'Community',
valid: true,
allowAnonymousAccess: false,
authProvider: 'documize',
authProvider: constants.AuthProvider.Documize,
authConfig: null,
setupMode: false,

View file

@ -0,0 +1,74 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import Ember from 'ember';
import netUtil from '../utils/net';
const {
inject: { service }
} = Ember;
export default Ember.Service.extend({
sessionService: service('session'),
audit: service(),
ajax: service(),
appMeta: service(),
keycloak: null,
boot(options) {
this.set('keycloak', new Keycloak(options));
return new Ember.RSVP.Promise((resolve, reject) => {
this.keycloak.init().success(() => {
this.get('audit').record("initialized-keycloak");
resolve(this.get('keycloak'));
}).error((err) => {
console.log('Keycloak init failed', err);
reject(err);
});
});
},
login() {
let url = netUtil.getAppUrl(netUtil.getSubdomain()) + '/auth/keycloak?mode=login';
return new Ember.RSVP.Promise((resolve, reject) => {
if (this.get('keycloak').authenticated) {
return resolve(this.get('keycloak'));
}
this.get('keycloak').login( {redirectUri: url} );
return reject();
});
},
fetchProfile(kc) {
return new Ember.RSVP.Promise((resolve, reject) => {
kc.loadUserProfile().success((profile) => {
return resolve(profile);
}).error((err) => {
console.log('Keycloak loadUserProfile failed', err);
return reject(err);
});
});
},
mapProfile(kc, profile) {
return {
token: kc.token,
enabled: profile.enabled,
email: profile.email,
username: profile.username,
firstname: profile.firstName,
lastname: profile.lastName,
};
}
});

View file

@ -7,14 +7,24 @@
<label>Provider</label>
<div class="tip">External authentication servers, services must be accessible from the server running this Documize instance</div>
{{#ui/ui-radio selected=isDocumizeProvider onClick=(action 'onDocumize')}}Documize &mdash; email/password{{/ui/ui-radio}}
{{#ui/ui-radio selected=isKeycloakProvider onClick=(action 'onKeycloak')}}Keycloak &mdash; bring your own authenticaiton server{{/ui/ui-radio}}
{{#ui/ui-radio selected=isKeycloakProvider onClick=(action 'onKeycloak')}}Keycloak &mdash; bring your own authentication server{{/ui/ui-radio}}
</div>
{{#if isKeycloakProvider}}
<div class="input-control">
<label>Keycloak OIDC JSON</label>
<div class="tip">Realm Client JSON configuration from Keycloak admin console</div>
{{textarea id="keycloak-config" type="text" rows=7 value=keycloakConfig class=(if KeycloakUrlError 'error')}}
<label>Keycloak Server URL</label>
<div class="tip">e.g. http://localhost:8888/auth</div>
{{focus-input id="keycloak-url" type="text" value=keycloakConfig.url class=(if KeycloakUrlError 'error')}}
</div>
<div class="input-control">
<label>Keycloak Realm</label>
<div class="tip">e.g. main</div>
{{input id="keycloak-realm" type="text" value=keycloakConfig.realm class=(if keycloakRealmError 'error')}}
</div>
<div class="input-control">
<label>Keycloak OIDC Client ID</label>
<div class="tip">e.g. account</div>
{{input id="keycloak-clientId" type="text" value=keycloakConfig.clientId class=(if KeycloakClientIdError 'error')}}
</div>
{{/if}}

View file

@ -19,5 +19,12 @@ export default {
AuthProvider: {
Documize: 'documize',
Keycloak: 'keycloak'
}
},
DocumentActionType: {
Read: 1,
Feedback: 2,
Contribute: 3,
Approve: 4
}
};

View file

@ -37,7 +37,7 @@
"ember-cli-sri": "^2.1.0",
"ember-cli-test-loader": "^1.1.0",
"ember-cli-uglify": "^1.2.0",
"ember-data": "^2.11.0",
"ember-data": "^2.12.0",
"ember-export-application-global": "^1.0.5",
"ember-load-initializers": "^0.6.0",
"ember-resolver": "^2.0.3",