mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
[ADF-2795] SSO implicitflow (#3332)
* Enable OAUTH2 * Create SSO services * SSO improvements * Rollback sso login change * Add SSO configuration from Setting component * Refactoring * Remove login ECM/BPM toggle and move use the userpreference instead of store * fix host setting unit test * Fix unit test missing instance * use the Js api oauth * add logout component and clean sso not used class * fix dependencies cicle * add translation settings * fix style setting page * clean * JS APi should receive the oauth config from the userPreference and not from the config file * change login if SSO is present * missing spaces * add sso test in login component * add logout directive new properties test * Improve host setting and remove library reference * fix login test * Remove unused code * Fix authentication unit test * fix authguard unit test * fix csrf check login component * fix unit test core and demo shell * remove
This commit is contained in:
committed by
Eugenio Romano
parent
3a6c12e624
commit
f8e92b2fb0
@@ -6,6 +6,16 @@
|
|||||||
"PROPERTIES": "Properties",
|
"PROPERTIES": "Properties",
|
||||||
"VERSIONS": "Versions"
|
"VERSIONS": "Versions"
|
||||||
},
|
},
|
||||||
|
"HOME": {
|
||||||
|
"TITLE": "Angular components for Alfresco",
|
||||||
|
"DOCUMENTATION": "Documentation"
|
||||||
|
},
|
||||||
|
"LOGOUT": {
|
||||||
|
"TITLE": "Logout Page",
|
||||||
|
"SUB_TITLE": "You are now logged out",
|
||||||
|
"LOGIN": "Login",
|
||||||
|
"HOME": "Home"
|
||||||
|
},
|
||||||
"ADF_VERSION_MANAGER": {
|
"ADF_VERSION_MANAGER": {
|
||||||
"ALLOW_DELETE": "Allow delete",
|
"ALLOW_DELETE": "Allow delete",
|
||||||
"SHOW_COMMENTS" : "Show comments on versions",
|
"SHOW_COMMENTS" : "Show comments on versions",
|
||||||
|
|||||||
@@ -2,7 +2,18 @@
|
|||||||
"$schema": "../../lib/core/app-config/schema.json",
|
"$schema": "../../lib/core/app-config/schema.json",
|
||||||
"ecmHost": "http://{hostname}:{port}",
|
"ecmHost": "http://{hostname}:{port}",
|
||||||
"bpmHost": "http://{hostname}:{port}",
|
"bpmHost": "http://{hostname}:{port}",
|
||||||
|
"providers": "OAUTH",
|
||||||
"contextRootBpm": "activiti-app",
|
"contextRootBpm": "activiti-app",
|
||||||
|
"oauth2": {
|
||||||
|
"host": "YOUR_AUTH_SERVER",
|
||||||
|
"clientId": "activiti",
|
||||||
|
"scope": "openid",
|
||||||
|
"secret": "",
|
||||||
|
"implicitFlow": true,
|
||||||
|
"silentLogin": true,
|
||||||
|
"redirectUri": "/",
|
||||||
|
"redirectUriLogout": "/logout"
|
||||||
|
},
|
||||||
"application": {
|
"application": {
|
||||||
"name": "Alfresco ADF Application",
|
"name": "Alfresco ADF Application",
|
||||||
"copyright": "© 2016 - 2018 Alfresco Software, Inc. All Rights Reserved."
|
"copyright": "© 2016 - 2018 Alfresco Software, Inc. All Rights Reserved."
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
|
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
|
||||||
import { AlfrescoApiService, SettingsService, PageTitleService, StorageService } from '@alfresco/adf-core';
|
import { AlfrescoApiService, PageTitleService } from '@alfresco/adf-core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -27,15 +27,12 @@ import { Router } from '@angular/router';
|
|||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
|
|
||||||
constructor(private settingsService: SettingsService,
|
constructor(private pageTitleService: PageTitleService,
|
||||||
private storage: StorageService,
|
|
||||||
private pageTitleService: PageTitleService,
|
|
||||||
private alfrescoApiService: AlfrescoApiService,
|
private alfrescoApiService: AlfrescoApiService,
|
||||||
private router: Router) {
|
private router: Router) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.setProvider();
|
|
||||||
|
|
||||||
this.pageTitleService.setTitle('title');
|
this.pageTitleService.setTitle('title');
|
||||||
|
|
||||||
@@ -46,10 +43,4 @@ export class AppComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private setProvider() {
|
|
||||||
if (this.storage.hasItem(`providers`)) {
|
|
||||||
this.settingsService.setProviders(this.storage.getItem(`providers`));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { AppComponent } from './app.component';
|
|||||||
import { AdfModule } from './adf.module';
|
import { AdfModule } from './adf.module';
|
||||||
import { MaterialModule } from './material.module';
|
import { MaterialModule } from './material.module';
|
||||||
import { LoginComponent } from './components/login/login.component';
|
import { LoginComponent } from './components/login/login.component';
|
||||||
|
import { LogoutComponent } from './components/logout/logout.component';
|
||||||
import { SettingsComponent } from './components/settings/settings.component';
|
import { SettingsComponent } from './components/settings/settings.component';
|
||||||
import { AppLayoutComponent } from './components/app-layout/app-layout.component';
|
import { AppLayoutComponent } from './components/app-layout/app-layout.component';
|
||||||
import { HomeComponent } from './components/home/home.component';
|
import { HomeComponent } from './components/home/home.component';
|
||||||
@@ -71,6 +72,7 @@ import { NotificationsComponent } from './components/notifications/notifications
|
|||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
LoginComponent,
|
LoginComponent,
|
||||||
|
LogoutComponent,
|
||||||
SettingsComponent,
|
SettingsComponent,
|
||||||
AppLayoutComponent,
|
AppLayoutComponent,
|
||||||
HomeComponent,
|
HomeComponent,
|
||||||
|
|||||||
@@ -17,11 +17,12 @@
|
|||||||
|
|
||||||
import { ModuleWithProviders } from '@angular/core';
|
import { ModuleWithProviders } from '@angular/core';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
import { AuthGuard, AuthGuardBpm, AuthGuardEcm, ErrorContentComponent } from '@alfresco/adf-core';
|
import { AuthGuard, AuthGuardEcm, ErrorContentComponent, AuthGuardBpm } from '@alfresco/adf-core';
|
||||||
import { AppLayoutComponent } from './components/app-layout/app-layout.component';
|
import { AppLayoutComponent } from './components/app-layout/app-layout.component';
|
||||||
import { LoginComponent } from './components/login/login.component';
|
import { LoginComponent } from './components/login/login.component';
|
||||||
import { SettingsComponent } from './components/settings/settings.component';
|
import { SettingsComponent } from './components/settings/settings.component';
|
||||||
import { HomeComponent } from './components/home/home.component';
|
import { HomeComponent } from './components/home/home.component';
|
||||||
|
import { LogoutComponent } from './components/logout/logout.component';
|
||||||
import { AboutComponent } from './components/about/about.component';
|
import { AboutComponent } from './components/about/about.component';
|
||||||
import { ProcessServiceComponent } from './components/process-service/process-service.component';
|
import { ProcessServiceComponent } from './components/process-service/process-service.component';
|
||||||
import { ShowDiagramComponent } from './components/process-service/show-diagram.component';
|
import { ShowDiagramComponent } from './components/process-service/show-diagram.component';
|
||||||
@@ -52,8 +53,9 @@ import { NotificationsComponent } from './components/notifications/notifications
|
|||||||
|
|
||||||
export const appRoutes: Routes = [
|
export const appRoutes: Routes = [
|
||||||
{ path: 'login', component: LoginComponent },
|
{ path: 'login', component: LoginComponent },
|
||||||
|
{ path: 'logout', component: LogoutComponent },
|
||||||
{ path: 'settings', component: SettingsComponent },
|
{ path: 'settings', component: SettingsComponent },
|
||||||
{ path: 'files/:nodeId/view', component: FileViewComponent, canActivate: [AuthGuardEcm], outlet: 'overlay' },
|
{ path: 'files/:nodeId/view', component: FileViewComponent, canActivate: [ AuthGuardEcm ], outlet: 'overlay' },
|
||||||
{ path: 'preview/blob', component: BlobPreviewComponent, outlet: 'overlay', pathMatch: 'full' },
|
{ path: 'preview/blob', component: BlobPreviewComponent, outlet: 'overlay', pathMatch: 'full' },
|
||||||
{ path: 'preview/s/:id', component: SharedLinkViewComponent },
|
{ path: 'preview/s/:id', component: SharedLinkViewComponent },
|
||||||
{
|
{
|
||||||
@@ -226,4 +228,4 @@ export const appRoutes: Routes = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
|
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes, { initialNavigation: true });
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
<mat-icon matListIcon class="sidenav-menu-icon">{{link.icon}}</mat-icon>
|
<mat-icon matListIcon class="sidenav-menu-icon">{{link.icon}}</mat-icon>
|
||||||
<div class="sidenav-menu-label" *ngIf="!isMenuMinimized()">{{link.title | translate }}</div>
|
<div class="sidenav-menu-label" *ngIf="!isMenuMinimized()">{{link.title | translate }}</div>
|
||||||
</a>
|
</a>
|
||||||
<a mat-list-item adf-logout class="adf-sidenav-link">
|
<a mat-list-item adf-logout [enabelRedirect]="enabelRedirect" redirectUri="/logout" class="adf-sidenav-link">
|
||||||
<mat-icon matListIcon class="sidenav-menu-icon">exit_to_app</mat-icon>
|
<mat-icon matListIcon class="sidenav-menu-icon">exit_to_app</mat-icon>
|
||||||
<div class="sidenav-menu-label" *ngIf="!isMenuMinimized()">Logout</div>
|
<div class="sidenav-menu-label" *ngIf="!isMenuMinimized()">Logout</div>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
|
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
|
||||||
import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core';
|
import { UserPreferencesService, AppConfigService, AlfrescoApiService } from '@alfresco/adf-core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: 'app-layout.component.html',
|
templateUrl: 'app-layout.component.html',
|
||||||
@@ -54,6 +54,7 @@ export class AppLayoutComponent implements OnInit {
|
|||||||
|
|
||||||
expandedSidenav = false;
|
expandedSidenav = false;
|
||||||
|
|
||||||
|
enabelRedirect = true;
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
const expand = this.config.get<boolean>('sideNav.expandedSidenav');
|
const expand = this.config.get<boolean>('sideNav.expandedSidenav');
|
||||||
@@ -65,7 +66,11 @@ export class AppLayoutComponent implements OnInit {
|
|||||||
this.expandedSidenav = expand;
|
this.expandedSidenav = expand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
constructor( private userpreference: UserPreferencesService, private config: AppConfigService) {
|
|
||||||
|
constructor(private userpreference: UserPreferencesService, private config: AppConfigService, private alfrescoApiService: AlfrescoApiService) {
|
||||||
|
if (this.alfrescoApiService.getInstance().isOauthConfiguration()) {
|
||||||
|
this.enabelRedirect = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(state) {
|
setState(state) {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import { MatDialog } from '@angular/material';
|
|||||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||||
import { MinimalNodeEntity, NodePaging, Pagination, MinimalNodeEntryEntity, SiteEntry } from 'alfresco-js-api';
|
import { MinimalNodeEntity, NodePaging, Pagination, MinimalNodeEntryEntity, SiteEntry } from 'alfresco-js-api';
|
||||||
import {
|
import {
|
||||||
AuthenticationService, AppConfigService, ContentService, TranslationService,
|
AuthenticationService, ContentService, TranslationService,
|
||||||
FileUploadEvent, FolderCreatedEvent, LogService, NotificationService,
|
FileUploadEvent, FolderCreatedEvent, LogService, NotificationService,
|
||||||
UploadService, DataColumn, DataRow, UserPreferencesService,
|
UploadService, DataColumn, DataRow, UserPreferencesService,
|
||||||
PaginationComponent, FormValues, DisplayMode, UserPreferenceValues, InfinitePaginationComponent
|
PaginationComponent, FormValues, DisplayMode, UserPreferenceValues, InfinitePaginationComponent
|
||||||
@@ -56,7 +56,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
displayMode = DisplayMode.List;
|
displayMode = DisplayMode.List;
|
||||||
includeFields = ['isFavorite', 'isLocked', 'aspectNames'];
|
includeFields = ['isFavorite', 'isLocked', 'aspectNames'];
|
||||||
|
|
||||||
baseShareUrl = this.appConfig.get<string>('ecmHost') + '/preview/s/';
|
baseShareUrl = this.preference.ecmHost + '/preview/s/';
|
||||||
|
|
||||||
toolbarColor = 'default';
|
toolbarColor = 'default';
|
||||||
|
|
||||||
@@ -191,7 +191,6 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
private router: Router,
|
private router: Router,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private preference: UserPreferencesService,
|
private preference: UserPreferencesService,
|
||||||
private appConfig: AppConfigService,
|
|
||||||
private preview: PreviewService,
|
private preview: PreviewService,
|
||||||
@Optional() private route: ActivatedRoute,
|
@Optional() private route: ActivatedRoute,
|
||||||
public authenticationService: AuthenticationService) {
|
public authenticationService: AuthenticationService) {
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
<div class="adf-home-section ad">
|
<div class="adf-home-section ad">
|
||||||
<div class="adf-home-headline">
|
<div class="adf-home-headline">
|
||||||
<h1 class="mat-h1">ADF</h1>
|
<h1 class="mat-h1">ADF</h1>
|
||||||
<h2> Angular components for Alfresco</h2>
|
<h2>{{ 'APP.HOME.TITLE' | translate}}</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="adf-home-start">
|
<div class="adf-home-start">
|
||||||
<a mat-raised-button class="adf-home-docs-button adf-primary-color" href="https://github.com/Alfresco/alfresco-ng2-components/tree/master/docs">DOCS</a>
|
<a mat-raised-button class="adf-home-docs-button adf-primary-color" href="https://github.com/Alfresco/alfresco-ng2-components/tree/master/docs">{{ 'APP.HOME.DOCUMENTATION' | translate}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@@ -1,24 +1,6 @@
|
|||||||
<!--BPM, ECN AND CSRF TOGGLE-->
|
<!--BPM, ECN AND CSRF TOGGLE-->
|
||||||
|
|
||||||
<div class="settings">
|
<div class="settings">
|
||||||
<p class="toggle">
|
|
||||||
<mat-slide-toggle
|
|
||||||
id="switch1"
|
|
||||||
[color]="'primary'"
|
|
||||||
(change)="toggleECM()"
|
|
||||||
[checked]="isECM">
|
|
||||||
{{ 'LOGIN.CONTENT_SERVICES'| translate }}
|
|
||||||
</mat-slide-toggle>
|
|
||||||
</p>
|
|
||||||
<p class="toggle">
|
|
||||||
<mat-slide-toggle
|
|
||||||
id="switch2"
|
|
||||||
[color]="'primary'"
|
|
||||||
(change)="toggleBPM()"
|
|
||||||
[checked]="isBPM">
|
|
||||||
{{ 'LOGIN.PROCESS_SERVICES'| translate }}
|
|
||||||
</mat-slide-toggle>
|
|
||||||
</p>
|
|
||||||
<p class="toggle">
|
<p class="toggle">
|
||||||
<mat-slide-toggle
|
<mat-slide-toggle
|
||||||
id="switch3"
|
id="switch3"
|
||||||
@@ -57,24 +39,6 @@
|
|||||||
(success)="onLogin($event)"
|
(success)="onLogin($event)"
|
||||||
(error)="onError($event)">
|
(error)="onError($event)">
|
||||||
<div class="mobile-settings">
|
<div class="mobile-settings">
|
||||||
<p>
|
|
||||||
<mat-slide-toggle
|
|
||||||
id="switch1-mobile"
|
|
||||||
[color]="'primary'"
|
|
||||||
(change)="toggleECM()"
|
|
||||||
[checked]="isECM">
|
|
||||||
{{ 'LOGIN.CONTENT_SERVICES'| translate }}
|
|
||||||
</mat-slide-toggle>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<mat-slide-toggle
|
|
||||||
id="switch2-mobile"
|
|
||||||
[color]="'primary'"
|
|
||||||
(change)="toggleBPM()"
|
|
||||||
[checked]="isBPM">
|
|
||||||
{{ 'LOGIN.PROCESS_SERVICES'| translate }}
|
|
||||||
</mat-slide-toggle>
|
|
||||||
</p>
|
|
||||||
<p>
|
<p>
|
||||||
<mat-slide-toggle
|
<mat-slide-toggle
|
||||||
id="switch3-mobile"
|
id="switch3-mobile"
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||||
import { Validators } from '@angular/forms';
|
import { Validators } from '@angular/forms';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { LogService, StorageService } from '@alfresco/adf-core';
|
import { LogService, UserPreferencesService } from '@alfresco/adf-core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-login',
|
selector: 'app-login',
|
||||||
@@ -34,13 +34,11 @@ export class LoginComponent implements OnInit {
|
|||||||
customValidation: any;
|
customValidation: any;
|
||||||
|
|
||||||
disableCsrf = false;
|
disableCsrf = false;
|
||||||
isECM = true;
|
|
||||||
isBPM = false;
|
|
||||||
showFooter = true;
|
showFooter = true;
|
||||||
customMinLength = 2;
|
customMinLength = 2;
|
||||||
|
|
||||||
constructor(private router: Router,
|
constructor(private router: Router,
|
||||||
private storage: StorageService,
|
private userPreference: UserPreferencesService,
|
||||||
private logService: LogService) {
|
private logService: LogService) {
|
||||||
this.customValidation = {
|
this.customValidation = {
|
||||||
username: ['', Validators.compose([Validators.required, Validators.minLength(this.customMinLength)])],
|
username: ['', Validators.compose([Validators.required, Validators.minLength(this.customMinLength)])],
|
||||||
@@ -53,24 +51,11 @@ export class LoginComponent implements OnInit {
|
|||||||
this.alfrescologin.addCustomValidationError('username', 'minlength', 'LOGIN.MESSAGES.USERNAME-MIN', {minLength: this.customMinLength});
|
this.alfrescologin.addCustomValidationError('username', 'minlength', 'LOGIN.MESSAGES.USERNAME-MIN', {minLength: this.customMinLength});
|
||||||
this.alfrescologin.addCustomValidationError('password', 'required', 'LOGIN.MESSAGES.PASSWORD-REQUIRED');
|
this.alfrescologin.addCustomValidationError('password', 'required', 'LOGIN.MESSAGES.PASSWORD-REQUIRED');
|
||||||
|
|
||||||
if (this.storage.hasItem('providers')) {
|
|
||||||
this.providers = this.storage.getItem('providers');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.initProviders();
|
this.initProviders();
|
||||||
}
|
}
|
||||||
|
|
||||||
initProviders() {
|
initProviders() {
|
||||||
if (this.providers === 'BPM') {
|
this.providers = this.userPreference.providers;
|
||||||
this.isECM = false;
|
|
||||||
this.isBPM = true;
|
|
||||||
} else if (this.providers === 'ECM') {
|
|
||||||
this.isECM = true;
|
|
||||||
this.isBPM = false;
|
|
||||||
} else if (this.providers === 'ALL') {
|
|
||||||
this.isECM = true;
|
|
||||||
this.isBPM = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onLogin($event) {
|
onLogin($event) {
|
||||||
@@ -81,16 +66,6 @@ export class LoginComponent implements OnInit {
|
|||||||
this.logService.error($event);
|
this.logService.error($event);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleECM() {
|
|
||||||
this.isECM = !this.isECM;
|
|
||||||
this.storage.setItem('providers', this.updateProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleBPM() {
|
|
||||||
this.isBPM = !this.isBPM;
|
|
||||||
this.storage.setItem('providers', this.updateProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleCSRF() {
|
toggleCSRF() {
|
||||||
this.disableCsrf = !this.disableCsrf;
|
this.disableCsrf = !this.disableCsrf;
|
||||||
}
|
}
|
||||||
@@ -99,26 +74,6 @@ export class LoginComponent implements OnInit {
|
|||||||
this.showFooter = !this.showFooter;
|
this.showFooter = !this.showFooter;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateProvider() {
|
|
||||||
if (this.isBPM && this.isECM) {
|
|
||||||
this.providers = 'ALL';
|
|
||||||
return this.providers;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isECM) {
|
|
||||||
this.providers = 'ECM';
|
|
||||||
return this.providers;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isBPM) {
|
|
||||||
this.providers = 'BPM';
|
|
||||||
return this.providers;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.providers = '';
|
|
||||||
return this.providers;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkForm(event: any) {
|
checkForm(event: any) {
|
||||||
const values = event.values;
|
const values = event.values;
|
||||||
this.logService.log(values);
|
this.logService.log(values);
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<header class="adf-logout-background">
|
||||||
|
<div class="adf-logout-section">
|
||||||
|
<div class="adf-logout-headline">
|
||||||
|
<h1>{{ 'APP.LOGOUT.TITLE' | translate}}</h1>
|
||||||
|
<h2>{{ 'APP.LOGOUT.SUB_TITLE' | translate}}</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="adf-logout-login">
|
||||||
|
<a mat-raised-button class="adf-logout-docs-button adf-primary-color"
|
||||||
|
href="/login">{{ 'APP.LOGOUT.LOGIN' | translate}}</a>
|
||||||
|
</div>
|
||||||
|
<div class="adf-logout-home">
|
||||||
|
<a mat-raised-button class="adf-logout-docs-button adf-primary-color"
|
||||||
|
href="/">{{ 'APP.LOGOUT.HOME' | translate}}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
:host {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-logout-header-background {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-logout-section {
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-logout-headline {
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 56px;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 56px;
|
||||||
|
margin: 15px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 28px;
|
||||||
|
margin: 15px 0 25px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-logout-docs-button {
|
||||||
|
margin: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-logout-login {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*!
|
||||||
|
* @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 { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-logout',
|
||||||
|
templateUrl: './logout.component.html',
|
||||||
|
styleUrls: ['./logout.component.scss']
|
||||||
|
})
|
||||||
|
export class LogoutComponent {}
|
||||||
@@ -1 +1 @@
|
|||||||
<adf-host-settings (error)="onError($event)"></adf-host-settings>
|
<adf-host-settings (cancel)="onCancel($event)" (success)="onSuccess($event)" (error)="onError($event)"></adf-host-settings>
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { LogService } from '@alfresco/adf-core';
|
import { LogService, AuthenticationService, AlfrescoApiService } from '@alfresco/adf-core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings',
|
selector: 'app-settings',
|
||||||
@@ -24,10 +25,23 @@ import { LogService } from '@alfresco/adf-core';
|
|||||||
})
|
})
|
||||||
export class SettingsComponent {
|
export class SettingsComponent {
|
||||||
|
|
||||||
constructor(public logService: LogService) {
|
constructor(private router: Router,
|
||||||
|
private authService: AuthenticationService,
|
||||||
|
private alfrescoApiService: AlfrescoApiService,
|
||||||
|
public logService: LogService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onError(error: string) {
|
onError(error: string) {
|
||||||
this.logService.log(error);
|
this.logService.log(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onCancel() {
|
||||||
|
this.router.navigate(['/']);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSuccess() {
|
||||||
|
this.authService.removeTicket();
|
||||||
|
this.alfrescoApiService.reset();
|
||||||
|
this.router.navigate(['/']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,14 @@ Logs the user out when the decorated element is clicked.
|
|||||||
<button adf-logout>Logout</button>
|
<button adf-logout>Logout</button>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Properties
|
||||||
|
|
||||||
|
| Name | Type | Default value | Description |
|
||||||
|
| -- | -- | -- | -- |
|
||||||
|
| redirectUri | `string` | 'login' | Uri to be redirect after the logout |
|
||||||
|
| enabelRedirect | `boolean` | 'true' | enable/disable redirect after logout |
|
||||||
|
|
||||||
|
|
||||||
## See also
|
## See also
|
||||||
|
|
||||||
- [Login component](login.component.md)
|
- [Login component](login.component.md)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ let button = new MenuButton({
|
|||||||
isVisible: this.isItemValid.bind(this)
|
isVisible: this.isItemValid.bind(this)
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
## Class members
|
||||||
|
|
||||||
## Properties
|
## Properties
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ export class FolderDialogComponent implements OnInit {
|
|||||||
@Output()
|
@Output()
|
||||||
error: EventEmitter<any> = new EventEmitter<any>();
|
error: EventEmitter<any> = new EventEmitter<any>();
|
||||||
|
|
||||||
|
/** Emitted when the edit/create folder is successfully created/mmodified
|
||||||
|
*/
|
||||||
@Output()
|
@Output()
|
||||||
success: EventEmitter<any> = new EventEmitter<MinimalNodeEntryEntity>();
|
success: EventEmitter<any> = new EventEmitter<MinimalNodeEntryEntity>();
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ import {
|
|||||||
AppConfigService,
|
AppConfigService,
|
||||||
ContentService,
|
ContentService,
|
||||||
StorageService,
|
StorageService,
|
||||||
|
UserPreferencesService,
|
||||||
|
setupTestBed,
|
||||||
|
CoreModule,
|
||||||
TranslationMock
|
TranslationMock
|
||||||
} from '@alfresco/adf-core';
|
} from '@alfresco/adf-core';
|
||||||
import { FileNode, FolderNode } from '../../mock';
|
import { FileNode, FolderNode } from '../../mock';
|
||||||
@@ -28,16 +31,25 @@ import { DocumentActionsService } from './document-actions.service';
|
|||||||
import { DocumentListService } from './document-list.service';
|
import { DocumentListService } from './document-list.service';
|
||||||
import { NodeActionsService } from './node-actions.service';
|
import { NodeActionsService } from './node-actions.service';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
describe('DocumentActionsService', () => {
|
describe('DocumentActionsService', () => {
|
||||||
|
|
||||||
let service: DocumentActionsService;
|
let service: DocumentActionsService;
|
||||||
let documentListService: DocumentListService;
|
let documentListService: DocumentListService;
|
||||||
let nodeActionsService: NodeActionsService;
|
let nodeActionsService: NodeActionsService;
|
||||||
|
let userPreferences;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
CoreModule.forRoot()
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
userPreferences = TestBed.get(UserPreferencesService);
|
||||||
let contentService = new ContentService(null, null, null, null);
|
let contentService = new ContentService(null, null, null, null);
|
||||||
let alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
|
let alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), userPreferences, new StorageService());
|
||||||
|
|
||||||
documentListService = new DocumentListService(null, contentService, alfrescoApiService, null, null);
|
documentListService = new DocumentListService(null, contentService, alfrescoApiService, null, null);
|
||||||
service = new DocumentActionsService(null, null, new TranslationMock(), documentListService, contentService);
|
service = new DocumentActionsService(null, null, new TranslationMock(), documentListService, contentService);
|
||||||
|
|||||||
@@ -16,8 +16,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { AlfrescoApiServiceMock, AlfrescoApiService,
|
import { AlfrescoApiServiceMock, AlfrescoApiService,
|
||||||
AppConfigService, StorageService, ContentService } from '@alfresco/adf-core';
|
AppConfigService, StorageService, ContentService, UserPreferencesService, setupTestBed, CoreModule } from '@alfresco/adf-core';
|
||||||
import { DocumentListService } from './document-list.service';
|
import { DocumentListService } from './document-list.service';
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
declare let jasmine: any;
|
declare let jasmine: any;
|
||||||
|
|
||||||
@@ -25,6 +26,7 @@ describe('DocumentListService', () => {
|
|||||||
|
|
||||||
let service: DocumentListService;
|
let service: DocumentListService;
|
||||||
let alfrescoApiService: AlfrescoApiService;
|
let alfrescoApiService: AlfrescoApiService;
|
||||||
|
let userPreferences: UserPreferencesService;
|
||||||
|
|
||||||
let fakeEntryNode = {
|
let fakeEntryNode = {
|
||||||
'entry': {
|
'entry': {
|
||||||
@@ -87,9 +89,17 @@ describe('DocumentListService', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
CoreModule.forRoot()
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
userPreferences = TestBed.get(UserPreferencesService);
|
||||||
|
|
||||||
let contentService = new ContentService(null, null, null, null);
|
let contentService = new ContentService(null, null, null, null);
|
||||||
alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
|
alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), userPreferences, new StorageService());
|
||||||
service = new DocumentListService(null, contentService, alfrescoApiService, null, null);
|
service = new DocumentListService(null, contentService, alfrescoApiService, null, null);
|
||||||
jasmine.Ajax.install();
|
jasmine.Ajax.install();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing';
|
||||||
import { AlfrescoApiServiceMock, AppConfigService, StorageService, ContentService, setupTestBed, CoreModule, TranslationMock } from '@alfresco/adf-core';
|
import { AlfrescoApiServiceMock, AppConfigService, StorageService, ContentService, setupTestBed, CoreModule, TranslationMock, UserPreferencesService } from '@alfresco/adf-core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { FileNode, FolderNode } from '../../mock';
|
import { FileNode, FolderNode } from '../../mock';
|
||||||
import { ContentActionHandler } from '../models/content-action.model';
|
import { ContentActionHandler } from '../models/content-action.model';
|
||||||
@@ -27,6 +27,7 @@ describe('FolderActionsService', () => {
|
|||||||
|
|
||||||
let service: FolderActionsService;
|
let service: FolderActionsService;
|
||||||
let documentListService: DocumentListService;
|
let documentListService: DocumentListService;
|
||||||
|
let userPreferences: UserPreferencesService;
|
||||||
|
|
||||||
setupTestBed({
|
setupTestBed({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -38,8 +39,10 @@ describe('FolderActionsService', () => {
|
|||||||
let appConfig: AppConfigService = TestBed.get(AppConfigService);
|
let appConfig: AppConfigService = TestBed.get(AppConfigService);
|
||||||
appConfig.config.ecmHost = 'http://localhost:9876/ecm';
|
appConfig.config.ecmHost = 'http://localhost:9876/ecm';
|
||||||
|
|
||||||
|
userPreferences = TestBed.get(UserPreferencesService);
|
||||||
|
|
||||||
let contentService = new ContentService(null, null, null, null);
|
let contentService = new ContentService(null, null, null, null);
|
||||||
let alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
|
let alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), userPreferences, new StorageService());
|
||||||
documentListService = new DocumentListService(null, contentService, alfrescoApiService, null, null);
|
documentListService = new DocumentListService(null, contentService, alfrescoApiService, null, null);
|
||||||
service = new FolderActionsService(null, documentListService, contentService, new TranslationMock());
|
service = new FolderActionsService(null, documentListService, contentService, new TranslationMock());
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,17 +15,27 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { AlfrescoApiServiceMock, AppConfigService, StorageService } from '@alfresco/adf-core';
|
import { AlfrescoApiServiceMock, AppConfigService, StorageService, setupTestBed, CoreModule, UserPreferencesService } from '@alfresco/adf-core';
|
||||||
import { RatingService } from './rating.service';
|
import { RatingService } from './rating.service';
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
declare let jasmine: any;
|
declare let jasmine: any;
|
||||||
|
|
||||||
describe('Rating service', () => {
|
describe('Rating service', () => {
|
||||||
|
|
||||||
let service;
|
let service;
|
||||||
|
let userPreferences: UserPreferencesService;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
CoreModule.forRoot()
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
service = new RatingService(new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()));
|
userPreferences = TestBed.get(UserPreferencesService);
|
||||||
|
|
||||||
|
service = new RatingService(new AlfrescoApiServiceMock(new AppConfigService(null), userPreferences, new StorageService()));
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@@ -15,17 +15,26 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService } from '@alfresco/adf-core';
|
import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService, setupTestBed, CoreModule, UserPreferencesService } from '@alfresco/adf-core';
|
||||||
import { TagService } from './tag.service';
|
import { TagService } from './tag.service';
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
declare let jasmine: any;
|
declare let jasmine: any;
|
||||||
|
|
||||||
describe('TagService', () => {
|
describe('TagService', () => {
|
||||||
|
|
||||||
let service: TagService;
|
let service: TagService;
|
||||||
|
let userPreferences: UserPreferencesService;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
CoreModule.forRoot()
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
service = new TagService(new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()), new LogService(new AppConfigService(null)));
|
userPreferences = TestBed.get(UserPreferencesService);
|
||||||
|
service = new TagService(new AlfrescoApiServiceMock(new AppConfigService(null), userPreferences, new StorageService()), new LogService(new AppConfigService(null)));
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@@ -18,10 +18,10 @@
|
|||||||
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
import { Http } from '@angular/http';
|
import { Http } from '@angular/http';
|
||||||
import { AuthenticationService } from '../services/authentication.service';
|
import { AuthenticationService } from '../services/authentication.service';
|
||||||
import { AppConfigService } from '../app-config/app-config.service';
|
|
||||||
import { BpmProductVersionModel, EcmProductVersionModel } from '../models/product-version.model';
|
import { BpmProductVersionModel, EcmProductVersionModel } from '../models/product-version.model';
|
||||||
import { DiscoveryApiService } from '../services/discovery-api.service';
|
import { DiscoveryApiService } from '../services/discovery-api.service';
|
||||||
import { ObjectDataTableAdapter } from '../datatable/data/object-datatable-adapter';
|
import { ObjectDataTableAdapter } from '../datatable/data/object-datatable-adapter';
|
||||||
|
import { UserPreferencesService } from '../services/user-preferences.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-about',
|
selector: 'adf-about',
|
||||||
@@ -44,7 +44,7 @@ export class AboutComponent implements OnInit {
|
|||||||
bpmVersion: BpmProductVersionModel = null;
|
bpmVersion: BpmProductVersionModel = null;
|
||||||
|
|
||||||
constructor(private http: Http,
|
constructor(private http: Http,
|
||||||
private appConfig: AppConfigService,
|
private userPreference: UserPreferencesService,
|
||||||
private authService: AuthenticationService,
|
private authService: AuthenticationService,
|
||||||
private discovery: DiscoveryApiService) {
|
private discovery: DiscoveryApiService) {
|
||||||
}
|
}
|
||||||
@@ -114,8 +114,8 @@ export class AboutComponent implements OnInit {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.ecmHost = this.appConfig.get<string>('ecmHost');
|
this.ecmHost = this.userPreference.ecmHost;
|
||||||
this.bpmHost = this.appConfig.get<string>('bpmHost');
|
this.bpmHost = this.userPreference.bpmHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
private gitHubLinkCreation(alfrescoPackagesTableRepresentation): void {
|
private gitHubLinkCreation(alfrescoPackagesTableRepresentation): void {
|
||||||
|
|||||||
@@ -461,12 +461,17 @@
|
|||||||
"oauth2": {
|
"oauth2": {
|
||||||
"description": "AUTH configuration parameters",
|
"description": "AUTH configuration parameters",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [ "host", "clientId", "secret" ],
|
"required": [ "host", "clientId", "secret", "scope" ],
|
||||||
"properties": {
|
"properties": {
|
||||||
"host": { "type": "string" },
|
"host": { "type": "string" },
|
||||||
|
"silentLogin": { "type": "boolean" },
|
||||||
"authPath": { "type": "string" },
|
"authPath": { "type": "string" },
|
||||||
"clientId": { "type": "string" },
|
"clientId": { "type": "string" },
|
||||||
"secret": { "type": "string" }
|
"secret": { "type": "string" },
|
||||||
|
"redirectUri": { "type": "string" },
|
||||||
|
"redirectUriLogout": { "type": "string" },
|
||||||
|
"silentRefreshRedirectUri": { "type": "string" },
|
||||||
|
"scope": { "type": "string" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"adf-version-manager": {
|
"adf-version-manager": {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
import { CommonModule, DatePipe } from '@angular/common';
|
import { CommonModule, DatePipe } from '@angular/common';
|
||||||
import { HttpClient, HttpClientModule } from '@angular/common/http';
|
import { HttpClient, HttpClientModule } from '@angular/common/http';
|
||||||
|
|
||||||
import { APP_INITIALIZER, NgModule, ModuleWithProviders } from '@angular/core';
|
import { APP_INITIALIZER, NgModule, ModuleWithProviders } from '@angular/core';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component } from '@angular/core';
|
import { Component, ContentChildren } from '@angular/core';
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
@@ -23,14 +23,20 @@ import { Observable } from 'rxjs/Observable';
|
|||||||
import { AuthenticationService } from '../services';
|
import { AuthenticationService } from '../services';
|
||||||
import { setupTestBed } from '../testing/setupTestBed';
|
import { setupTestBed } from '../testing/setupTestBed';
|
||||||
import { CoreModule } from '../core.module';
|
import { CoreModule } from '../core.module';
|
||||||
|
import { LogoutDirective } from './logout.directive';
|
||||||
|
|
||||||
describe('LogoutDirective', () => {
|
describe('LogoutDirective', () => {
|
||||||
|
|
||||||
|
describe('No input', () => {
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-test-component',
|
selector: 'adf-test-component',
|
||||||
template: '<button adf-logout></button>'
|
template: '<button adf-logout></button>'
|
||||||
})
|
})
|
||||||
class TestComponent {}
|
class TestComponent {
|
||||||
|
@ContentChildren(LogoutDirective)
|
||||||
|
logoutDirective: LogoutDirective;
|
||||||
|
}
|
||||||
|
|
||||||
let fixture: ComponentFixture<TestComponent>;
|
let fixture: ComponentFixture<TestComponent>;
|
||||||
let router: Router;
|
let router: Router;
|
||||||
@@ -61,7 +67,7 @@ describe('LogoutDirective', () => {
|
|||||||
button.click();
|
button.click();
|
||||||
|
|
||||||
expect(authService.logout).toHaveBeenCalled();
|
expect(authService.logout).toHaveBeenCalled();
|
||||||
expect(router.navigate).toHaveBeenCalledWith([ '/login' ]);
|
expect(router.navigate).toHaveBeenCalledWith(['/login']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should redirect to login even on logout error', () => {
|
it('should redirect to login even on logout error', () => {
|
||||||
@@ -72,7 +78,97 @@ describe('LogoutDirective', () => {
|
|||||||
button.click();
|
button.click();
|
||||||
|
|
||||||
expect(authService.logout).toHaveBeenCalled();
|
expect(authService.logout).toHaveBeenCalled();
|
||||||
expect(router.navigate).toHaveBeenCalledWith([ '/login' ]);
|
expect(router.navigate).toHaveBeenCalledWith(['/login']);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('redirectUri', () => {
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-test-component',
|
||||||
|
template: '<button adf-logout redirectUri="/myCustomUri"></button>'
|
||||||
|
})
|
||||||
|
class TestComponent {
|
||||||
|
@ContentChildren(LogoutDirective)
|
||||||
|
logoutDirective: LogoutDirective;
|
||||||
|
}
|
||||||
|
|
||||||
|
let fixture: ComponentFixture<TestComponent>;
|
||||||
|
let router: Router;
|
||||||
|
let authService: AuthenticationService;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
CoreModule.forRoot(),
|
||||||
|
RouterTestingModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
TestComponent
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
router = TestBed.get(Router);
|
||||||
|
authService = TestBed.get(AuthenticationService);
|
||||||
|
fixture = TestBed.createComponent(TestComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should redirect to the the input redirectUri on click if present', () => {
|
||||||
|
spyOn(router, 'navigate').and.callThrough();
|
||||||
|
spyOn(authService, 'logout').and.returnValue(Observable.of(true));
|
||||||
|
|
||||||
|
const button = fixture.nativeElement.querySelector('button');
|
||||||
|
button.click();
|
||||||
|
|
||||||
|
expect(authService.logout).toHaveBeenCalled();
|
||||||
|
expect(router.navigate).toHaveBeenCalledWith(['/myCustomUri']);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('redirectUri', () => {
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'adf-test-component',
|
||||||
|
template: '<button adf-logout [enabelRedirect]="false"></button>'
|
||||||
|
})
|
||||||
|
class TestComponent {
|
||||||
|
@ContentChildren(LogoutDirective)
|
||||||
|
logoutDirective: LogoutDirective;
|
||||||
|
}
|
||||||
|
|
||||||
|
let fixture: ComponentFixture<TestComponent>;
|
||||||
|
let router: Router;
|
||||||
|
let authService: AuthenticationService;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
CoreModule.forRoot(),
|
||||||
|
RouterTestingModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
TestComponent
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
router = TestBed.get(Router);
|
||||||
|
authService = TestBed.get(AuthenticationService);
|
||||||
|
fixture = TestBed.createComponent(TestComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not redirect if enabelRedirect is false', () => {
|
||||||
|
spyOn(router, 'navigate').and.callThrough();
|
||||||
|
spyOn(authService, 'logout').and.returnValue(Observable.of(true));
|
||||||
|
const button = fixture.nativeElement.querySelector('button');
|
||||||
|
button.click();
|
||||||
|
|
||||||
|
expect(authService.logout).toHaveBeenCalled();
|
||||||
|
expect(router.navigate).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Directive, ElementRef, OnInit, Renderer2 } from '@angular/core';
|
import { Input, Directive, ElementRef, OnInit, Renderer2 } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { AuthenticationService } from '../services/authentication.service';
|
import { AuthenticationService } from '../services/authentication.service';
|
||||||
|
|
||||||
@@ -24,8 +24,15 @@ import { AuthenticationService } from '../services/authentication.service';
|
|||||||
})
|
})
|
||||||
export class LogoutDirective implements OnInit {
|
export class LogoutDirective implements OnInit {
|
||||||
|
|
||||||
constructor(
|
/** Uri to be redirect after the logout default value login */
|
||||||
private elementRef: ElementRef,
|
@Input()
|
||||||
|
redirectUri: string = '/login';
|
||||||
|
|
||||||
|
/** Enable redirect after logout */
|
||||||
|
@Input()
|
||||||
|
enabelRedirect: boolean = true;
|
||||||
|
|
||||||
|
constructor(private elementRef: ElementRef,
|
||||||
private renderer: Renderer2,
|
private renderer: Renderer2,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private auth: AuthenticationService) {
|
private auth: AuthenticationService) {
|
||||||
@@ -42,12 +49,14 @@ export class LogoutDirective implements OnInit {
|
|||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
this.auth.logout().subscribe(
|
this.auth.logout().subscribe(
|
||||||
() => this.redirectToLogin(),
|
() => this.redirectToUri(),
|
||||||
() => this.redirectToLogin()
|
() => this.redirectToUri()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
redirectToLogin() {
|
redirectToUri() {
|
||||||
this.router.navigate(['/login']);
|
if (this.enabelRedirect) {
|
||||||
|
this.router.navigate([this.redirectUri]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,20 +16,28 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { SimpleChange } from '@angular/core';
|
import { SimpleChange } from '@angular/core';
|
||||||
import { fakeAsync, tick } from '@angular/core/testing';
|
import { fakeAsync, tick, TestBed } from '@angular/core/testing';
|
||||||
import { NodeFavoriteDirective } from './node-favorite.directive';
|
import { NodeFavoriteDirective } from './node-favorite.directive';
|
||||||
import { AlfrescoApiServiceMock } from '../mock/alfresco-api.service.mock';
|
import { AlfrescoApiServiceMock } from '../mock/alfresco-api.service.mock';
|
||||||
import { AppConfigService } from '../app-config/app-config.service';
|
import { AppConfigService } from '../app-config/app-config.service';
|
||||||
import { StorageService } from '../services/storage.service';
|
import { StorageService } from '../services/storage.service';
|
||||||
import { AlfrescoApiService } from '../services/alfresco-api.service';
|
import { UserPreferencesService } from '../services/user-preferences.service';
|
||||||
|
import { setupTestBed } from '../testing/setupTestBed';
|
||||||
|
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||||
|
|
||||||
describe('NodeFavoriteDirective', () => {
|
describe('NodeFavoriteDirective', () => {
|
||||||
|
|
||||||
let directive;
|
let directive;
|
||||||
let alfrescoApiService: AlfrescoApiService;
|
let alfrescoApiService;
|
||||||
|
let userPreferences;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [CoreTestingModule]
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService());
|
userPreferences = TestBed.get(UserPreferencesService);
|
||||||
|
alfrescoApiService = new AlfrescoApiServiceMock(new AppConfigService(null), userPreferences, new StorageService());
|
||||||
directive = new NodeFavoriteDirective( alfrescoApiService);
|
directive = new NodeFavoriteDirective( alfrescoApiService);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,7 @@
|
|||||||
"ERROR_PLURAL": "{{ number }} items couldn't be deleted"
|
"ERROR_PLURAL": "{{ number }} items couldn't be deleted"
|
||||||
},
|
},
|
||||||
"HOST_SETTINGS": {
|
"HOST_SETTINGS": {
|
||||||
|
"REQUIRED": "The field is required",
|
||||||
"CS_URL_ERROR": "Content Services address doesn't match the URL format",
|
"CS_URL_ERROR": "Content Services address doesn't match the URL format",
|
||||||
"PS_URL_ERROR": "Process Services address doesn't match the URL format",
|
"PS_URL_ERROR": "Process Services address doesn't match the URL format",
|
||||||
"TITLE": "Settings",
|
"TITLE": "Settings",
|
||||||
@@ -125,7 +126,11 @@
|
|||||||
"BP-HOST": "Process Services URL",
|
"BP-HOST": "Process Services URL",
|
||||||
"BACK": "Back",
|
"BACK": "Back",
|
||||||
"APPLY": "APPLY",
|
"APPLY": "APPLY",
|
||||||
"NOT_VALID": "http(s)://host|ip:port(/path) not recognized, try a different URL."
|
"NOT_VALID": "http(s)://host|ip:port(/path) not recognized, try a different URL.",
|
||||||
|
"REDIRECT": "Redirect Uri",
|
||||||
|
"SILENT": "Silent Login",
|
||||||
|
"SCOPE": "Scope",
|
||||||
|
"CLIENT": "ClientId"
|
||||||
},
|
},
|
||||||
"CARDVIEW": {
|
"CARDVIEW": {
|
||||||
"VALIDATORS": {
|
"VALIDATORS": {
|
||||||
@@ -193,7 +198,8 @@
|
|||||||
"BUTTON": {
|
"BUTTON": {
|
||||||
"LOGIN": "SIGN IN",
|
"LOGIN": "SIGN IN",
|
||||||
"CHECKING": "CHECKING",
|
"CHECKING": "CHECKING",
|
||||||
"WELCOME": "WELCOME"
|
"WELCOME": "WELCOME",
|
||||||
|
"SSO": "SIGN IN SSO"
|
||||||
},
|
},
|
||||||
"ACTION": {
|
"ACTION": {
|
||||||
"HELP": "NEED HELP?",
|
"HELP": "NEED HELP?",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
<mat-card-content class="adf-login-controls">
|
<mat-card-content class="adf-login-controls">
|
||||||
|
|
||||||
|
<div *ngIf="!implicitFlow">
|
||||||
<!--ERRORS AREA-->
|
<!--ERRORS AREA-->
|
||||||
<div class="adf-error-container">
|
<div class="adf-error-container">
|
||||||
<div *ngIf="isError" id="login-error" data-automation-id="login-error"
|
<div *ngIf="isError" id="login-error" data-automation-id="login-error"
|
||||||
@@ -31,7 +32,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--USERNAME FIELD-->
|
<!--USERNAME FIELD-->
|
||||||
<div class="adf-login__field" [ngClass]="{'is-invalid': isErrorStyle(form.controls.username)}">
|
<div class="adf-login__field"
|
||||||
|
[ngClass]="{'is-invalid': isErrorStyle(form.controls.username)}">
|
||||||
<mat-form-field class="adf-full-width" floatPlaceholder="never" color="primary">
|
<mat-form-field class="adf-full-width" floatPlaceholder="never" color="primary">
|
||||||
<input matInput placeholder="{{'LOGIN.LABEL.USERNAME' | translate }}"
|
<input matInput placeholder="{{'LOGIN.LABEL.USERNAME' | translate }}"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -59,10 +61,12 @@
|
|||||||
data-automation-id="password"
|
data-automation-id="password"
|
||||||
tabindex="2">
|
tabindex="2">
|
||||||
<mat-icon *ngIf="isPasswordShow" matSuffix class="adf-login-password-icon"
|
<mat-icon *ngIf="isPasswordShow" matSuffix class="adf-login-password-icon"
|
||||||
data-automation-id="hide_password" (click)="toggleShowPassword()">visibility
|
data-automation-id="hide_password" (click)="toggleShowPassword()">
|
||||||
|
visibility
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
<mat-icon *ngIf="!isPasswordShow" matSuffix class="adf-login-password-icon"
|
<mat-icon *ngIf="!isPasswordShow" matSuffix class="adf-login-password-icon"
|
||||||
data-automation-id="show_password" (click)="toggleShowPassword()">visibility_off
|
data-automation-id="show_password" (click)="toggleShowPassword()">
|
||||||
|
visibility_off
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<span class="adf-login-validation" for="password" *ngIf="formError.password">
|
<span class="adf-login-validation" for="password" *ngIf="formError.password">
|
||||||
@@ -84,10 +88,13 @@
|
|||||||
|
|
||||||
<span *ngIf="actualLoginStep === LoginSteps.Landing" class="adf-login-button-label">{{ 'LOGIN.BUTTON.LOGIN' | translate }}</span>
|
<span *ngIf="actualLoginStep === LoginSteps.Landing" class="adf-login-button-label">{{ 'LOGIN.BUTTON.LOGIN' | translate }}</span>
|
||||||
|
|
||||||
<div *ngIf="actualLoginStep === LoginSteps.Checking" class="adf-interactive-login-label">
|
<div *ngIf="actualLoginStep === LoginSteps.Checking"
|
||||||
<span class="adf-login-button-label">{{ 'LOGIN.BUTTON.CHECKING' | translate }}</span>
|
class="adf-interactive-login-label">
|
||||||
|
<span
|
||||||
|
class="adf-login-button-label">{{ 'LOGIN.BUTTON.CHECKING' | translate }}</span>
|
||||||
<div class="adf-login-spinner-container">
|
<div class="adf-login-spinner-container">
|
||||||
<mat-spinner id="checking-spinner" class="adf-login-checking-spinner" [diameter]="25"></mat-spinner>
|
<mat-spinner id="checking-spinner" class="adf-login-checking-spinner"
|
||||||
|
[diameter]="25"></mat-spinner>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -99,11 +106,25 @@
|
|||||||
|
|
||||||
</button>
|
</button>
|
||||||
<div *ngIf="showRememberMe" class="adf-login__remember-me">
|
<div *ngIf="showRememberMe" class="adf-login__remember-me">
|
||||||
<mat-checkbox id="adf-login-remember" color="primary" class="adf-login-rememberme" [checked]="rememberMe"
|
<mat-checkbox id="adf-login-remember" color="primary" class="adf-login-rememberme"
|
||||||
(change)="rememberMe = !rememberMe">{{ 'LOGIN.LABEL.REMEMBER' | translate }}
|
[checked]="rememberMe"
|
||||||
|
(change)="rememberMe = !rememberMe">{{ 'LOGIN.LABEL.REMEMBER' | translate
|
||||||
|
}}
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="implicitFlow">
|
||||||
|
<button type="button" (click)="implicitLogin()" id="login-button-sso" tabindex="1"
|
||||||
|
class="adf-login-button"
|
||||||
|
mat-raised-button color="primary"
|
||||||
|
data-automation-id="login-button-sso">
|
||||||
|
<span class="adf-login-button-label">{{ 'LOGIN.BUTTON.SSO' | translate }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
|
|
||||||
<mat-card-actions *ngIf="footerTemplate || showLoginActions">
|
<mat-card-actions *ngIf="footerTemplate || showLoginActions">
|
||||||
|
|
||||||
<div class="adf-login-action-container">
|
<div class="adf-login-action-container">
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ describe('LoginComponent', () => {
|
|||||||
imports: [CoreTestingModule]
|
imports: [CoreTestingModule]
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(async(() => {
|
||||||
fixture = TestBed.createComponent(LoginComponent);
|
fixture = TestBed.createComponent(LoginComponent);
|
||||||
|
|
||||||
element = fixture.nativeElement;
|
element = fixture.nativeElement;
|
||||||
@@ -66,15 +66,17 @@ describe('LoginComponent', () => {
|
|||||||
component.showRememberMe = true;
|
component.showRememberMe = true;
|
||||||
component.showLoginActions = true;
|
component.showLoginActions = true;
|
||||||
|
|
||||||
usernameInput = element.querySelector('#username');
|
|
||||||
passwordInput = element.querySelector('#password');
|
|
||||||
|
|
||||||
authService = TestBed.get(AuthenticationService);
|
authService = TestBed.get(AuthenticationService);
|
||||||
router = TestBed.get(Router);
|
router = TestBed.get(Router);
|
||||||
userPreferences = TestBed.get(UserPreferencesService);
|
userPreferences = TestBed.get(UserPreferencesService);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
usernameInput = element.querySelector('#username');
|
||||||
|
passwordInput = element.querySelector('#password');
|
||||||
});
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
fixture.destroy();
|
fixture.destroy();
|
||||||
@@ -98,7 +100,7 @@ describe('LoginComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should redirect to route on successful login', () => {
|
it('should redirect to route on successful login', () => {
|
||||||
spyOn(authService, 'login').and.returnValue(Observable.of({ type: 'type', ticket: 'ticket'}));
|
spyOn(authService, 'login').and.returnValue(Observable.of({ type: 'type', ticket: 'ticket' }));
|
||||||
const redirect = '/home';
|
const redirect = '/home';
|
||||||
component.successRoute = redirect;
|
component.successRoute = redirect;
|
||||||
spyOn(router, 'navigate');
|
spyOn(router, 'navigate');
|
||||||
@@ -107,10 +109,10 @@ describe('LoginComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should redirect to previous route state on successful login', () => {
|
it('should redirect to previous route state on successful login', () => {
|
||||||
spyOn(authService, 'login').and.returnValue(Observable.of({ type: 'type', ticket: 'ticket'}));
|
spyOn(authService, 'login').and.returnValue(Observable.of({ type: 'type', ticket: 'ticket' }));
|
||||||
const redirect = '/home';
|
const redirect = '/home';
|
||||||
component.successRoute = redirect;
|
component.successRoute = redirect;
|
||||||
authService.setRedirect({ provider: 'ECM', navigation: ['some-route'] } );
|
authService.setRedirect({ provider: 'ECM', navigation: ['some-route'] });
|
||||||
|
|
||||||
spyOn(router, 'navigate');
|
spyOn(router, 'navigate');
|
||||||
|
|
||||||
@@ -158,7 +160,7 @@ describe('LoginComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should be changed to the "welcome key" after a successful login attempt', () => {
|
it('should be changed to the "welcome key" after a successful login attempt', () => {
|
||||||
spyOn(authService, 'login').and.returnValue(Observable.of({ type: 'type', ticket: 'ticket'}));
|
spyOn(authService, 'login').and.returnValue(Observable.of({ type: 'type', ticket: 'ticket' }));
|
||||||
loginWithCredentials('fake-username', 'fake-password');
|
loginWithCredentials('fake-username', 'fake-password');
|
||||||
|
|
||||||
expect(getLoginButtonText()).toEqual('LOGIN.BUTTON.WELCOME');
|
expect(getLoginButtonText()).toEqual('LOGIN.BUTTON.WELCOME');
|
||||||
@@ -382,7 +384,7 @@ describe('LoginComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should return success event after the login have succeeded', (done) => {
|
it('should return success event after the login have succeeded', (done) => {
|
||||||
spyOn(authService, 'login').and.returnValue(Observable.of({ type: 'type', ticket: 'ticket'}));
|
spyOn(authService, 'login').and.returnValue(Observable.of({ type: 'type', ticket: 'ticket' }));
|
||||||
|
|
||||||
component.providers = 'ECM';
|
component.providers = 'ECM';
|
||||||
expect(component.isError).toBe(false);
|
expect(component.isError).toBe(false);
|
||||||
@@ -514,7 +516,7 @@ describe('LoginComponent', () => {
|
|||||||
|
|
||||||
expect(component.isError).toBe(false);
|
expect(component.isError).toBe(false);
|
||||||
expect(event).toEqual(
|
expect(event).toEqual(
|
||||||
new LoginSuccessEvent({type: 'type', ticket: 'ticket'}, 'fake-username', null)
|
new LoginSuccessEvent({ type: 'type', ticket: 'ticket' }, 'fake-username', null)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -583,4 +585,47 @@ describe('LoginComponent', () => {
|
|||||||
|
|
||||||
loginWithCredentials('fake-username', 'fake-password');
|
loginWithCredentials('fake-username', 'fake-password');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
describe('SSO', () => {
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
userPreferences.oauthConfig = { implicitFlow: true };
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
userPreferences.oauthConfig = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show login username and password if SSO implicit flow is active', async(() => {
|
||||||
|
spyOn(authService, 'isOauth').and.returnValue(true);
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(element.querySelector('#username')).toBeNull();
|
||||||
|
expect(element.querySelector('#password')).toBeNull();
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should not show the login base auth button', async(() => {
|
||||||
|
spyOn(authService, 'isOauth').and.returnValue(true);
|
||||||
|
userPreferences.oauthConfig = { implicitFlow: true };
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(element.querySelector('#login-button')).toBeNull();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should show the login SSO button', async(() => {
|
||||||
|
spyOn(authService, 'isOauth').and.returnValue(true);
|
||||||
|
userPreferences.oauthConfig = { implicitFlow: true };
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(element.querySelector('#login-button-sso')).toBeDefined();
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -120,6 +120,8 @@ export class LoginComponent implements OnInit {
|
|||||||
@Output()
|
@Output()
|
||||||
executeSubmit = new EventEmitter<LoginSubmitEvent>();
|
executeSubmit = new EventEmitter<LoginSubmitEvent>();
|
||||||
|
|
||||||
|
implicitFlow: boolean = false;
|
||||||
|
|
||||||
form: FormGroup;
|
form: FormGroup;
|
||||||
isError: boolean = false;
|
isError: boolean = false;
|
||||||
errorMsg: string;
|
errorMsg: string;
|
||||||
@@ -154,6 +156,12 @@ export class LoginComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
if (this.authService.isOauth()) {
|
||||||
|
if (this.userPreferences.oauthConfig && this.userPreferences.oauthConfig.implicitFlow) {
|
||||||
|
this.implicitFlow = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.hasCustomFiledsValidation()) {
|
if (this.hasCustomFiledsValidation()) {
|
||||||
this.form = this._fb.group(this.fieldsValidation);
|
this.form = this._fb.group(this.fieldsValidation);
|
||||||
} else {
|
} else {
|
||||||
@@ -178,7 +186,7 @@ export class LoginComponent implements OnInit {
|
|||||||
this.settingsService.csrfDisabled = this.disableCsrf;
|
this.settingsService.csrfDisabled = this.disableCsrf;
|
||||||
|
|
||||||
this.disableError();
|
this.disableError();
|
||||||
const args = new LoginSubmitEvent({controls : { username : this.form.controls.username} });
|
const args = new LoginSubmitEvent({ controls: { username: this.form.controls.username } });
|
||||||
this.executeSubmit.emit(args);
|
this.executeSubmit.emit(args);
|
||||||
|
|
||||||
if (args.defaultPrevented) {
|
if (args.defaultPrevented) {
|
||||||
@@ -188,6 +196,10 @@ export class LoginComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
implicitLogin() {
|
||||||
|
this.authService.ssoImplictiLogin();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method check the error in the form and push the error in the formError object
|
* The method check the error in the form and push the error in the formError object
|
||||||
* @param data
|
* @param data
|
||||||
|
|||||||
@@ -16,49 +16,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { AlfrescoApi } from 'alfresco-js-api';
|
|
||||||
import * as alfrescoApi from 'alfresco-js-api';
|
|
||||||
import { AppConfigService } from '../app-config/app-config.service';
|
import { AppConfigService } from '../app-config/app-config.service';
|
||||||
import { StorageService } from '../services/storage.service';
|
import { StorageService } from '../services/storage.service';
|
||||||
import { AlfrescoApiService } from '../services/alfresco-api.service';
|
import { AlfrescoApiService } from '../services/alfresco-api.service';
|
||||||
|
import { UserPreferencesService } from '../services/user-preferences.service';
|
||||||
|
|
||||||
/* tslint:disable:adf-file-name */
|
/* tslint:disable:adf-file-name */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AlfrescoApiServiceMock extends AlfrescoApiService {
|
export class AlfrescoApiServiceMock extends AlfrescoApiService {
|
||||||
|
|
||||||
constructor(protected appConfig: AppConfigService,
|
constructor(protected appConfig: AppConfigService,
|
||||||
|
protected userPreference: UserPreferencesService,
|
||||||
protected storage: StorageService) {
|
protected storage: StorageService) {
|
||||||
super(appConfig, storage);
|
super(appConfig, userPreference, storage);
|
||||||
if (!this.alfrescoApi) {
|
if (!this.alfrescoApi) {
|
||||||
this.initAlfrescoApi();
|
this.initAlfrescoApi();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
|
||||||
await this.appConfig.load().then(() => {
|
|
||||||
if (!this.alfrescoApi) {
|
|
||||||
this.initAlfrescoApi();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async reset() {
|
|
||||||
if (this.alfrescoApi) {
|
|
||||||
this.alfrescoApi = null;
|
|
||||||
}
|
|
||||||
this.initAlfrescoApi();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected initAlfrescoApi() {
|
|
||||||
this.alfrescoApi = <AlfrescoApi> new alfrescoApi({
|
|
||||||
provider: this.storage.getItem('AUTH_TYPE'),
|
|
||||||
ticketEcm: this.storage.getItem('ticket-ECM'),
|
|
||||||
ticketBpm: this.storage.getItem('ticket-BPM'),
|
|
||||||
hostEcm: this.appConfig.get<string>('ecmHost'),
|
|
||||||
hostBpm: this.appConfig.get<string>('bpmHost'),
|
|
||||||
contextRoot: 'alfresco',
|
|
||||||
disableCsrf: this.storage.getItem('DISABLE_CSRF') === 'true',
|
|
||||||
oauth2: this.appConfig.get<any>('oauth2')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/*!
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface OauthConfigModel {
|
||||||
|
host: string;
|
||||||
|
clientId: string;
|
||||||
|
scope: string;
|
||||||
|
implicitFlow: boolean;
|
||||||
|
redirectUri: string;
|
||||||
|
silentLogin?: boolean;
|
||||||
|
silentRefreshRedirectUri?: string;
|
||||||
|
secret?: string;
|
||||||
|
refreshTokenTimeout?: number;
|
||||||
|
redirectUriLogout?: string;
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@ import * as alfrescoApi from 'alfresco-js-api';
|
|||||||
import { AppConfigService } from '../app-config/app-config.service';
|
import { AppConfigService } from '../app-config/app-config.service';
|
||||||
import { StorageService } from './storage.service';
|
import { StorageService } from './storage.service';
|
||||||
import { Subject } from 'rxjs/Subject';
|
import { Subject } from 'rxjs/Subject';
|
||||||
|
import { UserPreferencesService } from './user-preferences.service';
|
||||||
|
|
||||||
/* tslint:disable:adf-file-name */
|
/* tslint:disable:adf-file-name */
|
||||||
|
|
||||||
@@ -95,6 +96,7 @@ export class AlfrescoApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(protected appConfig: AppConfigService,
|
constructor(protected appConfig: AppConfigService,
|
||||||
|
protected userPreference: UserPreferencesService,
|
||||||
protected storage: StorageService) {
|
protected storage: StorageService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,23 +107,32 @@ export class AlfrescoApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async reset() {
|
async reset() {
|
||||||
if (this.alfrescoApi) {
|
|
||||||
this.alfrescoApi = null;
|
|
||||||
}
|
|
||||||
this.initAlfrescoApi();
|
this.initAlfrescoApi();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected initAlfrescoApi() {
|
protected initAlfrescoApi() {
|
||||||
this.alfrescoApi = <AlfrescoApi> new alfrescoApi({
|
let oauth: any = Object.assign({}, this.userPreference.oauthConfig);
|
||||||
provider: this.storage.getItem('AUTH_TYPE'),
|
if (oauth) {
|
||||||
|
oauth.redirectUri = window.location.origin + (oauth.redirectUri || '/');
|
||||||
|
oauth.redirectUriLogout = window.location.origin + (oauth.redirectUriLogout || '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
provider: this.userPreference.providers,
|
||||||
ticketEcm: this.storage.getItem('ticket-ECM'),
|
ticketEcm: this.storage.getItem('ticket-ECM'),
|
||||||
ticketBpm: this.storage.getItem('ticket-BPM'),
|
ticketBpm: this.storage.getItem('ticket-BPM'),
|
||||||
hostEcm: this.appConfig.get<string>('ecmHost'),
|
hostEcm: this.userPreference.ecmHost,
|
||||||
hostBpm: this.appConfig.get<string>('bpmHost'),
|
hostBpm: this.userPreference.bpmHost,
|
||||||
contextRootBpm: this.appConfig.get<string>('contextRootBpm'),
|
contextRootBpm: this.appConfig.get<string>('contextRootBpm'),
|
||||||
contextRoot: this.appConfig.get<string>('contextRootEcm'),
|
contextRoot: this.appConfig.get<string>('contextRootEcm'),
|
||||||
disableCsrf: this.storage.getItem('DISABLE_CSRF') === 'true',
|
disableCsrf: this.storage.getItem('DISABLE_CSRF') === 'true',
|
||||||
oauth2: this.appConfig.get<any>('oauth2')
|
oauth2: oauth
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (this.alfrescoApi) {
|
||||||
|
this.alfrescoApi.configureJsApi(config);
|
||||||
|
} else {
|
||||||
|
this.alfrescoApi = <AlfrescoApi> new alfrescoApi(config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ describe('AuthGuardService BPM', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
localStorage.clear();
|
||||||
authService = TestBed.get(AuthenticationService);
|
authService = TestBed.get(AuthenticationService);
|
||||||
authGuard = TestBed.get(AuthGuardBpm);
|
authGuard = TestBed.get(AuthGuardBpm);
|
||||||
routerService = TestBed.get(Router);
|
routerService = TestBed.get(Router);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export class AuthGuardEcm implements CanActivate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private isLoggedIn(): Promise<boolean> {
|
private isLoggedIn(): Promise<boolean> {
|
||||||
if (!this.authApi.isLoggedIn()) {
|
if (this.authApi === undefined || !this.authApi.isLoggedIn()) {
|
||||||
return Promise.resolve(false);
|
return Promise.resolve(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ describe('AuthGuardService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
localStorage.clear();
|
||||||
state = { url: '' };
|
state = { url: '' };
|
||||||
authService = TestBed.get(AuthenticationService);
|
authService = TestBed.get(AuthenticationService);
|
||||||
router = TestBed.get(Router);
|
router = TestBed.get(Router);
|
||||||
|
|||||||
@@ -21,22 +21,24 @@ import {
|
|||||||
CanActivateChild, RouterStateSnapshot, Router,
|
CanActivateChild, RouterStateSnapshot, Router,
|
||||||
PRIMARY_OUTLET, UrlTree, UrlSegmentGroup, UrlSegment
|
PRIMARY_OUTLET, UrlTree, UrlSegmentGroup, UrlSegment
|
||||||
} from '@angular/router';
|
} from '@angular/router';
|
||||||
import { AppConfigService } from '../app-config/app-config.service';
|
|
||||||
import { AuthenticationService } from './authentication.service';
|
import { AuthenticationService } from './authentication.service';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { AppConfigService } from '../app-config/app-config.service';
|
||||||
|
import { UserPreferencesService } from './user-preferences.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthGuard implements CanActivate, CanActivateChild {
|
export class AuthGuard implements CanActivate, CanActivateChild {
|
||||||
constructor(private authService: AuthenticationService,
|
constructor(private authService: AuthenticationService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
private userPreference: UserPreferencesService,
|
||||||
private appConfig: AppConfigService) {}
|
private appConfig: AppConfigService) {}
|
||||||
|
|
||||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
|
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean> {
|
||||||
const redirectUrl = state.url;
|
const redirectUrl = state.url;
|
||||||
|
|
||||||
return this.checkLogin(redirectUrl);
|
return this.checkLogin(redirectUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
|
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean> {
|
||||||
return this.canActivate(route, state);
|
return this.canActivate(route, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,23 +46,29 @@ export class AuthGuard implements CanActivate, CanActivateChild {
|
|||||||
if (this.authService.isLoggedIn()) {
|
if (this.authService.isLoggedIn()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (!this.authService.isOauth() || this.isOAuthWithoutSilentLogin() ) {
|
||||||
const navigation = this.getNavigationCommands(redirectUrl);
|
const navigation = this.getNavigationCommands(redirectUrl);
|
||||||
|
|
||||||
this.authService.setRedirect({ provider: 'ALL', navigation } );
|
this.authService.setRedirect({ provider: 'ALL', navigation } );
|
||||||
|
|
||||||
const pathToLogin = this.getRouteDestinationForLogin();
|
const pathToLogin = this.getRouteDestinationForLogin();
|
||||||
this.router.navigate(['/' + pathToLogin]);
|
this.router.navigate(['/' + pathToLogin]);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getRouteDestinationForLogin(): string {
|
isOAuthWithoutSilentLogin() {
|
||||||
|
return this.authService.isOauth() && this.userPreference.oauthConfig.silentLogin === false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getRouteDestinationForLogin(): string {
|
||||||
return this.appConfig &&
|
return this.appConfig &&
|
||||||
this.appConfig.get<string>('loginRoute') ?
|
this.appConfig.get<string>('loginRoute') ?
|
||||||
this.appConfig.get<string>('loginRoute') : 'login';
|
this.appConfig.get<string>('loginRoute') : 'login';
|
||||||
}
|
}
|
||||||
|
|
||||||
private getNavigationCommands(redirectUrl: string): any[] {
|
public getNavigationCommands(redirectUrl: string): any[] {
|
||||||
const urlTree: UrlTree = this.router.parseUrl(redirectUrl);
|
const urlTree: UrlTree = this.router.parseUrl(redirectUrl);
|
||||||
const urlSegmentGroup: UrlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET];
|
const urlSegmentGroup: UrlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET];
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ describe('AuthenticationService', () => {
|
|||||||
describe('remember me', () => {
|
describe('remember me', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
preferences.authType = 'ECM';
|
preferences.providers = 'ECM';
|
||||||
|
apiService.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[ECM] should save the remember me cookie as a session cookie after successful login', (done) => {
|
it('[ECM] should save the remember me cookie as a session cookie after successful login', (done) => {
|
||||||
@@ -123,7 +124,8 @@ describe('AuthenticationService', () => {
|
|||||||
describe('when the setting is ECM', () => {
|
describe('when the setting is ECM', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
preferences.authType = 'ECM';
|
preferences.providers = 'ECM';
|
||||||
|
apiService.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should require remember me set for ECM check', () => {
|
it('should require remember me set for ECM check', () => {
|
||||||
@@ -154,7 +156,7 @@ describe('AuthenticationService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||||
'status': 201,
|
status: 201,
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
responseText: JSON.stringify({ 'entry': { 'id': 'fake-post-ticket', 'userId': 'admin' } })
|
responseText: JSON.stringify({ 'entry': { 'id': 'fake-post-ticket', 'userId': 'admin' } })
|
||||||
});
|
});
|
||||||
@@ -274,26 +276,27 @@ describe('AuthenticationService', () => {
|
|||||||
it('[ECM] should set/get redirectUrl when provider is ECM', () => {
|
it('[ECM] should set/get redirectUrl when provider is ECM', () => {
|
||||||
authService.setRedirect({ provider: 'ECM', navigation: ['some-url'] });
|
authService.setRedirect({ provider: 'ECM', navigation: ['some-url'] });
|
||||||
|
|
||||||
expect(authService.getRedirect(preferences.authType)).toEqual(['some-url']);
|
expect(authService.getRedirect(preferences.providers)).toEqual(['some-url']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[ECM] should set/get redirectUrl when provider is BPM', () => {
|
it('[ECM] should set/get redirectUrl when provider is BPM', () => {
|
||||||
authService.setRedirect({ provider: 'BPM', navigation: ['some-url'] });
|
authService.setRedirect({ provider: 'BPM', navigation: ['some-url'] });
|
||||||
|
|
||||||
expect(authService.getRedirect(preferences.authType)).toBeNull();
|
expect(authService.getRedirect(preferences.providers)).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[ECM] should return null as redirectUrl when redirectUrl field is not set', () => {
|
it('[ECM] should return null as redirectUrl when redirectUrl field is not set', () => {
|
||||||
authService.setRedirect(null);
|
authService.setRedirect(null);
|
||||||
|
|
||||||
expect(authService.getRedirect(preferences.authType)).toBeNull();
|
expect(authService.getRedirect(preferences.providers)).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when the setting is BPM', () => {
|
describe('when the setting is BPM', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
preferences.authType = 'BPM';
|
preferences.providers = 'BPM';
|
||||||
|
apiService.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should require remember me set for BPM check', () => {
|
it('should require remember me set for BPM check', () => {
|
||||||
@@ -426,26 +429,27 @@ describe('AuthenticationService', () => {
|
|||||||
it('[BPM] should set/get redirectUrl when provider is BPM', () => {
|
it('[BPM] should set/get redirectUrl when provider is BPM', () => {
|
||||||
authService.setRedirect({ provider: 'BPM', navigation: ['some-url'] });
|
authService.setRedirect({ provider: 'BPM', navigation: ['some-url'] });
|
||||||
|
|
||||||
expect(authService.getRedirect(preferences.authType)).toEqual(['some-url']);
|
expect(authService.getRedirect(preferences.providers)).toEqual(['some-url']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[BPM] should set/get redirectUrl when provider is ECM', () => {
|
it('[BPM] should set/get redirectUrl when provider is ECM', () => {
|
||||||
authService.setRedirect({ provider: 'ECM', navigation: ['some-url'] });
|
authService.setRedirect({ provider: 'ECM', navigation: ['some-url'] });
|
||||||
|
|
||||||
expect(authService.getRedirect(preferences.authType)).toBeNull();
|
expect(authService.getRedirect(preferences.providers)).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[BPM] should return null as redirectUrl when redirectUrl field is not set', () => {
|
it('[BPM] should return null as redirectUrl when redirectUrl field is not set', () => {
|
||||||
authService.setRedirect(null);
|
authService.setRedirect(null);
|
||||||
|
|
||||||
expect(authService.getRedirect(preferences.authType)).toBeNull();
|
expect(authService.getRedirect(preferences.providers)).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when the setting is both ECM and BPM ', () => {
|
describe('when the setting is both ECM and BPM ', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
preferences.authType = 'ALL';
|
preferences.providers = 'ALL';
|
||||||
|
apiService.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[ALL] should return both ECM and BPM tickets after the login done', (done) => {
|
it('[ALL] should return both ECM and BPM tickets after the login done', (done) => {
|
||||||
@@ -542,25 +546,25 @@ describe('AuthenticationService', () => {
|
|||||||
it('[ALL] should set/get redirectUrl when provider is ALL', () => {
|
it('[ALL] should set/get redirectUrl when provider is ALL', () => {
|
||||||
authService.setRedirect({ provider: 'ALL', navigation: ['some-url'] });
|
authService.setRedirect({ provider: 'ALL', navigation: ['some-url'] });
|
||||||
|
|
||||||
expect(authService.getRedirect(preferences.authType)).toEqual(['some-url']);
|
expect(authService.getRedirect(preferences.providers)).toEqual(['some-url']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[ALL] should set/get redirectUrl when provider is BPM', () => {
|
it('[ALL] should set/get redirectUrl when provider is BPM', () => {
|
||||||
authService.setRedirect({ provider: 'BPM', navigation: ['some-url'] });
|
authService.setRedirect({ provider: 'BPM', navigation: ['some-url'] });
|
||||||
|
|
||||||
expect(authService.getRedirect(preferences.authType)).toEqual(['some-url']);
|
expect(authService.getRedirect(preferences.providers)).toEqual(['some-url']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[ALL] should set/get redirectUrl when provider is ECM', () => {
|
it('[ALL] should set/get redirectUrl when provider is ECM', () => {
|
||||||
authService.setRedirect({ provider: 'ECM', navigation: ['some-url'] });
|
authService.setRedirect({ provider: 'ECM', navigation: ['some-url'] });
|
||||||
|
|
||||||
expect(authService.getRedirect(preferences.authType)).toEqual(['some-url']);
|
expect(authService.getRedirect(preferences.providers)).toEqual(['some-url']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[ALL] should return null as redirectUrl when redirectUrl field is not set', () => {
|
it('[ALL] should return null as redirectUrl when redirectUrl field is not set', () => {
|
||||||
authService.setRedirect(null);
|
authService.setRedirect(null);
|
||||||
|
|
||||||
expect(authService.getRedirect(preferences.authType)).toBeNull();
|
expect(authService.getRedirect(preferences.providers)).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ export class AuthenticationService {
|
|||||||
return !!this.alfrescoApi.getInstance().isLoggedIn();
|
return !!this.alfrescoApi.getInstance().isLoggedIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isOauth(): boolean {
|
||||||
|
return this.alfrescoApi.getInstance().isOauthConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs the user in.
|
* Logs the user in.
|
||||||
* @param username Username for the login
|
* @param username Username for the login
|
||||||
@@ -63,19 +67,26 @@ export class AuthenticationService {
|
|||||||
*/
|
*/
|
||||||
login(username: string, password: string, rememberMe: boolean = false): Observable<{ type: string, ticket: any }> {
|
login(username: string, password: string, rememberMe: boolean = false): Observable<{ type: string, ticket: any }> {
|
||||||
this.removeTicket();
|
this.removeTicket();
|
||||||
return Observable.fromPromise(this.callApiLogin(username, password))
|
return Observable.fromPromise(this.alfrescoApi.getInstance().login(username, password))
|
||||||
.map((response: any) => {
|
.map((response: any) => {
|
||||||
this.saveRememberMeCookie(rememberMe);
|
this.saveRememberMeCookie(rememberMe);
|
||||||
this.saveTickets();
|
this.saveTickets();
|
||||||
this.onLogin.next(response);
|
this.onLogin.next(response);
|
||||||
return {
|
return {
|
||||||
type: this.preferences.authType,
|
type: this.preferences.providers,
|
||||||
ticket: response
|
ticket: response
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.catch(err => this.handleError(err));
|
.catch(err => this.handleError(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the user in with SSO
|
||||||
|
*/
|
||||||
|
ssoImplictiLogin() {
|
||||||
|
this.alfrescoApi.getInstance().implicitLogin();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the "remember me" cookie as either a long-life cookie or a session cookie.
|
* Saves the "remember me" cookie as either a long-life cookie or a session cookie.
|
||||||
* @param rememberMe Enables a long-life cookie
|
* @param rememberMe Enables a long-life cookie
|
||||||
@@ -100,15 +111,6 @@ export class AuthenticationService {
|
|||||||
return (this.cookie.getItem(REMEMBER_ME_COOKIE_KEY) === null) ? false : true;
|
return (this.cookie.getItem(REMEMBER_ME_COOKIE_KEY) === null) ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the alfresco Api with user and password end call the login method
|
|
||||||
* @param username
|
|
||||||
* @param password
|
|
||||||
*/
|
|
||||||
private callApiLogin(username: string, password: string) {
|
|
||||||
return this.alfrescoApi.getInstance().login(username, password);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs the user out.
|
* Logs the user out.
|
||||||
* @returns Response event called when logout is complete
|
* @returns Response event called when logout is complete
|
||||||
@@ -213,7 +215,7 @@ export class AuthenticationService {
|
|||||||
if (this.cookie.isEnabled() && !this.isRememberMeSet()) {
|
if (this.cookie.isEnabled() && !this.isRememberMeSet()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return this.alfrescoApi.getInstance().ecmAuth && !!this.alfrescoApi.getInstance().ecmAuth.isLoggedIn();
|
return this.alfrescoApi.getInstance().isEcmLoggedIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -224,7 +226,7 @@ export class AuthenticationService {
|
|||||||
if (this.cookie.isEnabled() && !this.isRememberMeSet()) {
|
if (this.cookie.isEnabled() && !this.isRememberMeSet()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return this.alfrescoApi.getInstance().bpmAuth && !!this.alfrescoApi.getInstance().bpmAuth.isLoggedIn();
|
return this.alfrescoApi.getInstance().isBpmLoggedIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -232,7 +234,7 @@ export class AuthenticationService {
|
|||||||
* @returns The ECM username
|
* @returns The ECM username
|
||||||
*/
|
*/
|
||||||
getEcmUsername(): string {
|
getEcmUsername(): string {
|
||||||
return this.alfrescoApi.getInstance().ecmAuth.username;
|
return this.alfrescoApi.getInstance().getEcmUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -240,7 +242,7 @@ export class AuthenticationService {
|
|||||||
* @returns The BPM username
|
* @returns The BPM username
|
||||||
*/
|
*/
|
||||||
getBpmUsername(): string {
|
getBpmUsername(): string {
|
||||||
return this.alfrescoApi.getInstance().bpmAuth.username;
|
return this.alfrescoApi.getInstance().getBpmUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the URL to redirect to after login.
|
/** Sets the URL to redirect to after login.
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
import { inject, TestBed } from '@angular/core/testing';
|
import { inject, TestBed } from '@angular/core/testing';
|
||||||
import { Title } from '@angular/platform-browser';
|
import { Title } from '@angular/platform-browser';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
import { AppConfigService } from '../app-config/app-config.service';
|
import { AppConfigService } from '../app-config/app-config.service';
|
||||||
import { PageTitleService } from './page-title.service';
|
import { PageTitleService } from './page-title.service';
|
||||||
@@ -54,7 +55,8 @@ class TestConfig {
|
|||||||
get: () => this.setup.applicationName,
|
get: () => this.setup.applicationName,
|
||||||
load: () => {
|
load: () => {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
},
|
||||||
|
onLoad: Observable.of({})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -23,25 +23,18 @@ import { UploadService } from './upload.service';
|
|||||||
import { AppConfigService } from '../app-config/app-config.service';
|
import { AppConfigService } from '../app-config/app-config.service';
|
||||||
import { AlfrescoApiService } from './alfresco-api.service';
|
import { AlfrescoApiService } from './alfresco-api.service';
|
||||||
import { StorageService } from './storage.service';
|
import { StorageService } from './storage.service';
|
||||||
import { AlfrescoApiServiceMock } from '../mock/alfresco-api.service.mock';
|
|
||||||
|
import { setupTestBed } from '../testing/setupTestBed';
|
||||||
|
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||||
|
|
||||||
declare let jasmine: any;
|
declare let jasmine: any;
|
||||||
|
|
||||||
describe('UploadService', () => {
|
describe('UploadService', () => {
|
||||||
let service: UploadService;
|
let service: UploadService;
|
||||||
|
|
||||||
beforeEach(async(() => {
|
setupTestBed({
|
||||||
TestBed.configureTestingModule({
|
imports: [CoreTestingModule, AppConfigModule]
|
||||||
imports: [
|
});
|
||||||
AppConfigModule
|
|
||||||
],
|
|
||||||
providers: [
|
|
||||||
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
|
|
||||||
StorageService,
|
|
||||||
UploadService
|
|
||||||
]
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
let appConfig: AppConfigService = TestBed.get(AppConfigService);
|
let appConfig: AppConfigService = TestBed.get(AppConfigService);
|
||||||
@@ -53,6 +46,8 @@ describe('UploadService', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
service = TestBed.get(UploadService);
|
service = TestBed.get(UploadService);
|
||||||
|
service.queue = [];
|
||||||
|
service.activeTask = null;
|
||||||
jasmine.Ajax.install();
|
jasmine.Ajax.install();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -162,6 +157,8 @@ describe('UploadService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('If newVersion is set, name should be a param', () => {
|
it('If newVersion is set, name should be a param', () => {
|
||||||
|
let uploadFileSpy = spyOn(service.apiService.getInstance().upload, 'uploadFile').and.callThrough();
|
||||||
|
|
||||||
let emitter = new EventEmitter();
|
let emitter = new EventEmitter();
|
||||||
|
|
||||||
const filesFake = new FileModel(<File> { name: 'fake-name', size: 10 }, {
|
const filesFake = new FileModel(<File> { name: 'fake-name', size: 10 }, {
|
||||||
@@ -170,7 +167,16 @@ describe('UploadService', () => {
|
|||||||
service.addToQueue(filesFake);
|
service.addToQueue(filesFake);
|
||||||
service.uploadFilesInTheQueue(emitter);
|
service.uploadFilesInTheQueue(emitter);
|
||||||
|
|
||||||
expect(jasmine.Ajax.requests.mostRecent().params.has('name')).toBe(true);
|
expect(uploadFileSpy).toHaveBeenCalledWith({
|
||||||
|
name: 'fake-name',
|
||||||
|
size: 10
|
||||||
|
}, undefined, undefined, null, {
|
||||||
|
renditions: 'doclib',
|
||||||
|
overwrite: true,
|
||||||
|
majorVersion: undefined,
|
||||||
|
comment: undefined,
|
||||||
|
name: 'fake-name'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use custom root folder ID given to the service', (done) => {
|
it('should use custom root folder ID given to the service', (done) => {
|
||||||
|
|||||||
@@ -156,9 +156,9 @@ describe('UserPreferencesService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should stream only the selected attribute changes when using select', (done) => {
|
it('should stream only the selected attribute changes when using select', (done) => {
|
||||||
preferences.disableCSRF = true;
|
preferences.disableCSRF = false;
|
||||||
preferences.select(UserPreferenceValues.DisableCSRF).subscribe((disableCSRFFlag) => {
|
preferences.select(UserPreferenceValues.DisableCSRF).subscribe((disableCSRFFlag) => {
|
||||||
expect(disableCSRFFlag).toBeTruthy();
|
expect(disableCSRFFlag).toBeFalsy();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { AppConfigService } from '../app-config/app-config.service';
|
import { AppConfigService } from '../app-config/app-config.service';
|
||||||
import { AlfrescoApiService } from './alfresco-api.service';
|
|
||||||
import { StorageService } from './storage.service';
|
import { StorageService } from './storage.service';
|
||||||
import 'rxjs/add/operator/distinctUntilChanged';
|
import 'rxjs/add/operator/distinctUntilChanged';
|
||||||
|
import { OauthConfigModel } from '../models/oauth-config.model';
|
||||||
|
|
||||||
export enum UserPreferenceValues {
|
export enum UserPreferenceValues {
|
||||||
PaginationSize = 'PAGINATION_SIZE',
|
PaginationSize = 'PAGINATION_SIZE',
|
||||||
@@ -50,17 +50,14 @@ export class UserPreferencesService {
|
|||||||
* @deprecated we are grouping every value changed on the user preference in a single stream : userPreferenceValue$
|
* @deprecated we are grouping every value changed on the user preference in a single stream : userPreferenceValue$
|
||||||
*/
|
*/
|
||||||
locale$: Observable<string>;
|
locale$: Observable<string>;
|
||||||
private localeSubject: BehaviorSubject<string> ;
|
private localeSubject: BehaviorSubject<string>;
|
||||||
|
|
||||||
private onChangeSubject: BehaviorSubject<any>;
|
private onChangeSubject: BehaviorSubject<any>;
|
||||||
onChange: Observable<any>;
|
onChange: Observable<any>;
|
||||||
|
|
||||||
constructor(
|
constructor(public translate: TranslateService,
|
||||||
public translate: TranslateService,
|
|
||||||
private appConfig: AppConfigService,
|
private appConfig: AppConfigService,
|
||||||
private storage: StorageService,
|
private storage: StorageService) {
|
||||||
private apiService: AlfrescoApiService
|
|
||||||
) {
|
|
||||||
this.appConfig.onLoad.subscribe(this.initUserPreferenceStatus.bind(this));
|
this.appConfig.onLoad.subscribe(this.initUserPreferenceStatus.bind(this));
|
||||||
this.localeSubject = new BehaviorSubject(this.userPreferenceStatus[UserPreferenceValues.Locale]);
|
this.localeSubject = new BehaviorSubject(this.userPreferenceStatus[UserPreferenceValues.Locale]);
|
||||||
this.locale$ = this.localeSubject.asObservable();
|
this.locale$ = this.localeSubject.asObservable();
|
||||||
@@ -106,7 +103,9 @@ export class UserPreferencesService {
|
|||||||
* @param value New value for the property
|
* @param value New value for the property
|
||||||
*/
|
*/
|
||||||
set(property: string, value: any) {
|
set(property: string, value: any) {
|
||||||
if (!property) { return; }
|
if (!property) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.storage.setItem(
|
this.storage.setItem(
|
||||||
this.getPropertyKey(property),
|
this.getPropertyKey(property),
|
||||||
value
|
value
|
||||||
@@ -149,19 +148,29 @@ export class UserPreferencesService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Authorization type (can be "ECM", "BPM" or "ALL"). */
|
/** Authorization type (can be "ECM", "BPM" or "ALL"). */
|
||||||
set authType(value: string) {
|
/** @deprecated in 2.4.0 */
|
||||||
this.storage.setItem('AUTH_TYPE', value);
|
set authType(authType: string) {
|
||||||
this.apiService.reset();
|
let storedAuthType = this.storage.getItem('AUTH_TYPE');
|
||||||
|
|
||||||
|
if (authType !== storedAuthType) {
|
||||||
|
this.storage.setItem('AUTH_TYPE', authType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @deprecated in 2.4.0 */
|
||||||
get authType(): string {
|
get authType(): string {
|
||||||
return this.storage.getItem('AUTH_TYPE') || 'ALL';
|
return this.storage.getItem('AUTH_TYPE') || 'ALL';
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Prevents the CSRF Token from being submitted if true. Only valid for Process Services. */
|
/** Prevents the CSRF Token from being submitted if true. Only valid for Process Services. */
|
||||||
set disableCSRF(value: boolean) {
|
set disableCSRF(csrf: boolean) {
|
||||||
this.set('DISABLE_CSRF', value);
|
let storedCSRF = this.storage.getItem('DISABLE_CSRF');
|
||||||
this.apiService.reset();
|
|
||||||
|
if (csrf !== null && csrf !== undefined) {
|
||||||
|
if (csrf.toString() === storedCSRF) {
|
||||||
|
this.set('DISABLE_CSRF', csrf);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get disableCSRF(): boolean {
|
get disableCSRF(): boolean {
|
||||||
@@ -196,4 +205,56 @@ export class UserPreferencesService {
|
|||||||
return this.appConfig.get<string>('locale') || this.translate.getBrowserLang() || 'en';
|
return this.appConfig.get<string>('locale') || this.translate.getBrowserLang() || 'en';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get providers(): string {
|
||||||
|
if (this.storage.hasItem('providers')) {
|
||||||
|
return this.storage.getItem('providers');
|
||||||
|
} else {
|
||||||
|
return this.appConfig.get('providers', 'ECM');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set providers(providers: string) {
|
||||||
|
this.storage.setItem('providers', providers);
|
||||||
|
}
|
||||||
|
|
||||||
|
get bpmHost(): string {
|
||||||
|
if (this.storage.hasItem('bpmHost')) {
|
||||||
|
return this.storage.getItem('bpmHost');
|
||||||
|
} else {
|
||||||
|
return this.appConfig.get('bpmHost');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set bpmHost(bpmHost: string) {
|
||||||
|
this.storage.setItem('bpmHost', bpmHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
get ecmHost(): string {
|
||||||
|
if (this.storage.hasItem('ecmHost')) {
|
||||||
|
return this.storage.getItem('ecmHost');
|
||||||
|
} else {
|
||||||
|
return this.appConfig.get('ecmHost');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set ecmHost(ecmHost: string) {
|
||||||
|
this.storage.setItem('ecmHost', ecmHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
get oauthConfig(): OauthConfigModel {
|
||||||
|
if (this.storage.hasItem('oauthConfig')) {
|
||||||
|
return JSON.parse(this.storage.getItem('oauthConfig'));
|
||||||
|
} else {
|
||||||
|
return this.appConfig.get<OauthConfigModel>('oauth2');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set oauthConfig(oauthConfig: OauthConfigModel) {
|
||||||
|
this.storage.setItem('oauthConfig', JSON.stringify(oauthConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
get sso(): boolean {
|
||||||
|
return this.providers === 'OAUTH' && this.oauthConfig.implicitFlow;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,70 +1,97 @@
|
|||||||
<div class="adf-setting-container">
|
<div class="adf-setting-container">
|
||||||
<div class="adf-setting-card-padding"></div>
|
|
||||||
<mat-toolbar color="primary" class="adf-setting-toolbar">
|
<mat-toolbar color="primary" class="adf-setting-toolbar">
|
||||||
<h3>{{'CORE.HOST_SETTINGS.TITLE' | translate}}</h3>
|
<h3>{{'CORE.HOST_SETTINGS.TITLE' | translate}}</h3>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
|
|
||||||
<mat-card class="adf-setting-card">
|
<mat-card class="adf-setting-card">
|
||||||
<div *ngIf="providers==='ALL' || providers==='ECM'">
|
<form id="host-form" [formGroup]="form" (submit)="onSubmit(form.value)">
|
||||||
<mat-card-header>
|
<mat-form-field>
|
||||||
<mat-card-subtitle>{{'CORE.HOST_SETTINGS.CS-HOST' | translate }}</mat-card-subtitle>
|
<mat-select placeholder="Provider" [formControl]="providers">
|
||||||
</mat-card-header>
|
<mat-option *ngFor="let provider of providersValues" [value]="provider.value">
|
||||||
|
{{ provider.title }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<ng-container *ngIf="isALL() || isECM()">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<mat-form-field class="full-width">
|
<mat-form-field class="full-width" floatLabel="{{'CORE.HOST_SETTINGS.CS-HOST' | translate }}" >
|
||||||
<mat-icon class="adf-CORE.HOST_SETTINGS-link-icon" matPrefix>link</mat-icon>
|
<mat-label>{{'CORE.HOST_SETTINGS.CS-HOST' | translate }}</mat-label>
|
||||||
<input matInput
|
<input matInput [formControl]="ecmHost" data-automation-id="ecmHost" type="text" tabindex="2" id="ecmHost" placeholder="http(s)://host|ip:port(/path)">
|
||||||
[formControl]="urlFormControlEcm"
|
<mat-error *ngIf="ecmHost.hasError('pattern')">
|
||||||
data-automation-id="ecmHost"
|
|
||||||
type="text"
|
|
||||||
(change)="onChangeECMHost($event)"
|
|
||||||
tabindex="2"
|
|
||||||
id="ecmHost"
|
|
||||||
value="{{ecmHost}}"
|
|
||||||
placeholder="http(s)://host|ip:port(/path)">
|
|
||||||
<mat-error *ngIf="urlFormControlEcm.hasError('pattern')">
|
|
||||||
{{ 'CORE.HOST_SETTINGS.NOT_VALID'| translate }}
|
{{ 'CORE.HOST_SETTINGS.NOT_VALID'| translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
<mat-error *ngIf="ecmHost.hasError('required')">
|
||||||
|
{{ 'CORE.HOST_SETTINGS.REQUIRED'| translate }}
|
||||||
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<p>
|
<p>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</div>
|
</ng-container>
|
||||||
<p>
|
|
||||||
<div *ngIf="providers==='ALL' || providers==='BPM'">
|
|
||||||
<mat-card-header>
|
|
||||||
<mat-card-subtitle>{{'CORE.HOST_SETTINGS.BP-HOST' | translate }}</mat-card-subtitle>
|
|
||||||
</mat-card-header>
|
|
||||||
<mat-card-content>
|
|
||||||
|
|
||||||
<mat-form-field class="full-width">
|
<ng-container *ngIf="isALL() || isOAUTH() || isBPM()">
|
||||||
<mat-icon class="adf-CORE.HOST_SETTINGS-link-icon" matPrefix>link</mat-icon>
|
<mat-card-content>
|
||||||
<input matInput
|
<mat-form-field class="full-width" floatLabel="{{'CORE.HOST_SETTINGS.BP-HOST' | translate }}">
|
||||||
[formControl]="urlFormControlBpm"
|
<mat-label>{{'CORE.HOST_SETTINGS.BP-HOST' | translate }}</mat-label>
|
||||||
data-automation-id="bpmHost"
|
<input matInput [formControl]="bpmHost" data-automation-id="bpmHost" type="text" tabindex="2" id="bpmHost" placeholder="http(s)://host|ip:port(/path)">
|
||||||
type="text"
|
<mat-error *ngIf="bpmHost.hasError('pattern')">
|
||||||
(change)="onChangeBPMHost($event)"
|
|
||||||
tabindex="2"
|
|
||||||
id="bpmHost"
|
|
||||||
value="{{bpmHost}}"
|
|
||||||
placeholder="http(s)://host|ip:port(/path)">
|
|
||||||
<mat-error *ngIf="urlFormControlBpm.hasError('pattern')">
|
|
||||||
{{ 'CORE.HOST_SETTINGS.NOT_VALID'| translate }}
|
{{ 'CORE.HOST_SETTINGS.NOT_VALID'| translate }}
|
||||||
</mat-error>
|
</mat-error>
|
||||||
|
<mat-error *ngIf="bpmHost.hasError('required')">
|
||||||
|
{{ 'CORE.HOST_SETTINGS.REQUIRED'| translate }}
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<ng-container *ngIf="isOAUTH()">
|
||||||
|
<div formGroupName="oauthConfig">
|
||||||
|
<mat-form-field class="full-width" floatLabel="Auth Host">
|
||||||
|
<mat-label>Auth Host</mat-label>
|
||||||
|
<input matInput name="host" id="oauthHost" formControlName="host" placeholder="http(s)://host|ip:port(/path)" >
|
||||||
|
<mat-error *ngIf="host.hasError('pattern')">
|
||||||
|
{{ 'CORE.HOST_SETTINGS.NOT_VALID'| translate }}
|
||||||
|
</mat-error>
|
||||||
|
<mat-error *ngIf="host.hasError('required')">
|
||||||
|
{{ 'CORE.HOST_SETTINGS.REQUIRED'| translate }}
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="full-width" floatLabel="Client Id">
|
||||||
|
<mat-label>{{ 'CORE.HOST_SETTINGS.CLIENT'| translate }}d</mat-label>
|
||||||
|
<input matInput name="clientId" id="clientId" formControlName="clientId" placeholder="Client Id">
|
||||||
|
<mat-error *ngIf="clientId.hasError('required')">
|
||||||
|
{{ 'CORE.HOST_SETTINGS.REQUIRED'| translate }}
|
||||||
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</mat-card-content>
|
|
||||||
</div>
|
|
||||||
<mat-card-actions class="adf-CORE.HOST_SETTINGS-actions">
|
|
||||||
|
|
||||||
<button mat-button onclick="window.history.back()" color="primary">
|
<mat-form-field class="full-width" floatLabel="Scope">
|
||||||
|
<mat-label>{{ 'CORE.HOST_SETTINGS.SCOPE'| translate }}</mat-label>
|
||||||
|
<input matInput name="{{ 'CORE.HOST_SETTINGS.SCOPE'| translate }}" formControlName="scope" placeholder="Scope Id">
|
||||||
|
<mat-error *ngIf="scope.hasError('required')">
|
||||||
|
{{ 'CORE.HOST_SETTINGS.REQUIRED'| translate }}
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<label for="silentLogin">{{ 'CORE.HOST_SETTINGS.SILENT'| translate }}</label>
|
||||||
|
<mat-slide-toggle class="full-width" name="silentLogin" [color]="'primary'" formControlName="silentLogin">
|
||||||
|
</mat-slide-toggle>
|
||||||
|
|
||||||
|
<mat-form-field class="full-width" floatLabel="Redirect Uri">
|
||||||
|
<mat-label>{{ 'CORE.HOST_SETTINGS.REDIRECT'| translate }}</mat-label>
|
||||||
|
<input matInput placeholder="{{ 'CORE.HOST_SETTINGS.REDIRECT'| translate }}" name="redirectUri" formControlName="redirectUri">
|
||||||
|
<mat-error *ngIf="redirectUri.hasError('required')">
|
||||||
|
{{ 'CORE.HOST_SETTINGS.REQUIRED'| translate }}
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</mat-card-content>
|
||||||
|
</ng-container>
|
||||||
|
<mat-card-actions class="adf-actions">
|
||||||
|
<button mat-button (click)="onCancel()" color="primary">
|
||||||
{{'CORE.HOST_SETTINGS.BACK' | translate }}
|
{{'CORE.HOST_SETTINGS.BACK' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
<button type="submit" id="host-button" tabindex="4" class="adf-login-button" mat-raised-button color="primary" data-automation-id="host-button"
|
||||||
<button mat-raised-button (click)="save($event)"
|
[disabled]="!form.valid">
|
||||||
[disabled]="urlFormControlBpm.hasError('pattern') || urlFormControlEcm.hasError('pattern')"
|
|
||||||
color="primary">
|
|
||||||
{{'CORE.HOST_SETTINGS.APPLY' | translate }}
|
{{'CORE.HOST_SETTINGS.APPLY' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
|
</form>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
<div class="adf-setting-card-padding"></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,12 +5,10 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.adf-setting-toolbar {
|
|
||||||
width: 600px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.adf-setting-container {
|
.adf-setting-container {
|
||||||
|
width: 800px;
|
||||||
display: table;
|
display: table;
|
||||||
|
margin: 0 auto;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,14 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { HostSettingsComponent } from './host-settings.component';
|
import { HostSettingsComponent } from './host-settings.component';
|
||||||
import { setupTestBed } from '../testing/setupTestBed';
|
import { setupTestBed } from '../testing/setupTestBed';
|
||||||
import { CoreTestingModule } from '../testing/core.testing.module';
|
import { CoreTestingModule } from '../testing/core.testing.module';
|
||||||
|
import { UserPreferencesService } from '../services/user-preferences.service';
|
||||||
|
|
||||||
describe('HostSettingsComponent', () => {
|
describe('HostSettingsComponent', () => {
|
||||||
|
|
||||||
let fixture: ComponentFixture<HostSettingsComponent>;
|
let fixture: ComponentFixture<HostSettingsComponent>;
|
||||||
let component: HostSettingsComponent;
|
let component: HostSettingsComponent;
|
||||||
|
let userPreferences: UserPreferencesService;
|
||||||
|
let element: any;
|
||||||
|
|
||||||
setupTestBed({
|
setupTestBed({
|
||||||
imports: [CoreTestingModule]
|
imports: [CoreTestingModule]
|
||||||
@@ -32,96 +35,262 @@ describe('HostSettingsComponent', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(HostSettingsComponent);
|
fixture = TestBed.createComponent(HostSettingsComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
userPreferences = TestBed.get(UserPreferencesService);
|
||||||
|
element = fixture.nativeElement;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
fixture.destroy();
|
fixture.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit an error when the ECM url inserted is wrong', (done) => {
|
describe('BPM ', () => {
|
||||||
|
|
||||||
|
let ecmUrlInput;
|
||||||
|
let bpmUrlInput;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
userPreferences.providers = 'BPM';
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
bpmUrlInput = element.querySelector('#bpmHost');
|
||||||
component.error.subscribe((message: string) => {
|
ecmUrlInput = element.querySelector('#ecmHost');
|
||||||
expect(message).toEqual('CORE.HOST_SETTING.CS_URL_ERROR');
|
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const ecmUrlInput = fixture.nativeElement.querySelector('#ecmHost');
|
afterEach(() => {
|
||||||
ecmUrlInput.value = 'wrong_url';
|
fixture.destroy();
|
||||||
|
|
||||||
const event: any = {};
|
|
||||||
event.target = ecmUrlInput;
|
|
||||||
component.onChangeECMHost(event);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit ecmHostChange when the ECM url inserted is correct', (done) => {
|
it('should have a valid form when the url inserted is correct', (done) => {
|
||||||
fixture.detectChanges();
|
|
||||||
const url = 'http://localhost:9999/ecm';
|
|
||||||
component.ecmHostChange.subscribe((message: string) => {
|
|
||||||
expect(message).toEqual(url);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
const ecmUrlInput = fixture.nativeElement.querySelector('#ecmHost');
|
|
||||||
ecmUrlInput.value = url;
|
|
||||||
|
|
||||||
const event: any = {};
|
|
||||||
event.target = ecmUrlInput;
|
|
||||||
component.onChangeECMHost(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should emit an error when the BPM url inserted is wrong', (done) => {
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
component.error.subscribe((message: string) => {
|
|
||||||
expect(message).toEqual('CORE.HOST_SETTING.PS_URL_ERROR');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
const bpmUrlInput: any = fixture.nativeElement.querySelector('#bpmHost');
|
|
||||||
bpmUrlInput.value = 'wrong_url';
|
|
||||||
|
|
||||||
const event: any = {};
|
|
||||||
event.target = bpmUrlInput;
|
|
||||||
component.onChangeBPMHost(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should emit bpmHostChange when the BPM url inserted is correct', (done) => {
|
|
||||||
fixture.detectChanges();
|
|
||||||
const url = 'http://localhost:9999/bpm';
|
const url = 'http://localhost:9999/bpm';
|
||||||
|
|
||||||
component.ecmHostChange.subscribe((message: string) => {
|
component.form.statusChanges.subscribe((status: string) => {
|
||||||
expect(message).toEqual(url);
|
expect(status).toEqual('VALID');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
const ecmUrlInput = fixture.nativeElement.querySelector('#bpmHost');
|
component.form.valueChanges.subscribe((values) => {
|
||||||
ecmUrlInput.value = url;
|
expect(values.bpmHost).toEqual(url);
|
||||||
|
});
|
||||||
|
|
||||||
const event: any = {};
|
bpmUrlInput.value = url;
|
||||||
event.target = ecmUrlInput;
|
bpmUrlInput.dispatchEvent(new Event('input'));
|
||||||
component.onChangeECMHost(event);
|
});
|
||||||
|
|
||||||
|
it('should have an invalid form when the inserted is wrong', (done) => {
|
||||||
|
const url = 'wrong';
|
||||||
|
|
||||||
|
component.form.statusChanges.subscribe((status: string) => {
|
||||||
|
expect(status).toEqual('INVALID');
|
||||||
|
expect(component.bpmHost.hasError('pattern')).toBeTruthy();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
bpmUrlInput.value = url;
|
||||||
|
bpmUrlInput.dispatchEvent(new Event('input'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not render the ECM url config if setting provider is BPM', () => {
|
it('should not render the ECM url config if setting provider is BPM', () => {
|
||||||
component.providers = 'BPM';
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
const bpmUrlInput = fixture.nativeElement.querySelector('#bpmHost');
|
|
||||||
const ecmUrlInput = fixture.nativeElement.querySelector('#ecmHost');
|
|
||||||
expect(ecmUrlInput).toEqual(null);
|
expect(ecmUrlInput).toEqual(null);
|
||||||
expect(bpmUrlInput).toBeDefined();
|
expect(bpmUrlInput).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should hide the BPM url config if setting provider is ECM', () => {
|
});
|
||||||
component.providers = 'ECM';
|
|
||||||
|
|
||||||
|
describe('ECM ', () => {
|
||||||
|
|
||||||
|
let ecmUrlInput;
|
||||||
|
let bpmUrlInput;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
userPreferences.providers = 'ECM';
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
bpmUrlInput = element.querySelector('#bpmHost');
|
||||||
|
ecmUrlInput = element.querySelector('#ecmHost');
|
||||||
|
});
|
||||||
|
|
||||||
const ecmUrlInput = fixture.nativeElement.querySelector('#ecmHost');
|
afterEach(() => {
|
||||||
const bpmUrlInput = fixture.nativeElement.querySelector('#bpmHost');
|
fixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a valid form when the url inserted is correct', (done) => {
|
||||||
|
const url = 'http://localhost:9999/ecm';
|
||||||
|
|
||||||
|
component.form.statusChanges.subscribe((status: string) => {
|
||||||
|
expect(status).toEqual('VALID');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
ecmUrlInput.value = url;
|
||||||
|
ecmUrlInput.dispatchEvent(new Event('input'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have an invalid form when the url inserted is wrong', (done) => {
|
||||||
|
const url = 'wrong';
|
||||||
|
|
||||||
|
component.form.statusChanges.subscribe((status: string) => {
|
||||||
|
expect(status).toEqual('INVALID');
|
||||||
|
expect(component.ecmHost.hasError('pattern')).toBeTruthy();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
ecmUrlInput.value = url;
|
||||||
|
ecmUrlInput.dispatchEvent(new Event('input'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not render the BPM url config if setting provider is BPM', () => {
|
||||||
expect(bpmUrlInput).toEqual(null);
|
expect(bpmUrlInput).toEqual(null);
|
||||||
expect(ecmUrlInput).toBeDefined();
|
expect(ecmUrlInput).toBeDefined();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('ALL ', () => {
|
||||||
|
|
||||||
|
let ecmUrlInput;
|
||||||
|
let bpmUrlInput;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
userPreferences.providers = 'ALL';
|
||||||
|
fixture.detectChanges();
|
||||||
|
bpmUrlInput = element.querySelector('#bpmHost');
|
||||||
|
ecmUrlInput = element.querySelector('#ecmHost');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a valid form when the BPM and ECM url inserted are correct', (done) => {
|
||||||
|
const urlEcm = 'http://localhost:9999/ecm';
|
||||||
|
const urlBpm = 'http://localhost:9999/bpm';
|
||||||
|
|
||||||
|
component.form.statusChanges.subscribe((status: string) => {
|
||||||
|
expect(status).toEqual('VALID');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
ecmUrlInput.value = urlEcm;
|
||||||
|
bpmUrlInput.value = urlBpm;
|
||||||
|
ecmUrlInput.dispatchEvent(new Event('input'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have an invalid form when one of the ECM url inserted is wrong', (done) => {
|
||||||
|
const url = 'wrong';
|
||||||
|
|
||||||
|
component.form.statusChanges.subscribe((status: string) => {
|
||||||
|
expect(status).toEqual('INVALID');
|
||||||
|
expect(component.ecmHost.hasError('pattern')).toBeTruthy();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
ecmUrlInput.value = url;
|
||||||
|
ecmUrlInput.dispatchEvent(new Event('input'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have an invalid form when one of the BPM url inserted is wrong', (done) => {
|
||||||
|
const url = 'wrong';
|
||||||
|
|
||||||
|
component.form.statusChanges.subscribe((status: string) => {
|
||||||
|
expect(status).toEqual('INVALID');
|
||||||
|
expect(component.bpmHost.hasError('pattern')).toBeTruthy();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
bpmUrlInput.value = url;
|
||||||
|
bpmUrlInput.dispatchEvent(new Event('input'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have an invalid form when both BPM and ECM url inserted are wrong', (done) => {
|
||||||
|
const url = 'wrong';
|
||||||
|
|
||||||
|
component.form.statusChanges.subscribe((status: string) => {
|
||||||
|
expect(status).toEqual('INVALID');
|
||||||
|
expect(component.bpmHost.hasError('pattern')).toBeTruthy();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
bpmUrlInput.value = url;
|
||||||
|
ecmUrlInput.value = url;
|
||||||
|
bpmUrlInput.dispatchEvent(new Event('input'));
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('OAUTH ', () => {
|
||||||
|
|
||||||
|
let ecmUrlInput;
|
||||||
|
let bpmUrlInput;
|
||||||
|
let oauthHostUrlInput;
|
||||||
|
let clientIdInput;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
userPreferences.providers = 'OAUTH';
|
||||||
|
userPreferences.oauthConfig = {
|
||||||
|
host: 'http://localhost:6543',
|
||||||
|
redirectUri: '/',
|
||||||
|
silentLogin: false,
|
||||||
|
implicitFlow: true,
|
||||||
|
clientId: 'activiti',
|
||||||
|
scope: 'openid',
|
||||||
|
secret: ''
|
||||||
|
};
|
||||||
|
fixture.detectChanges();
|
||||||
|
bpmUrlInput = element.querySelector('#bpmHost');
|
||||||
|
oauthHostUrlInput = element.querySelector('#oauthHost');
|
||||||
|
clientIdInput = element.querySelector('#clientId');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
fixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a valid form when the BPM is correct', (done) => {
|
||||||
|
const urlBpm = 'http://localhost:9999/bpm';
|
||||||
|
|
||||||
|
component.form.statusChanges.subscribe((status: string) => {
|
||||||
|
expect(status).toEqual('VALID');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
bpmUrlInput.value = urlBpm;
|
||||||
|
bpmUrlInput.dispatchEvent(new Event('input'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have an invalid form when the url inserted is wrong', (done) => {
|
||||||
|
const url = 'wrong';
|
||||||
|
|
||||||
|
component.form.statusChanges.subscribe((status: string) => {
|
||||||
|
expect(status).toEqual('INVALID');
|
||||||
|
expect(component.bpmHost.hasError('pattern')).toBeTruthy();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
bpmUrlInput.value = url;
|
||||||
|
bpmUrlInput.dispatchEvent(new Event('input'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have an invalid form when the host is wrong', (done) => {
|
||||||
|
const hostUrl = 'wrong';
|
||||||
|
|
||||||
|
component.form.statusChanges.subscribe((status: string) => {
|
||||||
|
expect(status).toEqual('INVALID');
|
||||||
|
expect(component.host.hasError('pattern')).toBeTruthy();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
oauthHostUrlInput.value = hostUrl;
|
||||||
|
oauthHostUrlInput.dispatchEvent(new Event('input'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a required clientId an invalid form when the clientId is missing', (done) => {
|
||||||
|
component.form.statusChanges.subscribe((status: string) => {
|
||||||
|
expect(status).toEqual('INVALID');
|
||||||
|
expect(component.clientId.hasError('required')).toBeTruthy();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
clientIdInput.value = '';
|
||||||
|
clientIdInput.dispatchEvent(new Event('input'));
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,12 +15,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
|
import { Component, EventEmitter, Output, ViewEncapsulation, OnInit } from '@angular/core';
|
||||||
import { FormControl, Validators } from '@angular/forms';
|
import { Validators, FormGroup, FormBuilder, AbstractControl } from '@angular/forms';
|
||||||
import { LogService } from '../services/log.service';
|
import { UserPreferencesService } from '../services';
|
||||||
import { SettingsService } from '../services/settings.service';
|
|
||||||
import { StorageService } from '../services/storage.service';
|
|
||||||
import { TranslationService } from '../services/translation.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-host-settings',
|
selector: 'adf-host-settings',
|
||||||
@@ -31,20 +28,18 @@ import { TranslationService } from '../services/translation.service';
|
|||||||
styleUrls: ['host-settings.component.scss'],
|
styleUrls: ['host-settings.component.scss'],
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class HostSettingsComponent {
|
export class HostSettingsComponent implements OnInit {
|
||||||
|
|
||||||
HOST_REGEX: string = '^(http|https):\/\/.*[^/]$';
|
HOST_REGEX: string = '^(http|https):\/\/.*[^/]$';
|
||||||
|
|
||||||
ecmHost: string;
|
providersValues = [
|
||||||
ecmHostTmp: string;
|
{ title: 'ECM and BPM', value: 'ALL' },
|
||||||
bpmHost: string;
|
{ title: 'BPM', value: 'BPM' },
|
||||||
bpmHostTmp: string;
|
{ title: 'ECM', value: 'ECM' },
|
||||||
urlFormControlEcm = new FormControl('', [Validators.required, Validators.pattern(this.HOST_REGEX)]);
|
{ title: 'OAUTH', value: 'OAUTH' }
|
||||||
urlFormControlBpm = new FormControl('', [Validators.required, Validators.pattern(this.HOST_REGEX)]);
|
];
|
||||||
|
|
||||||
/** Determines which configurations are shown. Possible valid values are "ECM", "BPM" or "ALL". */
|
form: FormGroup;
|
||||||
@Input()
|
|
||||||
providers: string = 'ALL';
|
|
||||||
|
|
||||||
/** Emitted when the URL is invalid. */
|
/** Emitted when the URL is invalid. */
|
||||||
@Output()
|
@Output()
|
||||||
@@ -54,56 +49,136 @@ export class HostSettingsComponent {
|
|||||||
@Output()
|
@Output()
|
||||||
ecmHostChange = new EventEmitter<string>();
|
ecmHostChange = new EventEmitter<string>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
cancel = new EventEmitter<boolean>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
success = new EventEmitter<boolean>();
|
||||||
|
|
||||||
/** Emitted when the bpm host URL is changed. */
|
/** Emitted when the bpm host URL is changed. */
|
||||||
@Output()
|
@Output()
|
||||||
bpmHostChange = new EventEmitter<string>();
|
bpmHostChange = new EventEmitter<string>();
|
||||||
|
|
||||||
constructor(private settingsService: SettingsService,
|
constructor(private fb: FormBuilder,
|
||||||
private storage: StorageService,
|
private userPreference: UserPreferencesService) {
|
||||||
private logService: LogService,
|
|
||||||
private translationService: TranslationService) {
|
|
||||||
this.ecmHostTmp = this.ecmHost = storage.getItem('ecmHost') || this.settingsService.ecmHost;
|
|
||||||
this.bpmHostTmp = this.bpmHost = storage.getItem('bpmHost') || this.settingsService.bpmHost;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onChangeECMHost(event: any): void {
|
ngOnInit() {
|
||||||
let value = (<HTMLInputElement> event.target).value.trim();
|
|
||||||
if (value && this.isValidUrl(value)) {
|
let providerSelected = this.userPreference.providers;
|
||||||
this.logService.info(`ECM host: ${value}`);
|
|
||||||
this.ecmHostTmp = value;
|
this.form = this.fb.group({
|
||||||
this.ecmHostChange.emit(value);
|
providers: [providerSelected, Validators.required],
|
||||||
} else {
|
ecmHost: [this.userPreference.ecmHost, [Validators.required, Validators.pattern(this.HOST_REGEX)]],
|
||||||
this.translationService.get('CORE.HOST_SETTING.CS_URL_ERROR').subscribe((message) => {
|
bpmHost: [this.userPreference.bpmHost, [Validators.required, Validators.pattern(this.HOST_REGEX)]]
|
||||||
this.error.emit(message);
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public onChangeBPMHost(event: any): void {
|
const oAuthConfig = this.userPreference.oauthConfig;
|
||||||
let value = (<HTMLInputElement> event.target).value.trim();
|
if (oAuthConfig) {
|
||||||
if (value && this.isValidUrl(value)) {
|
const oauthGroup = this.fb.group( {
|
||||||
this.logService.info(`BPM host: ${value}`);
|
host: [oAuthConfig.host, [Validators.required, Validators.pattern(this.HOST_REGEX)]],
|
||||||
this.bpmHostTmp = value;
|
clientId: [oAuthConfig.clientId, Validators.required],
|
||||||
this.bpmHostChange.emit(value);
|
redirectUri: [oAuthConfig.redirectUri, Validators.required],
|
||||||
} else {
|
scope: [oAuthConfig.scope, Validators.required],
|
||||||
this.translationService.get('CORE.HOST_SETTING.PS_URL_ERROR').subscribe((message) => {
|
secret: oAuthConfig.secret,
|
||||||
this.error.emit(message);
|
silentLogin: oAuthConfig.silentLogin,
|
||||||
|
implicitFlow: oAuthConfig.implicitFlow
|
||||||
});
|
});
|
||||||
}
|
this.form.addControl('oauthConfig', oauthGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
public save(event: KeyboardEvent): void {
|
|
||||||
if (this.bpmHost !== this.bpmHostTmp) {
|
|
||||||
this.storage.setItem(`bpmHost`, this.bpmHostTmp);
|
|
||||||
}
|
|
||||||
if (this.ecmHost !== this.ecmHostTmp) {
|
|
||||||
this.storage.setItem(`ecmHost`, this.ecmHostTmp);
|
|
||||||
}
|
|
||||||
window.location.href = '/';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isValidUrl(url: string) {
|
onCancel() {
|
||||||
return /^(http|https):\/\/.*/.test(url);
|
this.cancel.emit(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit(values: any) {
|
||||||
|
this.userPreference.providers = values.providers;
|
||||||
|
if (this.isBPM()) {
|
||||||
|
this.saveBPMValues(values);
|
||||||
|
} else if (this.isECM()) {
|
||||||
|
this.saveECMValues(values);
|
||||||
|
} else if (this.isALL()) {
|
||||||
|
this.saveECMValues(values);
|
||||||
|
this.saveBPMValues(values);
|
||||||
|
} else if (this.isOAUTH()) {
|
||||||
|
this.saveOAuthValues(values);
|
||||||
|
}
|
||||||
|
this.success.emit(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
saveOAuthValues(values: any) {
|
||||||
|
this.userPreference.oauthConfig = values.oauthConfig;
|
||||||
|
this.userPreference.bpmHost = values.bpmHost;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveBPMValues(values: any) {
|
||||||
|
this.userPreference.bpmHost = values.bpmHost;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveECMValues(values: any) {
|
||||||
|
this.userPreference.ecmHost = values.ecmHost;
|
||||||
|
}
|
||||||
|
|
||||||
|
isBPM(): boolean {
|
||||||
|
return this.providers.value === 'BPM';
|
||||||
|
}
|
||||||
|
|
||||||
|
isECM(): boolean {
|
||||||
|
return this.providers.value === 'ECM';
|
||||||
|
}
|
||||||
|
|
||||||
|
isALL(): boolean {
|
||||||
|
return this.providers.value === 'ALL';
|
||||||
|
}
|
||||||
|
|
||||||
|
isOAUTH(): boolean {
|
||||||
|
return this.providers.value === 'OAUTH';
|
||||||
|
}
|
||||||
|
|
||||||
|
get providers(): AbstractControl {
|
||||||
|
return this.form.get('providers');
|
||||||
|
}
|
||||||
|
|
||||||
|
get bpmHost(): AbstractControl {
|
||||||
|
return this.form.get('bpmHost');
|
||||||
|
}
|
||||||
|
|
||||||
|
get ecmHost(): AbstractControl {
|
||||||
|
return this.form.get('ecmHost');
|
||||||
|
}
|
||||||
|
|
||||||
|
get host(): AbstractControl {
|
||||||
|
return this.oauthConfig.get('host');
|
||||||
|
}
|
||||||
|
|
||||||
|
get clientId(): AbstractControl {
|
||||||
|
return this.oauthConfig.get('clientId');
|
||||||
|
}
|
||||||
|
|
||||||
|
get scope(): AbstractControl {
|
||||||
|
return this.oauthConfig.get('scope');
|
||||||
|
}
|
||||||
|
|
||||||
|
get secretId(): AbstractControl {
|
||||||
|
return this.oauthConfig.get('secretId');
|
||||||
|
}
|
||||||
|
|
||||||
|
get implicitFlow(): AbstractControl {
|
||||||
|
return this.oauthConfig.get('implicitFlow');
|
||||||
|
}
|
||||||
|
|
||||||
|
get silentLogin(): AbstractControl {
|
||||||
|
return this.oauthConfig.get('silentLogin');
|
||||||
|
}
|
||||||
|
|
||||||
|
get redirectUri(): AbstractControl {
|
||||||
|
return this.oauthConfig.get('redirectUri');
|
||||||
|
}
|
||||||
|
|
||||||
|
get oauthConfig(): AbstractControl {
|
||||||
|
return this.form.get('oauthConfig');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ export const setupTestBed = (moduleDef: TestModuleMetadata) => {
|
|||||||
preventAngularFromResetting();
|
preventAngularFromResetting();
|
||||||
TestBed.configureTestingModule(moduleDef);
|
TestBed.configureTestingModule(moduleDef);
|
||||||
await TestBed.compileComponents();
|
await TestBed.compileComponents();
|
||||||
|
localStorage.clear();
|
||||||
|
sessionStorage.clear();
|
||||||
|
|
||||||
// prevent Angular from resetting testing module
|
// prevent Angular from resetting testing module
|
||||||
TestBed.resetTestingModule = () => TestBed;
|
TestBed.resetTestingModule = () => TestBed;
|
||||||
|
|||||||
@@ -15,11 +15,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { async } from '@angular/core/testing';
|
import { async, TestBed } from '@angular/core/testing';
|
||||||
import { mockError, fakeProcessFilters } from '../../mock';
|
import { mockError, fakeProcessFilters } from '../../mock';
|
||||||
import { FilterProcessRepresentationModel } from '../models/filter-process.model';
|
import { FilterProcessRepresentationModel } from '../models/filter-process.model';
|
||||||
import { ProcessFilterService } from './process-filter.service';
|
import { ProcessFilterService } from './process-filter.service';
|
||||||
import { AlfrescoApiServiceMock, AlfrescoApiService, AppConfigService, StorageService } from '@alfresco/adf-core';
|
import { AlfrescoApiServiceMock, AlfrescoApiService, AppConfigService, StorageService, UserPreferencesService, setupTestBed, CoreModule } from '@alfresco/adf-core';
|
||||||
|
|
||||||
declare let jasmine: any;
|
declare let jasmine: any;
|
||||||
|
|
||||||
@@ -28,9 +28,17 @@ describe('Process filter', () => {
|
|||||||
let service: ProcessFilterService;
|
let service: ProcessFilterService;
|
||||||
let apiService: AlfrescoApiService;
|
let apiService: AlfrescoApiService;
|
||||||
let alfrescoApi: any;
|
let alfrescoApi: any;
|
||||||
|
let userPreferences: UserPreferencesService;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
CoreModule.forRoot()
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
apiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService() );
|
userPreferences = TestBed.get(UserPreferencesService);
|
||||||
|
apiService = new AlfrescoApiServiceMock(new AppConfigService(null), userPreferences, new StorageService() );
|
||||||
service = new ProcessFilterService(apiService);
|
service = new ProcessFilterService(apiService);
|
||||||
alfrescoApi = apiService.getInstance();
|
alfrescoApi = apiService.getInstance();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,13 +15,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { async } from '@angular/core/testing';
|
import { async, TestBed } from '@angular/core/testing';
|
||||||
import { exampleProcess, fakeProcessInstances } from '../../mock';
|
import { exampleProcess, fakeProcessInstances } from '../../mock';
|
||||||
import { mockError, fakeProcessDef, fakeTasksList } from '../../mock';
|
import { mockError, fakeProcessDef, fakeTasksList } from '../../mock';
|
||||||
import { ProcessFilterParamRepresentationModel } from '../models/filter-process.model';
|
import { ProcessFilterParamRepresentationModel } from '../models/filter-process.model';
|
||||||
import { ProcessInstanceVariable } from '../models/process-instance-variable.model';
|
import { ProcessInstanceVariable } from '../models/process-instance-variable.model';
|
||||||
import { ProcessService } from './process.service';
|
import { ProcessService } from './process.service';
|
||||||
import { AlfrescoApiService, AlfrescoApiServiceMock, AppConfigService, StorageService } from '@alfresco/adf-core';
|
import { AlfrescoApiService, AlfrescoApiServiceMock, AppConfigService, StorageService, UserPreferencesService, setupTestBed, CoreModule } from '@alfresco/adf-core';
|
||||||
|
|
||||||
declare let moment: any;
|
declare let moment: any;
|
||||||
|
|
||||||
@@ -30,9 +30,17 @@ describe('ProcessService', () => {
|
|||||||
let service: ProcessService;
|
let service: ProcessService;
|
||||||
let apiService: AlfrescoApiService;
|
let apiService: AlfrescoApiService;
|
||||||
let alfrescoApi: any;
|
let alfrescoApi: any;
|
||||||
|
let userPreferences: UserPreferencesService;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
CoreModule.forRoot()
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
apiService = new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService() );
|
userPreferences = TestBed.get(UserPreferencesService);
|
||||||
|
apiService = new AlfrescoApiServiceMock(new AppConfigService(null), userPreferences, new StorageService() );
|
||||||
service = new ProcessService(apiService);
|
service = new ProcessService(apiService);
|
||||||
alfrescoApi = apiService.getInstance();
|
alfrescoApi = apiService.getInstance();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { async } from '@angular/core/testing';
|
import { async, TestBed } from '@angular/core/testing';
|
||||||
import {
|
import {
|
||||||
fakeAppFilter,
|
fakeAppFilter,
|
||||||
fakeAppPromise,
|
fakeAppPromise,
|
||||||
@@ -23,15 +23,24 @@ import {
|
|||||||
} from '../../mock';
|
} from '../../mock';
|
||||||
import { FilterRepresentationModel } from '../models/filter.model';
|
import { FilterRepresentationModel } from '../models/filter.model';
|
||||||
import { TaskFilterService } from './task-filter.service';
|
import { TaskFilterService } from './task-filter.service';
|
||||||
import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService } from '@alfresco/adf-core';
|
import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService, setupTestBed, CoreModule, UserPreferencesService } from '@alfresco/adf-core';
|
||||||
|
|
||||||
declare let jasmine: any;
|
declare let jasmine: any;
|
||||||
|
|
||||||
describe('Activiti Task filter Service', () => {
|
describe('Activiti Task filter Service', () => {
|
||||||
|
|
||||||
let service: TaskFilterService;
|
let service: TaskFilterService;
|
||||||
|
let userPreferences: UserPreferencesService;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
CoreModule.forRoot()
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
service = new TaskFilterService(new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService()), new LogService(new AppConfigService(null)));
|
userPreferences = TestBed.get(UserPreferencesService);
|
||||||
|
service = new TaskFilterService(new AlfrescoApiServiceMock(new AppConfigService(null), userPreferences, new StorageService()), new LogService(new AppConfigService(null)));
|
||||||
jasmine.Ajax.install();
|
jasmine.Ajax.install();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { async } from '@angular/core/testing';
|
import { async, TestBed } from '@angular/core/testing';
|
||||||
import { UserProcessModel } from '@alfresco/adf-core';
|
import { UserProcessModel, setupTestBed, CoreModule } from '@alfresco/adf-core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import {
|
import {
|
||||||
fakeCompletedTaskList,
|
fakeCompletedTaskList,
|
||||||
@@ -35,16 +35,24 @@ import {
|
|||||||
import { FilterRepresentationModel, TaskQueryRequestRepresentationModel } from '../models/filter.model';
|
import { FilterRepresentationModel, TaskQueryRequestRepresentationModel } from '../models/filter.model';
|
||||||
import { TaskDetailsModel } from '../models/task-details.model';
|
import { TaskDetailsModel } from '../models/task-details.model';
|
||||||
import { TaskListService } from './tasklist.service';
|
import { TaskListService } from './tasklist.service';
|
||||||
import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService } from '@alfresco/adf-core';
|
import { AlfrescoApiServiceMock, LogService, AppConfigService, StorageService, UserPreferencesService } from '@alfresco/adf-core';
|
||||||
|
|
||||||
declare let jasmine: any;
|
declare let jasmine: any;
|
||||||
|
|
||||||
describe('Activiti TaskList Service', () => {
|
describe('Activiti TaskList Service', () => {
|
||||||
|
|
||||||
let service: TaskListService;
|
let service: TaskListService;
|
||||||
|
let userPreferences: UserPreferencesService;
|
||||||
|
|
||||||
|
setupTestBed({
|
||||||
|
imports: [
|
||||||
|
CoreModule.forRoot()
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
service = new TaskListService(new AlfrescoApiServiceMock(new AppConfigService(null), new StorageService() ), new LogService(new AppConfigService(null)));
|
userPreferences = TestBed.get(UserPreferencesService);
|
||||||
|
service = new TaskListService(new AlfrescoApiServiceMock(new AppConfigService(null), userPreferences, new StorageService() ), new LogService(new AppConfigService(null)));
|
||||||
jasmine.Ajax.install();
|
jasmine.Ajax.install();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
Generated
+27
-106
@@ -1033,6 +1033,14 @@
|
|||||||
"tslib": "1.9.1"
|
"tslib": "1.9.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@auth0/angular-jwt": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@auth0/angular-jwt/-/angular-jwt-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-T2t8ed4/g/w5aniVmOJ7AieTrQ9iU7urAbzRBx5OToY4UeEzzng+yP4yk114Xwoi3iV9AS4zhqMqgKcQ3vNvxA==",
|
||||||
|
"requires": {
|
||||||
|
"url": "0.11.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@mat-datetimepicker/core": {
|
"@mat-datetimepicker/core": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@mat-datetimepicker/core/-/core-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@mat-datetimepicker/core/-/core-1.0.4.tgz",
|
||||||
@@ -1403,9 +1411,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"alfresco-js-api": {
|
"alfresco-js-api": {
|
||||||
"version": "2.4.0-beta6",
|
"version": "2.4.0-fed4e011ee70eb36b5e2015859e719153d70b6c2",
|
||||||
"resolved": "https://registry.npmjs.org/alfresco-js-api/-/alfresco-js-api-2.4.0-beta6.tgz",
|
"resolved": "https://registry.npmjs.org/alfresco-js-api/-/alfresco-js-api-2.4.0-fed4e011ee70eb36b5e2015859e719153d70b6c2.tgz",
|
||||||
"integrity": "sha512-ytEScVOdD9MeoIqkYwBHVE/GpmwD/0PE9eEEMZLzs/7r5igDhqIw4BrleIerfXh/S4y+U15fP0UFv++BW2XKEQ==",
|
"integrity": "sha512-HWA2zLbuRTi1mjIoaEW2ZSWKMDfOWcYOgplFZovQgXUOaFZuPJH1AQ7RbImq/G5/NKwe9AJSUAnkg5vpuKEBTg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"event-emitter": "0.3.4",
|
"event-emitter": "0.3.4",
|
||||||
"superagent": "3.8.2"
|
"superagent": "3.8.2"
|
||||||
@@ -1477,6 +1485,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"angular-oauth2-oidc": {
|
||||||
|
"version": "3.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/angular-oauth2-oidc/-/angular-oauth2-oidc-3.1.4.tgz",
|
||||||
|
"integrity": "sha1-B3k5VhbXLxXp3985Ld2pxpY3Qug=",
|
||||||
|
"requires": {
|
||||||
|
"jsrsasign": "8.0.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"angular2-template-loader": {
|
"angular2-template-loader": {
|
||||||
"version": "0.6.2",
|
"version": "0.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/angular2-template-loader/-/angular2-template-loader-0.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/angular2-template-loader/-/angular2-template-loader-0.6.2.tgz",
|
||||||
@@ -5888,30 +5904,6 @@
|
|||||||
"locate-path": "2.0.0"
|
"locate-path": "2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"findup": {
|
|
||||||
"version": "0.1.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/findup/-/findup-0.1.5.tgz",
|
|
||||||
"integrity": "sha1-itkpozk7rGJ5V6fl3kYjsGsOLOs=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"colors": "0.6.2",
|
|
||||||
"commander": "2.1.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"colors": {
|
|
||||||
"version": "0.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz",
|
|
||||||
"integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"commander": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz",
|
|
||||||
"integrity": "sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E=",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flatten": {
|
"flatten": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz",
|
||||||
@@ -6853,28 +6845,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ghooks": {
|
|
||||||
"version": "2.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/ghooks/-/ghooks-2.0.4.tgz",
|
|
||||||
"integrity": "sha1-/VDgQP9UiQauQstReToBv+JFZ7k=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"findup": "0.1.5",
|
|
||||||
"lodash.clone": "4.5.0",
|
|
||||||
"manage-path": "2.0.0",
|
|
||||||
"opt-cli": "1.5.1",
|
|
||||||
"path-exists": "3.0.0",
|
|
||||||
"spawn-command": "0.0.2"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"spawn-command": {
|
|
||||||
"version": "0.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz",
|
|
||||||
"integrity": "sha1-lUThpDygRfhTGqwaSMspva5iM44=",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"github-build": {
|
"github-build": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/github-build/-/github-build-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/github-build/-/github-build-1.2.0.tgz",
|
||||||
@@ -8951,6 +8921,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"jsrsasign": {
|
||||||
|
"version": "8.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-8.0.12.tgz",
|
||||||
|
"integrity": "sha1-Iqu5ZW00owuVMENnIINeicLlwxY="
|
||||||
|
},
|
||||||
"karma": {
|
"karma": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/karma/-/karma-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/karma/-/karma-2.0.2.tgz",
|
||||||
@@ -9467,14 +9442,7 @@
|
|||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.10",
|
"version": "4.17.10",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
|
||||||
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
|
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"lodash._baseclone": {
|
|
||||||
"version": "4.5.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz",
|
|
||||||
"integrity": "sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ=",
|
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"lodash._basecopy": {
|
"lodash._basecopy": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
@@ -9555,12 +9523,6 @@
|
|||||||
"lodash._createcompounder": "3.0.0"
|
"lodash._createcompounder": "3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lodash.clone": {
|
|
||||||
"version": "4.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz",
|
|
||||||
"integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"lodash.clonedeep": {
|
"lodash.clonedeep": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||||
@@ -10018,12 +9980,6 @@
|
|||||||
"integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==",
|
"integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"manage-path": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/manage-path/-/manage-path-2.0.0.tgz",
|
|
||||||
"integrity": "sha1-9M+EV7km7u4qg7FzUBQUvHbrlZc=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"map-cache": {
|
"map-cache": {
|
||||||
"version": "0.2.2",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
|
||||||
@@ -11519,38 +11475,6 @@
|
|||||||
"is-wsl": "1.1.0"
|
"is-wsl": "1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"opt-cli": {
|
|
||||||
"version": "1.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/opt-cli/-/opt-cli-1.5.1.tgz",
|
|
||||||
"integrity": "sha1-BNtEexPJa5kusxaFJm9O0NlzbcI=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"commander": "2.9.0",
|
|
||||||
"lodash.clone": "4.3.2",
|
|
||||||
"manage-path": "2.0.0",
|
|
||||||
"spawn-command": "0.0.2-1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"commander": {
|
|
||||||
"version": "2.9.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
|
|
||||||
"integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"graceful-readlink": "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lodash.clone": {
|
|
||||||
"version": "4.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.3.2.tgz",
|
|
||||||
"integrity": "sha1-5WsXa2gjp93jj38r9Y3n1ZcSAOk=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"lodash._baseclone": "4.5.7"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"optimist": {
|
"optimist": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
|
||||||
@@ -14575,8 +14499,7 @@
|
|||||||
"querystring": {
|
"querystring": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
||||||
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
|
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"querystring-es3": {
|
"querystring-es3": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
@@ -18756,7 +18679,6 @@
|
|||||||
"version": "0.11.0",
|
"version": "0.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
|
||||||
"integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
|
"integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"punycode": "1.3.2",
|
"punycode": "1.3.2",
|
||||||
"querystring": "0.2.0"
|
"querystring": "0.2.0"
|
||||||
@@ -18765,8 +18687,7 @@
|
|||||||
"punycode": {
|
"punycode": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
|
||||||
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
|
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user