Adapt the Login component to works also with activiti

This commit is contained in:
mauriziovitale84
2016-07-08 12:34:16 +01:00
parent 3881faec42
commit f7dee66d1e
14 changed files with 855 additions and 150 deletions

View File

@@ -1 +1,11 @@
<alfresco-login (onSuccess)="onLogin($event)" (onError)="onError($event)"></alfresco-login> <div style="position: absolute; background-color: papayawhip; color: cadetblue; left: 10px; top: 10px; z-index: 1;">
<p style="width:120px;margin: 10px;">
<small style="float: left;">ECM</small>
<input class="mdl-slider mdl-js-slider" type="range" (click)="toggleECM(ecm.value)" #ecm id="s1" min="0" max="10" value="10" step="10">
</p>
<p style="width:120px;margin: 10px;">
<small style="float: left;">BPM</small>
<input class="mdl-slider mdl-js-slider" type="range" (click)="toggleBPM(bpm.value)" #bpm id="s2" min="0" max="10" value="0" step="10">
</p>
</div>
<alfresco-login [providers]="providers" (onSuccess)="onLogin($event)" (onError)="onError($event)"></alfresco-login>

View File

@@ -33,6 +33,8 @@ export class LoginDemoComponent {
constructor(public router: Router) { constructor(public router: Router) {
} }
providers: string [] = ['ECM'];
onLogin($event) { onLogin($event) {
console.log($event); console.log($event);
this.router.navigate(['Home']); this.router.navigate(['Home']);
@@ -42,4 +44,20 @@ export class LoginDemoComponent {
console.log($event); console.log($event);
} }
toggleECM(value) {
if (value === '10') {
this.providers[0] = 'ECM';
} else {
this.providers[0] = '';
}
}
toggleBPM(value) {
if (value === '10') {
this.providers[1] = 'BPM';
} else {
this.providers[1] = '';
}
}
} }

View File

@@ -22,6 +22,10 @@ import {
ObjectDataTableAdapter ObjectDataTableAdapter
} from 'ng2-alfresco-datatable'; } from 'ng2-alfresco-datatable';
import {
AlfrescoAuthenticationService
} from 'ng2-alfresco-core';
@Component({ @Component({
selector: 'tasks-demo', selector: 'tasks-demo',
template: ` template: `
@@ -38,20 +42,22 @@ export class TasksDemoComponent implements OnInit {
tasks: ObjectDataTableAdapter; tasks: ObjectDataTableAdapter;
constructor( constructor(
private activitiService: ActivitiService) {} private activitiService: ActivitiService,
private auth: AlfrescoAuthenticationService) {}
ngOnInit() { ngOnInit() {
this.activitiService if (this.auth.isLoggedIn('BPM')) {
.login('denys.vuika@alfresco.com', 'test') this.activitiService
.then(() => { .getTasks()
this.activitiService .then((data) => {
.getTasks() let tasks = data || [];
.then((data) => { console.log(tasks);
let tasks = data || []; this.loadTasks(tasks);
console.log(tasks); });
this.loadTasks(tasks); } else {
}); console.error('User unauthorized');
}); }
} }
private loadTasks(tasks: any[]) { private loadTasks(tasks: any[]) {

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;;;;;QAwBU,uBAAuB,EAUvB,sBAAsB,EAItB,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAdvB,qCAAA,uBAAuB,GAAU;gBAC1C,qEAA6B;gBAC7B,uDAAsB;gBACtB,yDAAuB;gBACvB,6DAAyB;gBACzB,+DAA0B;gBAC1B,qDAAqB;gBACrB,yCAAkB;aACrB,CAAA,CAAC;YAEW,oCAAA,sBAAsB,GAAU;gBACzC,yCAAkB;aACrB,CAAA,CAAC;YAEW,qCAAA,uBAAuB,GAAU;gBAC1C,0DAA0B;gBAC1B,6CAAoB;aACvB,CAAA,CAAC"}

View File

@@ -0,0 +1,37 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AbstractAuthentication } from '../interface/authentication.interface';
import { AlfrescoAuthenticationBPM } from '../services/AlfrescoAuthenticationBPM.service';
import { AlfrescoAuthenticationECM } from '../services/AlfrescoAuthenticationECM.service';
import { Http } from '@angular/http';
import { AlfrescoSettingsService } from '../services/AlfrescoSettingsService.service';
export class AuthenticationFactory {
public static createAuth(alfrescoSettingsService: AlfrescoSettingsService,
http: Http,
type: string): AbstractAuthentication {
if (type === 'ECM') {
return new AlfrescoAuthenticationECM(alfrescoSettingsService, http);
} else if (type === 'BPM') {
return new AlfrescoAuthenticationBPM(alfrescoSettingsService, http);
}
return null;
}
}

View File

@@ -0,0 +1,33 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Observable } from 'rxjs/Rx';
export interface AbstractAuthentication {
TYPE: string;
login(username: string, password: string): Observable<any>;
logout(): Observable<any>;
isLoggedIn(): boolean ;
getToken(): string;
saveToken(): void;
}

View File

@@ -0,0 +1,108 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AbstractAuthentication } from '../interface/authentication.interface';
import { Http, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { AlfrescoAuthenticationBase } from './AlfrescoAuthenticationBase.service';
import { AlfrescoSettingsService } from './AlfrescoSettingsService.service';
export class AlfrescoAuthenticationBPM extends AlfrescoAuthenticationBase implements AbstractAuthentication {
TYPE: string = 'BPM';
private token: string;
constructor(private alfrescoSettingsService: AlfrescoSettingsService,
private http: Http) {
super(alfrescoSettingsService, http);
}
/**
* Perform a login on behalf of the user and store the ticket returned
*
* @param username
* @param password
* @returns {Observable<R>|Observable<T>}
*/
login(username: string, password: string): Observable<any> {
return Observable.fromPromise(this.apiActivitiLogin(username, password))
.map((response: any) => {
this.token = response.status;
return this.token;
// return {name: this.TYPE, token: response.status};
})
.catch(this.handleError);
}
/**
* Delete the current login ticket from the server
*
* @returns {Observable<R>|Observable<T>}
*/
logout() {
return Observable.fromPromise(this.apiActivitiLogout())
.map(res => <any> res)
.do(response => {
this.removeToken(this.TYPE);
})
.catch(this.handleError);
}
/**
* The method return true if the user is logged in
* @returns {boolean}
*/
isLoggedIn(): boolean {
return !!this.getToken();
}
private apiActivitiLogin(username: string, password: string) {
let url = 'http://localhost:9999/activiti-app/app/authentication';
let headers = new Headers({
'Content-Type': 'application/x-www-form-urlencoded'
});
let options = new RequestOptions({headers: headers});
let data = 'j_username='
+ encodeURIComponent(username)
+ '&j_password='
+ encodeURIComponent(password)
+ '&_spring_security_remember_me=true&submit=Login';
return this.http
.post(url, data, options).toPromise();
}
private apiActivitiLogout() {
let url = 'http://localhost:9999/activiti-app/app/logout';
return this.http.get(url).toPromise();
}
public getToken (): string {
return localStorage.getItem(`token-${this.TYPE}`);
}
/**
* The method save the toke in the localStorage
* @param token
*/
public saveToken(): void {
if (this.token) {
super.saveToken(this.TYPE, this.token);
}
}
}

View File

@@ -0,0 +1,68 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Http, Response } from '@angular/http';
import { AlfrescoSettingsService } from './AlfrescoSettingsService.service';
import { Observable } from 'rxjs/Rx';
declare let AlfrescoApi: any;
export class AlfrescoAuthenticationBase {
private _authUrl: string = '/alfresco/api/-default-/public/authentication/versions/1';
private alfrescoSetting: AlfrescoSettingsService;
/**
* Constructor
* @param alfrescoSettingsService
*/
constructor(alfrescoSettingsService: AlfrescoSettingsService,
http: Http) {
this.alfrescoSetting = alfrescoSettingsService;
}
getBaseUrl(): string {
return this.alfrescoSetting.host + this._authUrl;
}
/**
* The method save the toke in the localStorage
* @param token
*/
public saveToken(provider:string, token: string): void {
if (token) {
localStorage.setItem(`token-${provider}`, token);
}
}
/**
* Remove the login token from localStorage
*/
public removeToken(provider:string): void {
localStorage.removeItem(`token-${provider}`);
}
/**
* The method write the error in the console browser
* @param error
* @returns {ErrorObservable}
*/
public handleError(error: Response): Observable<any> {
console.error('Error when logging in', error);
return Observable.throw(error || 'Server error');
}
}

View File

@@ -0,0 +1,110 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AbstractAuthentication } from '../interface/authentication.interface';
import { Observable } from 'rxjs/Rx';
import { Http } from '@angular/http';
import { AlfrescoAuthenticationBase } from './AlfrescoAuthenticationBase.service';
import { AlfrescoSettingsService } from './AlfrescoSettingsService.service';
declare let AlfrescoApi: any;
export class AlfrescoAuthenticationECM extends AlfrescoAuthenticationBase implements AbstractAuthentication {
TYPE: string = 'ECM';
private token: string;
constructor(private alfrescoSettingsService: AlfrescoSettingsService,
private http: Http) {
super(alfrescoSettingsService, http);
}
/**
* Perform a login on behalf of the user and store the ticket returned
*
* @param username
* @param password
* @returns {Observable<R>|Observable<T>}
*/
login(username: string, password: string): Observable<any> {
return Observable.fromPromise(this.getCreateTicketPromise(username, password))
.map((response: any) => {
this.token = response.entry.id;
return this.token;
// return {name: this.TYPE, token: response.entry.id};
})
.catch(this.handleError);
}
/**
* Delete the current login ticket from the server
*
* @returns {Observable<R>|Observable<T>}
*/
logout() {
return Observable.fromPromise(this.getDeleteTicketPromise())
.map(res => <any> res)
.do(response => {
this.removeToken(this.TYPE);
})
.catch(this.handleError);
}
/**
* The method return true if the user is logged in
* @returns {boolean}
*/
isLoggedIn(): boolean {
return !!this.getToken();
}
private getAlfrescoClient() {
return AlfrescoApi.getClientWithTicket(this.getBaseUrl(), this.getToken());
}
private getCreateTicketPromise(username: string, password: string) {
let apiInstance = new AlfrescoApi.Auth.AuthenticationApi(this.getAlfrescoClient());
let loginRequest = new AlfrescoApi.Auth.LoginRequest();
loginRequest.userId = username;
loginRequest.password = password;
return apiInstance.createTicket(loginRequest);
}
private getDeleteTicketPromise() {
let apiInstance = new AlfrescoApi.Auth.AuthenticationApi(this.getAlfrescoClient());
return apiInstance.deleteTicket();
}
/**
* The method return the token stored in the localStorage
* @param token
*/
public getToken (): string {
return localStorage.getItem(`token-${this.TYPE}`);
}
/**
* The method save the toke in the localStorage
* @param token
*/
public saveToken(): void {
if (this.token) {
super.saveToken(this.TYPE, this.token);
}
}
}

View File

@@ -15,21 +15,54 @@
* limitations under the License. * limitations under the License.
*/ */
import { it, describe, beforeEach } from '@angular/core/testing'; import { it, describe } from '@angular/core/testing';
import { ReflectiveInjector } from '@angular/core'; import { ReflectiveInjector, provide } from '@angular/core';
import { AlfrescoSettingsService } from './AlfrescoSettingsService.service'; import { AlfrescoSettingsService } from './AlfrescoSettingsService.service';
import { AlfrescoAuthenticationService } from './AlfrescoAuthenticationService.service'; import { AlfrescoAuthenticationService } from './AlfrescoAuthenticationService.service';
import { AlfrescoAuthenticationECM } from './AlfrescoAuthenticationECM.service';
import { AlfrescoAuthenticationBPM } from './AlfrescoAuthenticationBPM.service';
import { XHRBackend, HTTP_PROVIDERS } from '@angular/http';
import { MockBackend } from '@angular/http/testing';
declare var AlfrescoApi: any; declare var AlfrescoApi: any;
describe('AlfrescoAuthentication', () => { describe('AlfrescoAuthentication', () => {
let injector, let injector,
fakePromiseECM,
fakePromiseBPM,
service; service;
fakePromiseECM = new Promise(function (resolve, reject) {
resolve({
entry: {
userId: 'fake-username',
id: 'fake-post-token-ECM'
}
});
reject({
response: {
error: 'fake-error'
}
});
});
fakePromiseBPM = new Promise(function (resolve, reject) {
resolve({
status: 'fake-post-token-BPM'
});
reject({
response: {
error: 'fake-error'
}
});
});
beforeEach(() => { beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([ injector = ReflectiveInjector.resolveAndCreate([
AlfrescoAuthenticationService, HTTP_PROVIDERS,
AlfrescoSettingsService provide(XHRBackend, {useClass: MockBackend}),
provide(AlfrescoSettingsService, {useClass: AlfrescoSettingsService}),
AlfrescoAuthenticationService
]); ]);
let store = {}; let store = {};
@@ -54,58 +87,283 @@ describe('AlfrescoAuthentication', () => {
service = injector.get(AlfrescoAuthenticationService); service = injector.get(AlfrescoAuthenticationService);
}); });
it('should return true and token if the user is logged in', () => { describe('when the setting is ECM', () => {
service.saveToken('fake-local-token');
expect(service.isLoggedIn()).toBe(true);
expect(localStorage.getItem('token')).toBeDefined();
expect(localStorage.getItem('token')).toEqual('fake-local-token');
});
it('should return false and token undefined if the user is not logged in', () => { it('should create an AlfrescoAuthenticationECM instance', (done) => {
expect(service.isLoggedIn()).toEqual(false); let providers = ['ECM'];
expect(localStorage.getItem('token')).not.toBeDefined(); spyOn(AlfrescoAuthenticationECM.prototype, 'getCreateTicketPromise').and.returnValue(fakePromiseECM);
}); service.login('fake-username', 'fake-password', providers)
.subscribe(() => {
it('should return true and token on sign in', () => { expect(service.isLoggedIn(providers[0])).toBe(true);
expect(service.providersInstance).toBeDefined();
let p = new Promise(function (resolve, reject) { expect(service.providersInstance.length).toBe(1);
resolve({ expect(service.providersInstance[0].TYPE).toEqual(providers[0]);
entry: { done();
userId: 'fake-username',
id: 'fake-post-token'
}
});
});
spyOn(service, 'getCreateTicketPromise').and.returnValue(p);
service.token = '';
service.login('fake-username', 'fake-password')
.subscribe(() => {
expect(service.isLoggedIn()).toBe(true);
expect(service.getToken()).toEqual('fake-post-token');
expect(localStorage.getItem('token')).toBeDefined();
expect(localStorage.getItem('token')).toEqual('fake-post-token');
} }
); );
});
it('should return false and token undefined on log out', () => {
let p = new Promise(function (resolve, reject) {
resolve();
}); });
spyOn(service, 'getDeleteTicketPromise').and.returnValue(p); it('should return an ECM token after the login done', (done) => {
let providers = ['ECM'];
spyOn(AlfrescoAuthenticationECM.prototype, 'getCreateTicketPromise').and.returnValue(fakePromiseECM);
localStorage.setItem('token', 'fake-token'); service.login('fake-username', 'fake-password', providers)
service.logout() .subscribe(() => {
.subscribe(() => { expect(service.isLoggedIn(providers[0])).toBe(true);
expect(service.isLoggedIn()).toBe(false); expect(service.getToken(providers[0])).toEqual('fake-post-token-ECM');
expect(service.getToken()).toBeUndefined(); done();
expect(localStorage.getItem('token')).toBeUndefined();
} }
); );
});
it('should return token undefined when the credentials are wrong', (done) => {
let providers = ['ECM'];
spyOn(AlfrescoAuthenticationECM.prototype, 'getCreateTicketPromise')
.and.returnValue(Promise.reject('fake invalid credentials'));
service.login('fake-wrong-username', 'fake-wrong-password', providers)
.subscribe(
(res) => {
done();
},
(err: any) => {
expect(service.isLoggedIn(providers[0])).toBe(false);
expect(service.getToken(providers[0])).toBeUndefined();
done();
}
);
});
it('should return an error if no provider are defined calling the login', (done) => {
let providers = [];
service.login('fake-username', 'fake-password', providers)
.subscribe(
(res) => {
done();
},
(err: any) => {
expect(err).toBeDefined();
expect(err).toEqual('No providers defined');
done();
}
);
});
it('should return an error if an empty provider are defined calling the login', (done) => {
let providers = [''];
service.login('fake-username', 'fake-password', providers)
.subscribe(
(res) => {
done();
},
(err: any) => {
expect(err).toBeDefined();
expect(err).toEqual('No providers defined');
done();
}
);
});
it('should return a token undefined after logout', (done) => {
let providers = ['ECM'];
localStorage.setItem('token-ECM', 'fake-post-token-ECM');
service.createProviderInstance(providers);
spyOn(AlfrescoAuthenticationECM.prototype, 'getDeleteTicketPromise').and.returnValue(fakePromiseECM);
service.logout()
.subscribe(() => {
expect(service.isLoggedIn(providers[0])).toBe(false);
expect(service.getToken(providers[0])).toBeUndefined();
expect(localStorage.getItem('token-ECM')).toBeUndefined();
done();
}
);
});
it('should return an error if no provider are defined calling the logout', (done) => {
service.logout()
.subscribe(
(res) => {
done();
},
(err: any) => {
expect(err).toBeDefined();
expect(err).toEqual('No providers defined');
done();
}
);
});
it('should return false if the user is not logged in', () => {
let providers = ['ECM'];
expect(service.isLoggedIn(providers[0])).toBe(false);
});
}); });
describe('when the setting is BPM', () => {
it('should create an AlfrescoAuthenticationBPM instance', (done) => {
let providers = ['BPM'];
spyOn(AlfrescoAuthenticationBPM.prototype, 'apiActivitiLogin').and.returnValue(fakePromiseBPM);
service.login('fake-username', 'fake-password', providers)
.subscribe(() => {
expect(service.isLoggedIn(providers[0])).toBe(true);
expect(service.providersInstance).toBeDefined();
expect(service.providersInstance.length).toBe(1);
expect(service.providersInstance[0].TYPE).toEqual(providers[0]);
done();
}
);
});
it('should return an BPM token after the login done', (done) => {
let providers = ['BPM'];
spyOn(AlfrescoAuthenticationBPM.prototype, 'apiActivitiLogin').and.returnValue(fakePromiseBPM);
service.login('fake-username', 'fake-password', providers)
.subscribe(() => {
expect(service.isLoggedIn(providers[0])).toBe(true);
expect(service.getToken(providers[0])).toEqual('fake-post-token-BPM');
done();
}
);
});
it('should return token undefined when the credentials are wrong', (done) => {
let providers = ['BPM'];
spyOn(AlfrescoAuthenticationBPM.prototype, 'apiActivitiLogin').and.returnValue(Promise.reject('fake invalid credentials'));
service.login('fake-wrong-username', 'fake-wrong-password', providers)
.subscribe(
(res) => {
done();
},
(err: any) => {
expect(service.isLoggedIn(providers[0])).toBe(false);
expect(service.getToken(providers[0])).toBeUndefined();
done();
}
);
});
it('should return a token undefined after logout', (done) => {
let providers = ['BPM'];
localStorage.setItem('token-BPM', 'fake-post-token-BPM');
service.createProviderInstance(providers);
spyOn(AlfrescoAuthenticationBPM.prototype, 'apiActivitiLogout').and.returnValue(fakePromiseBPM);
service.logout()
.subscribe(() => {
expect(service.isLoggedIn(providers[0])).toBe(false);
expect(service.getToken(providers[0])).toBeUndefined();
expect(localStorage.getItem('token-BPM')).toBeUndefined();
done();
}
);
});
it('should throw an error when the logout return error', (done) => {
let providers = ['BPM'];
localStorage.setItem('token-BPM', 'fake-post-token-BPM');
service.createProviderInstance(providers);
spyOn(AlfrescoAuthenticationBPM.prototype, 'apiActivitiLogout').and.returnValue(Promise.reject('fake logout error'));
service.logout()
.subscribe(
(res) => {
done();
},
(err: any) => {
expect(err).toBeDefined();
expect(err.message).toEqual('fake logout error');
expect(localStorage.getItem('token-BPM')).toEqual('fake-post-token-BPM');
done();
}
);
});
});
describe('when the setting is both ECM and BPM ', () => {
it('should create both instances', (done) => {
let providers = ['ECM', 'BPM'];
spyOn(AlfrescoAuthenticationECM.prototype, 'getCreateTicketPromise').and.returnValue(fakePromiseECM);
spyOn(AlfrescoAuthenticationBPM.prototype, 'apiActivitiLogin').and.returnValue(fakePromiseBPM);
service.login('fake-username', 'fake-password', providers)
.subscribe(() => {
expect(service.isLoggedIn(providers[0])).toBe(true);
expect(service.isLoggedIn(providers[1])).toBe(true);
expect(service.providersInstance).toBeDefined();
expect(service.providersInstance.length).toBe(2);
expect(service.providersInstance[0].TYPE).toEqual(providers[0]);
expect(service.providersInstance[1].TYPE).toEqual(providers[1]);
done();
}
);
});
it('should return both ECM and BPM tokens after the login done', (done) => {
let providers = ['ECM', 'BPM'];
spyOn(AlfrescoAuthenticationECM.prototype, 'getCreateTicketPromise').and.returnValue(fakePromiseECM);
spyOn(AlfrescoAuthenticationBPM.prototype, 'apiActivitiLogin').and.returnValue(fakePromiseBPM);
service.login('fake-username', 'fake-password', providers)
.subscribe(() => {
expect(service.isLoggedIn(providers[0])).toBe(true);
expect(service.isLoggedIn(providers[1])).toBe(true);
expect(service.getToken(providers[0])).toEqual('fake-post-token-ECM');
expect(service.getToken(providers[1])).toEqual('fake-post-token-BPM');
done();
}
);
});
it('should return token undefined when the credentials are correct for the ECM login but wrong for the BPM login', (done) => {
let providers = ['ECM', 'BPM'];
spyOn(AlfrescoAuthenticationECM.prototype, 'getCreateTicketPromise').and.returnValue(fakePromiseECM);
spyOn(AlfrescoAuthenticationBPM.prototype, 'apiActivitiLogin').and.returnValue(Promise.reject('fake invalid credentials'));
service.login('fake-username', 'fake-password', providers)
.subscribe(
(res) => {
done();
},
(err: any) => {
expect(service.isLoggedIn(providers[0])).toBe(false);
expect(service.getToken(providers[0])).toBeUndefined();
expect(service.isLoggedIn(providers[1])).toBe(false);
expect(service.getToken(providers[1])).toBeUndefined();
done();
}
);
});
it('should return token undefined when the credentials are correct for the BPM login but wrong for the ECM login', (done) => {
let providers = ['ECM', 'BPM'];
spyOn(AlfrescoAuthenticationECM.prototype, 'getCreateTicketPromise')
.and.returnValue(Promise.reject('fake invalid credentials'));
spyOn(AlfrescoAuthenticationBPM.prototype, 'apiActivitiLogin').and.returnValue(fakePromiseBPM);
service.login('fake-username', 'fake-password', providers)
.subscribe(
(res) => {
done();
},
(err: any) => {
expect(service.isLoggedIn(providers[0])).toBe(false);
expect(service.getToken(providers[0])).toBeUndefined();
expect(service.isLoggedIn(providers[1])).toBe(false);
expect(service.getToken(providers[1])).toBeUndefined();
done();
}
);
});
});
}); });

View File

@@ -17,8 +17,11 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Rx'; import { Observable } from 'rxjs/Rx';
import { Response } from '@angular/http'; import { Http } from '@angular/http';
import { AlfrescoSettingsService } from './AlfrescoSettingsService.service'; import { AlfrescoSettingsService } from './AlfrescoSettingsService.service';
import { AuthenticationFactory } from '../factory/AuthenticationFactory';
import { AbstractAuthentication } from '../interface/authentication.interface';
import { AlfrescoAuthenticationBase } from './AlfrescoAuthenticationBase.service';
declare let AlfrescoApi: any; declare let AlfrescoApi: any;
@@ -26,31 +29,17 @@ declare let AlfrescoApi: any;
* The AlfrescoAuthenticationService provide the login service and store the token in the localStorage * The AlfrescoAuthenticationService provide the login service and store the token in the localStorage
*/ */
@Injectable() @Injectable()
export class AlfrescoAuthenticationService { export class AlfrescoAuthenticationService extends AlfrescoAuthenticationBase {
private _authUrl: string = '/alfresco/api/-default-/public/authentication/versions/1'; private providersInstance: AbstractAuthentication[] = [];
/** /**
* Constructor * Constructor
* @param alfrescoSettingsService * @param alfrescoSettingsService
*/ */
constructor(private alfrescoSettingsService: AlfrescoSettingsService) { constructor(private alfrescoSettingsService: AlfrescoSettingsService,
} private http: Http) {
super(alfrescoSettingsService, http);
getBaseUrl(): string {
return this.alfrescoSettingsService.host + this._authUrl;
}
private getAlfrescoClient() {
return AlfrescoApi.getClientWithTicket(this.getBaseUrl(), this.getToken());
}
/**
* The method return tru if the user is logged in
* @returns {boolean}
*/
isLoggedIn(): boolean {
return !!localStorage.getItem('token');
} }
/** /**
@@ -59,95 +48,153 @@ export class AlfrescoAuthenticationService {
* @param password * @param password
* @returns {Observable<R>|Observable<T>} * @returns {Observable<R>|Observable<T>}
*/ */
login(username: string, password: string): Observable<string> { login(username: string, password: string, providers: string []): Observable<string> {
return this.loginPost(username, password); localStorage.clear();
if (providers.length === 0) {
return Observable.throw('No providers defined');
} else {
this.createProviderInstance(providers);
return this.performeLogin(username, password);
}
} }
/** /**
* Perform a login on behalf of the user and store the ticket returned * Perform a login on behalf of the user for the different provider instance
* *
* @param username * @param username
* @param password * @param password
* @returns {Observable<R>|Observable<T>} * @returns {Observable<R>|Observable<T>}
*/ */
loginPost(username: string, password: string) { private performeLogin(username: string, password: string): Observable<any> {
return Observable.fromPromise(this.getCreateTicketPromise(username, password)) let observableBatch = [];
.map(res => <any> res) if (this.providersInstance.length !== 0) {
.do(response => { this.providersInstance.forEach((authInstance) => {
this.saveToken(response.entry.id); observableBatch.push(authInstance.login(username, password));
return this.getToken(); });
}) return Observable.create(observer => {
.catch(this.handleError); Observable.forkJoin(observableBatch).subscribe(
} (response: any[]) => {
this.performeSaveToken();
getCreateTicketPromise(username: string, password: string) { /*response.forEach((res) => {
let apiInstance = new AlfrescoApi.Auth.AuthenticationApi(this.getAlfrescoClient()); this.performeSaveToken(res.name, res.token);
let loginRequest = new AlfrescoApi.Auth.LoginRequest(); });*/
loginRequest.userId = username; observer.next(response);
loginRequest.password = password; },
return apiInstance.createTicket(loginRequest); (err: any) => {
} observer.error(new Error(err));
});
/** });
* Delete the current login ticket from the server } else {
* return Observable.throw('No providers defined');
* @returns {Observable<R>|Observable<T>}
*/
loginDelete() {
return Observable.fromPromise(this.getDeleteTicketPromise())
.map(res => <any> res)
.do(response => {
this.removeToken();
this.saveToken('');
})
.catch(this.handleError);
}
getDeleteTicketPromise() {
let apiInstance = new AlfrescoApi.Auth.AuthenticationApi(this.getAlfrescoClient());
return apiInstance.deleteTicket();
}
/**
* Return the token stored in the localStorage
* @param token
*/
public getToken (): string {
return localStorage.getItem('token');
}
/**
* The method save the toke in the localStorage
* @param token
*/
public saveToken(token): void {
if (token) {
localStorage.setItem('token', token);
} }
} }
/** /**
* Remove the login token from localStorage * The method return tru if the user is logged in
* @returns {boolean}
*/ */
public removeToken(): void { isLoggedIn(type: string = 'ECM'): boolean {
localStorage.removeItem('token'); let auth: AbstractAuthentication = this.findProviderInstance(type);
if (auth) {
return auth.isLoggedIn();
}
return false;
}
/**
* Return the token stored in the localStorage of the specific provider type
* @param token
*/
public getToken(type: string = 'ECM'): string {
let auth: AbstractAuthentication = this.findProviderInstance(type);
if (auth) {
return auth.getToken();
}
return '';
}
/**
* Save the token calling the method of the specific provider type
* @param providerName
* @param token
*/
private performeSaveToken() {
/* let auth: AbstractAuthentication = this.findProviderInstance(type);
if (auth) {
auth.saveToken();
}
*/
this.providersInstance.forEach((authInstance) => {
authInstance.saveToken();
});
} }
/** /**
* The method remove the token from the local storage * The method remove the token from the local storage
* @returns {Observable<T>} * @returns {Observable<T>}
*/ */
public logout() { public logout(): Observable<string> {
return this.loginDelete(); if (this.providersInstance.length === 0) {
return Observable.throw('No providers defined');
} else {
return this.performeLogout();
}
} }
/** /**
* The method write the error in the console browser * Perform a logout on behalf of the user for the different provider instance
* @param error *
* @returns {ErrorObservable} * @param username
* @param password
* @returns {Observable<R>|Observable<T>}
*/ */
private handleError(error: Response) { private performeLogout(): Observable<any> {
console.error('Error when logging in', error); let observableBatch = [];
return Observable.throw(error || 'Server error'); this.providersInstance.forEach((authInstance) => {
observableBatch.push(authInstance.logout());
});
return Observable.create(observer => {
Observable.forkJoin(observableBatch).subscribe(
(response: any[]) => {
observer.next(response);
},
(err: any) => {
observer.error(new Error(err));
});
});
} }
/**
* Create the provider instance using a Factory
* @param providers - list of the providers like ECM BPM
*/
public createProviderInstance(providers: string []): void {
if (this.providersInstance.length === 0) {
providers.forEach((provider) => {
let authInstance: AbstractAuthentication = AuthenticationFactory.createAuth(
this.alfrescoSettingsService, this.http, provider);
if (authInstance) {
this.providersInstance.push(authInstance);
}
});
}
}
/**
* Find the provider by type and return it
* @param type
* @returns {AbstractAuthentication}
*/
private findProviderInstance(type: string): AbstractAuthentication {
let auth: AbstractAuthentication = null;
if (this.providersInstance && this.providersInstance.length !== 0) {
this.providersInstance.forEach((provider) => {
if (provider.TYPE === type) {
auth = provider;
}
});
}
return auth;
}
} }

View File

@@ -20,6 +20,7 @@ import { ReflectiveInjector } from '@angular/core';
import { AlfrescoSettingsService } from './AlfrescoSettingsService.service'; import { AlfrescoSettingsService } from './AlfrescoSettingsService.service';
import { AlfrescoAuthenticationService } from './AlfrescoAuthenticationService.service'; import { AlfrescoAuthenticationService } from './AlfrescoAuthenticationService.service';
import { AlfrescoContentService } from './AlfrescoContentService.service'; import { AlfrescoContentService } from './AlfrescoContentService.service';
import { HTTP_PROVIDERS } from '@angular/http';
describe('AlfrescoContentService', () => { describe('AlfrescoContentService', () => {
@@ -28,6 +29,7 @@ describe('AlfrescoContentService', () => {
beforeEach(() => { beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([ injector = ReflectiveInjector.resolveAndCreate([
HTTP_PROVIDERS,
AlfrescoContentService, AlfrescoContentService,
AlfrescoAuthenticationService, AlfrescoAuthenticationService,
AlfrescoSettingsService AlfrescoSettingsService

View File

@@ -32,7 +32,9 @@ import {
<input id="token" type="text" size="48" (change)="updateHost()" [(ngModel)]="host"><br><br> <input id="token" type="text" size="48" (change)="updateHost()" [(ngModel)]="host"><br><br>
{{ status }} {{ status }}
<hr> <hr>
<alfresco-login (onSuccess)="mySuccessMethod($event)" (onError)="myErrorMethod($event)"></alfresco-login>`,
<alfresco-login [providers]="providers" (onSuccess)="mySuccessMethod($event)"
(onError)="myErrorMethod($event)"></alfresco-login>`,
directives: [AlfrescoLoginComponent] directives: [AlfrescoLoginComponent]
}) })
export class AppComponent { export class AppComponent {
@@ -43,6 +45,8 @@ export class AppComponent {
public status: string = ''; public status: string = '';
public providers: string [] = ['ECM'];
constructor(public auth: AlfrescoAuthenticationService, constructor(public auth: AlfrescoAuthenticationService,
private alfrescoSettingsService: AlfrescoSettingsService) { private alfrescoSettingsService: AlfrescoSettingsService) {
alfrescoSettingsService.host = this.host; alfrescoSettingsService.host = this.host;

View File

@@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { Component, Output, EventEmitter } from '@angular/core'; import { Component, Input, Output, EventEmitter } from '@angular/core';
import { FORM_DIRECTIVES, ControlGroup, FormBuilder, Validators } from '@angular/common'; import { FORM_DIRECTIVES, ControlGroup, FormBuilder, Validators } from '@angular/common';
import { import {
AlfrescoTranslationService, AlfrescoTranslationService,
@@ -41,6 +41,9 @@ export class AlfrescoLoginComponent {
isPasswordShow: boolean = false; isPasswordShow: boolean = false;
@Input()
providers: string [] ;
@Output() @Output()
onSuccess = new EventEmitter(); onSuccess = new EventEmitter();
@Output() @Output()
@@ -102,7 +105,7 @@ export class AlfrescoLoginComponent {
if (event) { if (event) {
event.preventDefault(); event.preventDefault();
} }
this.auth.login(value.username, value.password) this.auth.login(value.username, value.password, this.providers)
.subscribe( .subscribe(
(token: any) => { (token: any) => {
this.success = true; this.success = true;