From f47cebc0a40a1c1af37b4443fffc6ad01a5f1520 Mon Sep 17 00:00:00 2001 From: Eugenio Romano Date: Fri, 14 Jun 2019 16:02:12 +0100 Subject: [PATCH] [ADF-4665] [ADF] - Application is refreshed when you have two instances of application opened (#4849) * refactoring getValueFromToken and fix user token refresh * refactoring getValueFromToken and fix user token refresh * refactoring getValueFromToken and fix user token refres * fix unit test --- .travis.yml | 2 +- .../services/task-filter-cloud.service.md | 2 +- .../auth-guard-sso-role.service.spec.ts | 29 +++++------ .../services/auth-guard-sso-role.service.ts | 16 ++---- lib/core/services/auth-guard.service.ts | 8 ++- lib/core/services/authentication.service.ts | 3 +- lib/core/services/jwt-helper.service.ts | 35 ++++++++++++- .../services/identity-user.service.ts | 50 ++++++------------- .../services/task-filter-cloud.service.ts | 20 ++------ package-lock.json | 22 ++++++-- .../{update-childre.sh => update-children.sh} | 0 11 files changed, 94 insertions(+), 93 deletions(-) rename scripts/travis/update/{update-childre.sh => update-children.sh} (100%) diff --git a/.travis.yml b/.travis.yml index 0ae3987849..2da482450e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -61,7 +61,7 @@ jobs: - stage: Update children projects dependency #Update children projects dependency name: Update Related Project if: tag =~ .*beta.* - script: ./scripts/update-project.sh + script: ./scripts/travis/update-children.sh - stage: e2e Test name: core script: ./scripts/travis/e2e/core-e2e.sh diff --git a/docs/process-services-cloud/services/task-filter-cloud.service.md b/docs/process-services-cloud/services/task-filter-cloud.service.md index 7635fdb802..451997f1c0 100644 --- a/docs/process-services-cloud/services/task-filter-cloud.service.md +++ b/docs/process-services-cloud/services/task-filter-cloud.service.md @@ -39,7 +39,7 @@ Manages task filters. - **getUsername**(): `string`
Gets the username field from the access token. - **Returns** `string` - Username string -- **getValueFromToken**(key: `string`)
+- **getValueFromLocalAccessToken**(key: `string`)
Gets a named value from the access token. - _key:_ `string` - Key name of the value - **updateFilter**(filter: [`TaskFilterCloudModel`](../../../lib/process-services-cloud/src/lib/task/task-filters/models/filter-cloud.model.ts))
diff --git a/lib/core/services/auth-guard-sso-role.service.spec.ts b/lib/core/services/auth-guard-sso-role.service.spec.ts index 942afc09bf..90cc6a6a44 100644 --- a/lib/core/services/auth-guard-sso-role.service.spec.ts +++ b/lib/core/services/auth-guard-sso-role.service.spec.ts @@ -21,12 +21,10 @@ import { setupTestBed } from '../testing/setupTestBed'; import { CoreTestingModule } from '../testing/core.testing.module'; import { AuthGuardSsoRoleService } from './auth-guard-sso-role.service'; import { JwtHelperService } from './jwt-helper.service'; -import { StorageService } from './storage.service'; describe('Auth Guard SSO role service', () => { let authGuard: AuthGuardSsoRoleService; - let storageService: StorageService; let jwtHelperService: JwtHelperService; let routerService: Router; @@ -36,14 +34,13 @@ describe('Auth Guard SSO role service', () => { beforeEach(() => { localStorage.clear(); - storageService = TestBed.get(StorageService); authGuard = TestBed.get(AuthGuardSsoRoleService); jwtHelperService = TestBed.get(JwtHelperService); routerService = TestBed.get(Router); }); it('Should canActivate be true if the Role is present int the JWT token', async(() => { - spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] } }); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); @@ -53,7 +50,7 @@ describe('Auth Guard SSO role service', () => { })); it('Should canActivate be false if the Role is not present int the JWT token', async(() => { - spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role3'] } }); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); @@ -63,7 +60,7 @@ describe('Auth Guard SSO role service', () => { })); it('Should not redirect if canActivate is', async(() => { - spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] } }); spyOn(routerService, 'navigate').and.stub(); @@ -75,7 +72,7 @@ describe('Auth Guard SSO role service', () => { })); it('Should canActivate return false if the data Role to check is empty', async(() => { - spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1', 'role3'] } }); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); @@ -84,7 +81,7 @@ describe('Auth Guard SSO role service', () => { })); it('Should canActivate return false if the realm_access is not present', async(() => { - spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue({}); const router: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); @@ -93,7 +90,7 @@ describe('Auth Guard SSO role service', () => { })); it('Should redirect to the redirectURL if canActivate is false and redirectUrl is in data', async(() => { - spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue({}); spyOn(routerService, 'navigate').and.stub(); @@ -105,7 +102,7 @@ describe('Auth Guard SSO role service', () => { })); it('Should not redirect if canActivate is false and redirectUrl is not in data', async(() => { - spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue({}); spyOn(routerService, 'navigate').and.stub(); @@ -140,7 +137,7 @@ describe('Auth Guard SSO role service', () => { it('Should canActivate be true if both Real Role and Client Role are present int the JWT token', () => { const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); - spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] }, @@ -155,7 +152,7 @@ describe('Auth Guard SSO role service', () => { it('Should canActivate be false if the Client Role is not present int the JWT token with the correct role', () => { const route: ActivatedRouteSnapshot = new ActivatedRouteSnapshot(); - spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue({ 'realm_access': { roles: ['role1'] }, @@ -171,7 +168,7 @@ describe('Auth Guard SSO role service', () => { describe('ClientRole ', () => { it('Should be true if the resource_access contains the single role', () => { - spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue( { @@ -183,7 +180,7 @@ describe('Auth Guard SSO role service', () => { }); it('Should be true if the resource_access contains at least one of the roles', () => { - spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue( { @@ -195,7 +192,7 @@ describe('Auth Guard SSO role service', () => { }); it('Should be false if the resource_access does not contain the role', () => { - spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue( { 'resource_access': { fakeapp: { roles: ['role3'] } } @@ -205,7 +202,7 @@ describe('Auth Guard SSO role service', () => { }); it('Should be false if the resource_access does not contain the client role related to the app', () => { - spyOn(storageService, 'getItem').and.returnValue('my-access_token'); + spyOn(localStorage, 'getItem').and.returnValue('my-access_token'); spyOn(jwtHelperService, 'decodeToken').and.returnValue( { 'resource_access': { anotherfakeapp: { roles: ['role1'] } } diff --git a/lib/core/services/auth-guard-sso-role.service.ts b/lib/core/services/auth-guard-sso-role.service.ts index 06b94792cf..8c64d0ce34 100644 --- a/lib/core/services/auth-guard-sso-role.service.ts +++ b/lib/core/services/auth-guard-sso-role.service.ts @@ -56,19 +56,19 @@ export class AuthGuardSsoRoleService implements CanActivate { } getRealmRoles(): string[] { - const access = this.getValueFromToken('realm_access'); + const access = this.jwtHelperService.getValueFromLocalAccessToken('realm_access'); const roles = access ? access['roles'] : []; return roles; } getClientRoles(client: string): string[] { - const clientRole = this.getValueFromToken('resource_access')[client]; + const clientRole = this.jwtHelperService.getValueFromLocalAccessToken('resource_access')[client]; const roles = clientRole ? clientRole['roles'] : []; return roles; } getAccessToken(): string { - return this.storageService.getItem('access_token'); + return this.storageService.getItem(JwtHelperService.USER_ACCESS_TOKEN); } hasRealmRole(role: string): boolean { @@ -104,14 +104,4 @@ export class AuthGuardSsoRoleService implements CanActivate { } return hasRole; } - - getValueFromToken(key: string): T { - let value; - const accessToken = this.getAccessToken(); - if (accessToken) { - const tokenPayload = this.jwtHelperService.decodeToken(accessToken); - value = tokenPayload[key]; - } - return value; - } } diff --git a/lib/core/services/auth-guard.service.ts b/lib/core/services/auth-guard.service.ts index b29fc85971..621750fc25 100644 --- a/lib/core/services/auth-guard.service.ts +++ b/lib/core/services/auth-guard.service.ts @@ -21,6 +21,7 @@ import { AuthenticationService } from './authentication.service'; import { Observable } from 'rxjs'; import { AppConfigService } from '../app-config/app-config.service'; import { AuthGuardBase } from './auth-guard-base'; +import { JwtHelperService } from './jwt-helper.service'; @Injectable({ providedIn: 'root' @@ -29,7 +30,8 @@ export class AuthGuard extends AuthGuardBase { ticketChangeBind: any; - constructor(authenticationService: AuthenticationService, + constructor(private jwtHelperService: JwtHelperService, + authenticationService: AuthenticationService, router: Router, appConfigService: AppConfigService) { super(authenticationService, router, appConfigService); @@ -47,7 +49,9 @@ export class AuthGuard extends AuthGuardBase { this.ticketChangeRedirect(event, 'BPM'); } - if (event.key === 'id_token' && event.newValue !== event.oldValue) { + if (event.key === JwtHelperService.USER_ACCESS_TOKEN && + this.jwtHelperService.getValueFromToken(event.newValue, JwtHelperService.USER_PREFERRED_USERNAME) !== + this.jwtHelperService.getValueFromToken(event.oldValue, JwtHelperService.USER_PREFERRED_USERNAME)) { this.ticketChangeRedirect(event, 'ALL'); } } diff --git a/lib/core/services/authentication.service.ts b/lib/core/services/authentication.service.ts index 03ae5a885e..162fc2cfea 100644 --- a/lib/core/services/authentication.service.ts +++ b/lib/core/services/authentication.service.ts @@ -25,6 +25,7 @@ import { AppConfigService, AppConfigValues } from '../app-config/app-config.serv import { UserRepresentation } from '@alfresco/js-api'; import { map, catchError, tap } from 'rxjs/operators'; import { HttpHeaders } from '@angular/common/http'; +import { JwtHelperService } from './jwt-helper.service'; const REMEMBER_ME_COOKIE_KEY = 'ALFRESCO_REMEMBER_ME'; const REMEMBER_ME_UNTIL = 1000 * 60 * 60 * 24 * 30; @@ -290,7 +291,7 @@ export class AuthenticationService { * @returns Auth token string */ getToken(): string { - return localStorage.getItem('access_token'); + return localStorage.getItem(JwtHelperService.USER_ACCESS_TOKEN); } /** diff --git a/lib/core/services/jwt-helper.service.ts b/lib/core/services/jwt-helper.service.ts index 6fe6bece91..275e153a15 100644 --- a/lib/core/services/jwt-helper.service.ts +++ b/lib/core/services/jwt-helper.service.ts @@ -22,7 +22,15 @@ import { Injectable } from '@angular/core'; }) export class JwtHelperService { - constructor() {} + static USER_NAME = 'name'; + static FAMILY_NAME = 'family_name'; + static GIVEN_NAME = 'given_name'; + static USER_EMAIL = 'email'; + static USER_ACCESS_TOKEN = 'access_token'; + static USER_PREFERRED_USERNAME = 'preferred_username'; + + constructor() { + } /** * Decodes a JSON web token into a JS object. @@ -64,4 +72,29 @@ export class JwtHelperService { } return decodeURIComponent(escape(window.atob(output))); } + + /** + * Gets a named value from the user access token. + * @param key Key name of the field to retrieve + * @returns Value from the token + */ + getValueFromLocalAccessToken(key: string): T { + const accessToken = localStorage.getItem(JwtHelperService.USER_ACCESS_TOKEN); + return this.getValueFromToken(accessToken, key); + } + + /** + * Gets a named value from the user access token. + * @param key accessToken + * @param key Key name of the field to retrieve + * @returns Value from the token + */ + getValueFromToken(accessToken: string, key: string): T { + let value; + if (accessToken) { + const tokenPayload = this.decodeToken(accessToken); + value = tokenPayload[key]; + } + return value; + } } diff --git a/lib/core/userinfo/services/identity-user.service.ts b/lib/core/userinfo/services/identity-user.service.ts index 21b02437db..5f0f6a31b0 100644 --- a/lib/core/userinfo/services/identity-user.service.ts +++ b/lib/core/userinfo/services/identity-user.service.ts @@ -30,16 +30,9 @@ import { IdentityRoleModel } from '../models/identity-role.model'; }) export class IdentityUserService { - static USER_NAME = 'name'; - static FAMILY_NAME = 'family_name'; - static GIVEN_NAME = 'given_name'; - static USER_EMAIL = 'email'; - static USER_ACCESS_TOKEN = 'access_token'; - static USER_PREFERRED_USERNAME = 'preferred_username'; - constructor( - private helper: JwtHelperService, - private apiService: AlfrescoApiService, + private jwtHelperService: JwtHelperService, + private alfrescoApiService: AlfrescoApiService, private appConfigService: AppConfigService) { } /** @@ -47,29 +40,14 @@ export class IdentityUserService { * @returns The user's details */ getCurrentUserInfo(): IdentityUserModel { - const familyName = this.getValueFromToken(IdentityUserService.FAMILY_NAME); - const givenName = this.getValueFromToken(IdentityUserService.GIVEN_NAME); - const email = this.getValueFromToken(IdentityUserService.USER_EMAIL); - const username = this.getValueFromToken(IdentityUserService.USER_PREFERRED_USERNAME); + const familyName = this.jwtHelperService.getValueFromLocalAccessToken(JwtHelperService.FAMILY_NAME); + const givenName = this.jwtHelperService.getValueFromLocalAccessToken(JwtHelperService.GIVEN_NAME); + const email = this.jwtHelperService.getValueFromLocalAccessToken(JwtHelperService.USER_EMAIL); + const username = this.jwtHelperService.getValueFromLocalAccessToken(JwtHelperService.USER_PREFERRED_USERNAME); const user = { firstName: givenName, lastName: familyName, email: email, username: username }; return new IdentityUserModel(user); } - /** - * Gets a named value from the user access token. - * @param key Key name of the field to retrieve - * @returns Value from the token - */ - getValueFromToken(key: string): T { - let value; - const token = localStorage.getItem(IdentityUserService.USER_ACCESS_TOKEN); - if (token) { - const tokenPayload = this.helper.decodeToken(token); - value = tokenPayload[key]; - } - return value; - } - /** * Find users based on search input. * @param search Search query string @@ -83,7 +61,7 @@ export class IdentityUserService { const httpMethod = 'GET', pathParams = {}, queryParams = { search: search }, bodyParam = {}, headerParams = {}, formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; - return (from(this.apiService.getInstance().oauth2Auth.callCustomApi( + return (from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi( url, httpMethod, pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts, Object, null, null) @@ -103,7 +81,7 @@ export class IdentityUserService { const httpMethod = 'GET', pathParams = {}, queryParams = { username: username }, bodyParam = {}, headerParams = {}, formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; - return (from(this.apiService.getInstance().oauth2Auth.callCustomApi( + return (from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi( url, httpMethod, pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts, Object, null, null) @@ -123,7 +101,7 @@ export class IdentityUserService { const httpMethod = 'GET', pathParams = {}, queryParams = { email: email }, bodyParam = {}, headerParams = {}, formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; - return (from(this.apiService.getInstance().oauth2Auth.callCustomApi( + return (from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi( url, httpMethod, pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts, Object, null, null) @@ -143,7 +121,7 @@ export class IdentityUserService { const httpMethod = 'GET', pathParams = {}, queryParams = {}, bodyParam = {}, headerParams = {}, formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; - return (from(this.apiService.getInstance().oauth2Auth.callCustomApi( + return (from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi( url, httpMethod, pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts, Object, null, null) @@ -161,7 +139,7 @@ export class IdentityUserService { const httpMethod = 'GET', pathParams = {}, queryParams = {}, bodyParam = {}, headerParams = {}, formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; - return from(this.apiService.getInstance().oauth2Auth.callCustomApi( + return from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi( url, httpMethod, pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts, Object, null, null) @@ -222,7 +200,7 @@ export class IdentityUserService { const url = this.buildGetClientsUrl(); const httpMethod = 'GET', pathParams = {}, queryParams = { clientId: applicationName }, bodyParam = {}, headerParams = {}, formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; - return from(this.apiService.getInstance() + return from(this.alfrescoApiService.getInstance() .oauth2Auth.callCustomApi(url, httpMethod, pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts, Object, null, null) @@ -272,7 +250,7 @@ export class IdentityUserService { const httpMethod = 'GET', pathParams = {}, queryParams = {}, bodyParam = {}, headerParams = {}, formParams = {}, authNames = [], contentTypes = ['application/json'], accepts = ['application/json']; - return from(this.apiService.getInstance().oauth2Auth.callCustomApi( + return from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi( url, httpMethod, pathParams, queryParams, headerParams, formParams, bodyParam, authNames, contentTypes, accepts, null, null) @@ -293,7 +271,7 @@ export class IdentityUserService { const httpMethod = 'GET', pathParams = {}, queryParams = {}, bodyParam = {}, headerParams = {}, formParams = {}, contentTypes = ['application/json'], accepts = ['application/json']; - return from(this.apiService.getInstance().oauth2Auth.callCustomApi( + return from(this.alfrescoApiService.getInstance().oauth2Auth.callCustomApi( url, httpMethod, pathParams, queryParams, headerParams, formParams, bodyParam, contentTypes, accepts, Object, null, null) diff --git a/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts b/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts index 2aa79df927..0f94394d60 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/services/task-filter-cloud.service.ts @@ -19,13 +19,14 @@ import { StorageService, JwtHelperService } from '@alfresco/adf-core'; import { Injectable } from '@angular/core'; import { Observable, BehaviorSubject } from 'rxjs'; import { TaskFilterCloudModel } from '../models/filter-cloud.model'; + @Injectable() export class TaskFilterCloudService { private filtersSubject: BehaviorSubject; filters$: Observable; - constructor(private storage: StorageService, private jwtService: JwtHelperService) { + constructor(private storage: StorageService, private jwtHelperService: JwtHelperService) { this.filtersSubject = new BehaviorSubject([]); this.filters$ = this.filtersSubject.asObservable(); } @@ -135,22 +136,7 @@ export class TaskFilterCloudService { * @returns Username string */ getUsername(): string { - return this.getValueFromToken('preferred_username'); - } - - /** - * Gets a named value from the access token. - * @param key Key name of the value - * @returns The value data - */ - getValueFromToken(key: string): T { - let value; - const token = localStorage.getItem('access_token'); - if (token) { - const tokenPayload = this.jwtService.decodeToken(token); - value = tokenPayload[key]; - } - return value; + return this.jwtHelperService.getValueFromLocalAccessToken(JwtHelperService.USER_PREFERRED_USERNAME); } /** diff --git a/package-lock.json b/package-lock.json index 12ee967720..ff7a3fca27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6504,7 +6504,8 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "fsevents": { "version": "1.2.7", @@ -7202,6 +7203,7 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -8240,6 +8242,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -8348,7 +8351,8 @@ "interpret": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", - "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==" + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "dev": true }, "invariant": { "version": "2.2.4", @@ -10851,6 +10855,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -11986,6 +11991,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } @@ -12466,7 +12472,8 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-is-inside": { "version": "1.0.2", @@ -12483,7 +12490,8 @@ "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true }, "path-to-regexp": { "version": "0.1.7", @@ -13742,6 +13750,7 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, "requires": { "resolve": "^1.1.6" } @@ -14060,6 +14069,7 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "dev": true, "requires": { "path-parse": "^1.0.6" } @@ -14891,6 +14901,7 @@ "version": "0.8.3", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "dev": true, "requires": { "glob": "^7.0.0", "interpret": "^1.0.0", @@ -18593,7 +18604,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "write": { "version": "1.0.3", diff --git a/scripts/travis/update/update-childre.sh b/scripts/travis/update/update-children.sh similarity index 100% rename from scripts/travis/update/update-childre.sh rename to scripts/travis/update/update-children.sh