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:
parent
9d1af37f6e
commit
74c9e76d09
17 changed files with 352 additions and 31 deletions
|
@ -21,7 +21,8 @@
|
|||
"Sortable",
|
||||
"datetimepicker",
|
||||
"Waypoint",
|
||||
"velocity"
|
||||
"velocity",
|
||||
"Keycloak"
|
||||
],
|
||||
"browser": true,
|
||||
"boss": true,
|
||||
|
|
|
@ -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() {
|
||||
|
|
62
app/app/authenticators/keycloak.js
Normal file
62
app/app/authenticators/keycloak.js
Normal 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();
|
||||
}
|
||||
});
|
|
@ -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;
|
||||
}
|
||||
|
|
14
app/app/pods/auth/keycloak/controller.js
Normal file
14
app/app/pods/auth/keycloak/controller.js
Normal 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({});
|
64
app/app/pods/auth/keycloak/route.js
Normal file
64
app/app/pods/auth/keycloak/route.js
Normal 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);
|
||||
});
|
||||
},
|
||||
});
|
4
app/app/pods/auth/keycloak/template.hbs
Normal file
4
app/app/pods/auth/keycloak/template.hbs
Normal file
|
@ -0,0 +1,4 @@
|
|||
<div class="sso-box">
|
||||
<p>Keycloak authentication...</p>
|
||||
<img src="/assets/img/busy-gray.gif" />
|
||||
</div>
|
|
@ -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;
|
||||
// }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
});
|
|
@ -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');
|
||||
}
|
||||
});
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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'
|
||||
});
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
74
app/app/services/kc-auth.js
Normal file
74
app/app/services/kc-auth.js
Normal 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,
|
||||
};
|
||||
}
|
||||
});
|
|
@ -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 — email/password{{/ui/ui-radio}}
|
||||
{{#ui/ui-radio selected=isKeycloakProvider onClick=(action 'onKeycloak')}}Keycloak — bring your own authenticaiton server{{/ui/ui-radio}}
|
||||
{{#ui/ui-radio selected=isKeycloakProvider onClick=(action 'onKeycloak')}}Keycloak — 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}}
|
||||
|
||||
|
|
|
@ -19,5 +19,12 @@ export default {
|
|||
AuthProvider: {
|
||||
Documize: 'documize',
|
||||
Keycloak: 'keycloak'
|
||||
}
|
||||
},
|
||||
|
||||
DocumentActionType: {
|
||||
Read: 1,
|
||||
Feedback: 2,
|
||||
Contribute: 3,
|
||||
Approve: 4
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue