Browse Source

Guards fixed

pull/271/head
Sebastian Stehle 8 years ago
parent
commit
64d60a2be9
  1. 22
      src/Squidex/app/features/administration/guards/user-must-exist.guard.spec.ts
  2. 52
      src/Squidex/app/shared/guards/app-must-exist.guard.spec.ts
  3. 10
      src/Squidex/app/shared/guards/app-must-exist.guard.ts
  4. 38
      src/Squidex/app/shared/guards/load-apps.guard.spec.ts
  5. 4
      src/Squidex/app/shared/guards/load-apps.guard.ts
  6. 44
      src/Squidex/app/shared/guards/must-be-authenticated.guard.spec.ts
  7. 4
      src/Squidex/app/shared/guards/must-be-authenticated.guard.ts
  8. 46
      src/Squidex/app/shared/guards/must-be-not-authenticated.guard.spec.ts
  9. 4
      src/Squidex/app/shared/guards/must-be-not-authenticated.guard.ts
  10. 90
      src/Squidex/app/shared/guards/resolve-app-languages.guard.spec.ts
  11. 12
      src/Squidex/app/shared/guards/resolve-app-languages.guard.ts
  12. 105
      src/Squidex/app/shared/guards/resolve-content.guard.spec.ts
  13. 16
      src/Squidex/app/shared/guards/resolve-content.guard.ts
  14. 100
      src/Squidex/app/shared/guards/resolve-published-schema.guard.spec.ts
  15. 26
      src/Squidex/app/shared/guards/resolve-published-schema.guard.ts
  16. 83
      src/Squidex/app/shared/guards/resolve-schema.guard.spec.ts
  17. 17
      src/Squidex/app/shared/guards/resolve-schema.guard.ts
  18. 14
      src/Squidex/app/shared/guards/router-mockup.ts
  19. 13
      src/Squidex/app/shared/guards/unset-app.guard.spec.ts
  20. 4
      src/Squidex/app/shared/guards/unset-app.guard.ts
  21. 28
      src/Squidex/app/shared/interceptors/auth.interceptor.spec.ts
  22. 4
      src/Squidex/app/shared/services/users-provider.service.spec.ts
  23. 2
      src/Squidex/app/shared/state/apps.state.spec.ts

22
src/Squidex/app/features/administration/guards/user-must-exist.guard.spec.ts

@ -14,6 +14,12 @@ import { UsersState } from './../state/users.state';
import { UserMustExistGuard } from './user-must-exist.guard';
describe('UserMustExistGuard', () => {
const route: any = {
params: {
userId: '123'
}
};
let usersState: IMock<UsersState>;
let router: IMock<Router>;
let userGuard: UserMustExistGuard;
@ -30,14 +36,6 @@ describe('UserMustExistGuard', () => {
let result: boolean;
const route: any = {
snapshot: {
params: {
userId: '123'
}
}
};
userGuard.canActivate(route).subscribe(x => {
result = x;
}).unsubscribe();
@ -53,14 +51,6 @@ describe('UserMustExistGuard', () => {
let result: boolean;
const route: any = {
snapshot: {
params: {
userId: '123'
}
}
};
userGuard.canActivate(route).subscribe(x => {
result = x;
}).unsubscribe();

52
src/Squidex/app/shared/guards/app-must-exist.guard.spec.ts

@ -5,54 +5,60 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { IMock, Mock } from 'typemoq';
import { Router } from '@angular/router';
import { IMock, Mock, Times } from 'typemoq';
import { Observable } from 'rxjs';
import { AppsState } from '@app/shared';
import { AppMustExistGuard } from './app-must-exist.guard';
import { RouterMockup } from './router-mockup';
describe('AppMustExistGuard', () => {
const route: any = {
params: {
appName: 'my-app'
}
};
let router: IMock<Router>;
let appsState: IMock<AppsState>;
let appGuard: AppMustExistGuard;
beforeEach(() => {
appsState = Mock.ofType(AppsState);
router = Mock.ofType<Router>();
appsState = Mock.ofType<AppsState>();
appGuard = new AppMustExistGuard(appsState.object, router.object);
});
it('should navigate to 404 page if app is not found', (done) => {
it('should navigate to 404 page if app is not found', () => {
appsState.setup(x => x.selectApp('my-app'))
.returns(() => Observable.of(null));
const router = new RouterMockup();
const route = <any> { params: { appName: 'my-app' } };
let result: boolean;
const guard = new AppMustExistGuard(appsState.object, <any>router);
appGuard.canActivate(route).subscribe(x => {
result = x;
});
guard.canActivate(route, <any>{})
.subscribe(result => {
expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']);
expect(result!).toBeFalsy();
done();
});
appsState.verify(x => x.selectApp('my-app'), Times.once());
});
it('should return true if app is found', (done) => {
it('should return true if app is found', () => {
appsState.setup(x => x.selectApp('my-app'))
.returns(() => Observable.of(<any>{}));
const router = new RouterMockup();
const route = <any> { params: { appName: 'my-app' } };
let result: boolean;
const guard = new AppMustExistGuard(appsState.object, <any>router);
appGuard.canActivate(route).subscribe(x => {
result = x;
});
guard.canActivate(route, <any>{})
.subscribe(result => {
expect(result).toBeTruthy();
expect(router.lastNavigation).toBeUndefined();
expect(result!).toBeTruthy();
done();
});
// router.verify(x => x.navigate(['/404']), Times.once());
});
});

10
src/Squidex/app/shared/guards/app-must-exist.guard.ts

@ -6,7 +6,7 @@
*/
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AppsState } from './../state/apps.state';
@ -14,21 +14,21 @@ import { AppsState } from './../state/apps.state';
@Injectable()
export class AppMustExistGuard implements CanActivate {
constructor(
private readonly appsStore: AppsState,
private readonly appsState: AppsState,
private readonly router: Router
) {
}
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
public canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
const appName = route.params['appName'];
const result =
this.appsStore.selectApp(appName)
this.appsState.selectApp(appName)
.do(dto => {
if (!dto) {
this.router.navigate(['/404']);
}
}).map(a => a !== null);
}).map(a => !!a);
return result;
}

38
src/Squidex/app/shared/guards/load-apps.guard.spec.ts

@ -0,0 +1,38 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { IMock, Mock, Times } from 'typemoq';
import { Observable } from 'rxjs';
import { AppsState } from '@app/shared';
import { LoadAppsGuard } from './load-apps.guard';
describe('LoadAppsGuard', () => {
let appsState: IMock<AppsState>;
let appGuard: LoadAppsGuard;
beforeEach(() => {
appsState = Mock.ofType<AppsState>();
appGuard = new LoadAppsGuard(appsState.object);
});
it('should load apps', () => {
appsState.setup(x => x.loadApps())
.returns(() => Observable.of(null));
let result = false;
appGuard.canActivate().subscribe(value => {
result = value;
});
expect(result).toBeTruthy();
appsState.verify(x => x.loadApps(), Times.once());
});
});

4
src/Squidex/app/shared/guards/load-apps.guard.ts

@ -6,7 +6,7 @@
*/
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
import { CanActivate } from '@angular/router';
import { Observable } from 'rxjs';
import { AppsState } from './../state/apps.state';
@ -18,7 +18,7 @@ export class LoadAppsGuard implements CanActivate {
) {
}
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
public canActivate(): Observable<boolean> {
return this.appsState.loadApps().map(a => true);
}
}

44
src/Squidex/app/shared/guards/must-be-authenticated.guard.spec.ts

@ -5,50 +5,52 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { IMock, Mock } from 'typemoq';
import { Router } from '@angular/router';
import { IMock, Mock, Times } from 'typemoq';
import { Observable } from 'rxjs';
import { AuthService } from '@app/shared';
import { MustBeAuthenticatedGuard } from './must-be-authenticated.guard';
import { RouterMockup } from './router-mockup';
describe('MustBeAuthenticatedGuard', () => {
let router: IMock<Router>;
let authService: IMock<AuthService>;
let authGuard: MustBeAuthenticatedGuard;
beforeEach(() => {
authService = Mock.ofType(AuthService);
router = Mock.ofType<Router>();
authService = Mock.ofType<AuthService>();
authGuard = new MustBeAuthenticatedGuard(authService.object, router.object);
});
it('should navigate to default page if not authenticated', (done) => {
it('should navigate to default page if not authenticated', () => {
authService.setup(x => x.userChanges)
.returns(() => Observable.of(null));
const router = new RouterMockup();
const guard = new MustBeAuthenticatedGuard(authService.object, <any>router);
let result: boolean;
authGuard.canActivate().subscribe(x => {
result = x;
});
guard.canActivate(<any>{}, <any>{})
.subscribe(result => {
expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['']);
expect(result!).toBeFalsy();
done();
});
router.verify(x => x.navigate(['']), Times.once());
});
it('should return true if authenticated', (done) => {
it('should return true if authenticated', () => {
authService.setup(x => x.userChanges)
.returns(() => Observable.of(<any>{}));
const router = new RouterMockup();
const guard = new MustBeAuthenticatedGuard(authService.object, <any>router);
let result: boolean;
guard.canActivate(<any>{}, <any>{})
.subscribe(result => {
expect(result).toBeTruthy();
expect(router.lastNavigation).toBeUndefined();
authGuard.canActivate().subscribe(x => {
result = x;
});
done();
});
expect(result!).toBeTruthy();
});
});

4
src/Squidex/app/shared/guards/must-be-authenticated.guard.ts

@ -6,7 +6,7 @@
*/
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { CanActivate, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './../services/auth.service';
@ -19,7 +19,7 @@ export class MustBeAuthenticatedGuard implements CanActivate {
) {
}
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
public canActivate(): Observable<boolean> {
return this.authService.userChanges.take(1)
.do(user => {
if (!user) {

46
src/Squidex/app/shared/guards/must-be-not-authenticated.guard.spec.ts

@ -5,50 +5,52 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { IMock, Mock } from 'typemoq';
import { Router } from '@angular/router';
import { IMock, Mock, Times } from 'typemoq';
import { Observable } from 'rxjs';
import { AuthService } from '@app/shared';
import { MustBeNotAuthenticatedGuard } from './must-be-not-authenticated.guard';
import { RouterMockup } from './router-mockup';
describe('MustBeNotAuthenticatedGuard', () => {
describe('MustNotBeAuthenticatedGuard', () => {
let router: IMock<Router>;
let authService: IMock<AuthService>;
let authGuard: MustBeNotAuthenticatedGuard;
beforeEach(() => {
authService = Mock.ofType(AuthService);
router = Mock.ofType<Router>();
authService = Mock.ofType<AuthService>();
authGuard = new MustBeNotAuthenticatedGuard(authService.object, router.object);
});
it('should navigate to app page if authenticated', (done) => {
it('should navigate to app page if authenticated', () => {
authService.setup(x => x.userChanges)
.returns(() => Observable.of(<any>{}));
const router = new RouterMockup();
const guard = new MustBeNotAuthenticatedGuard(authService.object, <any>router);
let result: boolean;
authGuard.canActivate().subscribe(x => {
result = x;
});
guard.canActivate(<any>{}, <any>{})
.subscribe(result => {
expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['app']);
expect(result!).toBeFalsy();
done();
});
router.verify(x => x.navigate(['app']), Times.once());
});
it('should return true if not authenticated', (done) => {
it('should return true if not authenticated', () => {
authService.setup(x => x.userChanges)
.returns(() => Observable.of(null));
const router = new RouterMockup();
const guard = new MustBeNotAuthenticatedGuard(authService.object, <any>router);
let result: boolean;
guard.canActivate(<any>{}, <any>{})
.subscribe(result => {
expect(result).toBeTruthy();
expect(router.lastNavigation).toBeUndefined();
authGuard.canActivate().subscribe(x => {
result = x;
});
done();
});
expect(result!).toBeTruthy();
});
});

4
src/Squidex/app/shared/guards/must-be-not-authenticated.guard.ts

@ -6,7 +6,7 @@
*/
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { CanActivate, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './../services/auth.service';
@ -19,7 +19,7 @@ export class MustBeNotAuthenticatedGuard implements CanActivate {
) {
}
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
public canActivate(): Observable<boolean> {
return this.authService.userChanges.take(1)
.do(user => {
if (user) {

90
src/Squidex/app/shared/guards/resolve-app-languages.guard.spec.ts

@ -1,90 +0,0 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { IMock, Mock } from 'typemoq';
import { Observable } from 'rxjs';
import {
AppLanguagesDto,
AppLanguagesService,
Version
} from '@app/shared';
import { ResolveAppLanguagesGuard } from './resolve-app-languages.guard';
import { RouterMockup } from './router-mockup';
describe('ResolveAppLanguagesGuard', () => {
const route = {
params: { },
parent: {
params: {
appName: 'my-app'
}
}
};
let appLanguagesService: IMock<AppLanguagesService>;
beforeEach(() => {
appLanguagesService = Mock.ofType(AppLanguagesService);
});
it('should throw if route does not contain parameter', () => {
const guard = new ResolveAppLanguagesGuard(appLanguagesService.object, <any>new RouterMockup());
expect(() => guard.resolve(<any>{ params: {} }, <any>{})).toThrow('Route must contain app name.');
});
it('should navigate to 404 page if languages are not found', (done) => {
appLanguagesService.setup(x => x.getLanguages('my-app'))
.returns(() => Observable.of(null!));
const router = new RouterMockup();
const guard = new ResolveAppLanguagesGuard(appLanguagesService.object, <any>router);
guard.resolve(<any>route, <any>{})
.subscribe(result => {
expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']);
done();
});
});
it('should navigate to 404 page if languages loading fails', (done) => {
appLanguagesService.setup(x => x.getLanguages('my-app'))
.returns(() => Observable.throw(null!));
const router = new RouterMockup();
const guard = new ResolveAppLanguagesGuard(appLanguagesService.object, <any>router);
guard.resolve(<any>route, <any>{})
.subscribe(result => {
expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']);
done();
});
});
it('should return languages if loading succeeded', (done) => {
const languages = new AppLanguagesDto([], new Version('2'));
appLanguagesService.setup(x => x.getLanguages('my-app'))
.returns(() => Observable.of(languages));
const router = new RouterMockup();
const guard = new ResolveAppLanguagesGuard(appLanguagesService.object, <any>router);
guard.resolve(<any>route, <any>{})
.subscribe(result => {
expect(result).toBe(languages.languages);
done();
});
});
});

12
src/Squidex/app/shared/guards/resolve-app-languages.guard.ts

@ -6,7 +6,7 @@
*/
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { allParams } from '@app/framework';
@ -21,14 +21,8 @@ export class ResolveAppLanguagesGuard implements Resolve<AppLanguageDto[] | null
) {
}
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<AppLanguageDto[] | null> {
const params = allParams(route);
const appName = params['appName'];
if (!appName) {
throw 'Route must contain app name.';
}
public resolve(route: ActivatedRouteSnapshot): Observable<AppLanguageDto[] | null> {
const appName = allParams(route)['appName'];
const result =
this.appLanguagesService.getLanguages(appName).map(d => d.languages)

105
src/Squidex/app/shared/guards/resolve-content.guard.spec.ts

@ -1,105 +0,0 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { IMock, Mock } from 'typemoq';
import { Observable } from 'rxjs';
import { ContentsService } from '@app/shared';
import { ResolveContentGuard } from './resolve-content.guard';
import { RouterMockup } from './router-mockup';
describe('ResolveContentGuard', () => {
const route = {
params: {
appName: 'my-app'
},
parent: {
params: {
schemaName: 'my-schema'
},
parent: {
params: {
contentId: '123'
}
}
}
};
let appsStore: IMock<ContentsService>;
beforeEach(() => {
appsStore = Mock.ofType(ContentsService);
});
it('should throw if route does not contain app name', () => {
const guard = new ResolveContentGuard(appsStore.object, <any>new RouterMockup());
expect(() => guard.resolve(<any>{ params: {} }, <any>{})).toThrow('Route must contain app name.');
});
it('should throw if route does not contain schema name', () => {
const guard = new ResolveContentGuard(appsStore.object, <any>new RouterMockup());
expect(() => guard.resolve(<any>{ params: { appName: 'my-app' } }, <any>{})).toThrow('Route must contain schema name.');
});
it('should throw if route does not contain content id', () => {
const guard = new ResolveContentGuard(appsStore.object, <any>new RouterMockup());
expect(() => guard.resolve(<any>{ params: { appName: 'my-app', schemaName: 'my-schema' } }, <any>{})).toThrow('Route must contain content id.');
});
it('should navigate to 404 page if schema is not found', (done) => {
appsStore.setup(x => x.getContent('my-app', 'my-schema', '123'))
.returns(() => Observable.of(null!));
const router = new RouterMockup();
const guard = new ResolveContentGuard(appsStore.object, <any>router);
guard.resolve(<any>route, <any>{})
.subscribe(result => {
expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']);
done();
});
});
it('should navigate to 404 page if schema loading fails', (done) => {
appsStore.setup(x => x.getContent('my-app', 'my-schema', '123'))
.returns(() => Observable.throw(null!));
const router = new RouterMockup();
const guard = new ResolveContentGuard(appsStore.object, <any>router);
guard.resolve(<any>route, <any>{})
.subscribe(result => {
expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']);
done();
});
});
it('should return content if loading succeeded', (done) => {
const content: any = {};
appsStore.setup(x => x.getContent('my-app', 'my-schema', '123'))
.returns(() => Observable.of(content));
const router = new RouterMockup();
const guard = new ResolveContentGuard(appsStore.object, <any>router);
guard.resolve(<any>route, <any>{})
.subscribe(result => {
expect(result).toBe(content);
done();
});
});
});

16
src/Squidex/app/shared/guards/resolve-content.guard.ts

@ -25,22 +25,8 @@ export class ResolveContentGuard implements Resolve<ContentDto | null> {
const params = allParams(route);
const appName = params['appName'];
if (!appName) {
throw 'Route must contain app name.';
}
const schemaName = params['schemaName'];
if (!schemaName) {
throw 'Route must contain schema name.';
}
const contentId = params['contentId'];
if (!contentId) {
throw 'Route must contain content id.';
}
const schemaName = params['schemaName'];
const result =
this.contentsService.getContent(appName, schemaName, contentId)

100
src/Squidex/app/shared/guards/resolve-published-schema.guard.spec.ts

@ -5,16 +5,16 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { IMock, Mock } from 'typemoq';
import { Router } from '@angular/router';
import { IMock, Mock, Times } from 'typemoq';
import { Observable } from 'rxjs';
import { SchemasService } from '@app/shared';
import { SchemasService, SchemaDetailsDto } from '@app/shared';
import { ResolvePublishedSchemaGuard } from './resolve-published-schema.guard';
import { RouterMockup } from './router-mockup';
describe('ResolvePublishedSchemaGuard', () => {
const route = {
const route: any = {
params: {
appName: 'my-app'
},
@ -25,88 +25,78 @@ describe('ResolvePublishedSchemaGuard', () => {
}
};
let router: IMock<Router>;
let schemasService: IMock<SchemasService>;
let schemaGuard: ResolvePublishedSchemaGuard;
beforeEach(() => {
schemasService = Mock.ofType(SchemasService);
});
it('should throw if route does not contain app name', () => {
const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>new RouterMockup());
router = Mock.ofType<Router>();
expect(() => guard.resolve(<any>{ params: {} }, <any>{})).toThrow('Route must contain app name.');
schemasService = Mock.ofType<SchemasService>();
schemaGuard = new ResolvePublishedSchemaGuard(schemasService.object, router.object);
});
it('should throw if route does not contain schema name', () => {
const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>new RouterMockup());
expect(() => guard.resolve(<any>{ params: { appName: 'my-app' } }, <any>{})).toThrow('Route must contain schema name.');
});
it('should return schema if loading succeeded', () => {
const schema: any = { isPublished: true };
it('should navigate to 404 page if schema is not found', (done) => {
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.of(null!));
const router = new RouterMockup();
.returns(() => Observable.of(schema));
let result: SchemaDetailsDto;
const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>router);
schemaGuard.resolve(route).subscribe(x => {
result = x!;
});
guard.resolve(<any>route, <any>{})
.subscribe(result => {
expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']);
expect(result!).toBe(schema);
done();
});
schemasService.verify(x => x.getSchema('my-app', 'my-schema'), Times.once());
});
it('should navigate to 404 page if schema loading fails', (done) => {
it('should navigate to 404 page if schema is not found', () => {
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.throw(null));
const router = new RouterMockup();
.returns(() => Observable.of(null!));
let result: SchemaDetailsDto;
const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>router);
schemaGuard.resolve(route).subscribe(x => {
result = x!!;
});
guard.resolve(<any>route, <any>{})
.subscribe(result => {
expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']);
expect(result!).toBeNull();
done();
});
router.verify(x => x.navigate(['/404']), Times.once());
});
it('should navigate to 404 page if schema not published', (done) => {
it('should navigate to 404 page if schema is not published', () => {
const schema: any = { isPublished: false };
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.of(schema));
const router = new RouterMockup();
const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>router);
let result: SchemaDetailsDto;
guard.resolve(<any>route, <any>{})
.subscribe(result => {
expect(result).toBe(schema);
expect(router.lastNavigation).toEqual(['/404']);
schemaGuard.resolve(route).subscribe(x => {
result = x!;
});
done();
});
});
expect(result!).toBeNull();
it('should return schema if loading succeeded', (done) => {
const schema: any = { isPublished: true };
router.verify(x => x.navigate(['/404']), Times.once());
});
it('should navigate to 404 page if schema loading fails', () => {
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.of(schema));
const router = new RouterMockup();
.returns(() => Observable.throw({}));
let result: SchemaDetailsDto;
const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>router);
schemaGuard.resolve(route).subscribe(x => {
result = x!;
});
guard.resolve(<any>route, <any>{})
.subscribe(result => {
expect(result).toBe(schema);
expect(result!).toBeNull();
done();
});
router.verify(x => x.navigate(['/404']), Times.once());
});
});

26
src/Squidex/app/shared/guards/resolve-published-schema.guard.ts

@ -6,7 +6,7 @@
*/
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { allParams } from '@app/framework';
@ -14,39 +14,37 @@ import { allParams } from '@app/framework';
import { SchemaDetailsDto, SchemasService } from './../services/schemas.service';
@Injectable()
export class ResolvePublishedSchemaGuard implements Resolve<SchemaDetailsDto> {
export class ResolvePublishedSchemaGuard implements Resolve<SchemaDetailsDto | null> {
constructor(
private readonly schemasService: SchemasService,
private readonly router: Router
) {
}
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<SchemaDetailsDto> {
public resolve(route: ActivatedRouteSnapshot): Observable<SchemaDetailsDto | null> {
const params = allParams(route);
const appName = params['appName'];
if (!appName) {
throw 'Route must contain app name.';
}
const schemaName = params['schemaName'];
if (!schemaName) {
throw 'Route must contain schema name.';
}
const result =
this.schemasService.getSchema(appName, schemaName)
.map(dto => {
if (dto && !dto.isPublished) {
return null;
}
return dto;
})
.do(dto => {
if (!dto || !dto.isPublished) {
if (!dto) {
this.router.navigate(['/404']);
}
})
.catch(error => {
this.router.navigate(['/404']);
return Observable.of(error);
return Observable.of(null);
});
return result;

83
src/Squidex/app/shared/guards/resolve-schema.guard.spec.ts

@ -5,16 +5,16 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { IMock, Mock } from 'typemoq';
import { Router } from '@angular/router';
import { IMock, Mock, Times } from 'typemoq';
import { Observable } from 'rxjs';
import { SchemasService } from '@app/shared';
import { SchemasService, SchemaDetailsDto } from '@app/shared';
import { ResolveSchemaGuard } from './resolve-schema.guard';
import { RouterMockup } from './router-mockup';
describe('ResolveSchemaGuard', () => {
const route = {
const route: any = {
params: {
appName: 'my-app'
},
@ -25,70 +25,61 @@ describe('ResolveSchemaGuard', () => {
}
};
let router: IMock<Router>;
let schemasService: IMock<SchemasService>;
let schemaGuard: ResolveSchemaGuard;
beforeEach(() => {
schemasService = Mock.ofType(SchemasService);
});
it('should throw if route does not contain app name', () => {
const guard = new ResolveSchemaGuard(schemasService.object, <any>new RouterMockup());
router = Mock.ofType<Router>();
expect(() => guard.resolve(<any>{ params: {} }, <any>{})).toThrow('Route must contain app name.');
schemasService = Mock.ofType<SchemasService>();
schemaGuard = new ResolveSchemaGuard(schemasService.object, router.object);
});
it('should throw if route does not contain schema name', () => {
const guard = new ResolveSchemaGuard(schemasService.object, <any>new RouterMockup());
expect(() => guard.resolve(<any>{ params: { appName: 'my-app' } }, <any>{})).toThrow('Route must contain schema name.');
});
it('should return schema if loading succeeded', () => {
const schema: any = {};
it('should navigate to 404 page if schema is not found', (done) => {
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.of(null!));
const router = new RouterMockup();
.returns(() => Observable.of(schema));
const guard = new ResolveSchemaGuard(schemasService.object, <any>router);
let result: SchemaDetailsDto;
guard.resolve(<any>route, <any>{})
.subscribe(result => {
expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']);
schemaGuard.resolve(route).subscribe(x => {
result = x!;
});
done();
});
expect(result!).toBe(schema);
schemasService.verify(x => x.getSchema('my-app', 'my-schema'), Times.once());
});
it('should navigate to 404 page if schema loading fails', (done) => {
it('should navigate to 404 page if schema is not found', () => {
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.throw(null!));
const router = new RouterMockup();
.returns(() => Observable.of(null!));
const guard = new ResolveSchemaGuard(schemasService.object, <any>router);
let result: SchemaDetailsDto;
guard.resolve(<any>route, <any>{})
.subscribe(result => {
expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']);
schemaGuard.resolve(route).subscribe(x => {
result = x!;
});
done();
});
});
expect(result!).toBeNull();
it('should return schema if loading succeeded', (done) => {
const schema: any = {};
router.verify(x => x.navigate(['/404']), Times.once());
});
it('should navigate to 404 page if schema loading fails', () => {
schemasService.setup(x => x.getSchema('my-app', 'my-schema'))
.returns(() => Observable.of(schema));
const router = new RouterMockup();
.returns(() => Observable.throw({}));
let result: SchemaDetailsDto;
const guard = new ResolveSchemaGuard(schemasService.object, <any>router);
schemaGuard.resolve(route).subscribe(x => {
result = x!;
});
guard.resolve(<any>route, <any>{})
.subscribe(result => {
expect(result).toBe(schema);
expect(result!).toBeNull();
done();
});
router.verify(x => x.navigate(['/404']), Times.once());
});
});

17
src/Squidex/app/shared/guards/resolve-schema.guard.ts

@ -6,7 +6,7 @@
*/
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { allParams } from '@app/framework';
@ -14,28 +14,19 @@ import { allParams } from '@app/framework';
import { SchemaDetailsDto, SchemasService } from './../services/schemas.service';
@Injectable()
export class ResolveSchemaGuard implements Resolve<SchemaDetailsDto> {
export class ResolveSchemaGuard implements Resolve<SchemaDetailsDto | null> {
constructor(
private readonly schemasService: SchemasService,
private readonly router: Router
) {
}
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<SchemaDetailsDto> {
public resolve(route: ActivatedRouteSnapshot): Observable<SchemaDetailsDto | null> {
const params = allParams(route);
const appName = params['appName'];
if (!appName) {
throw 'Route must contain app name.';
}
const schemaName = params['schemaName'];
if (!schemaName) {
throw 'Route must contain schema name.';
}
const result =
this.schemasService.getSchema(appName, schemaName)
.do(dto => {
@ -46,7 +37,7 @@ export class ResolveSchemaGuard implements Resolve<SchemaDetailsDto> {
.catch(error => {
this.router.navigate(['/404']);
return Observable.of(error);
return Observable.of(null);
});
return result;

14
src/Squidex/app/shared/guards/router-mockup.ts

@ -1,14 +0,0 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
export class RouterMockup {
public lastNavigation: any[];
public navigate(target: any[]) {
this.lastNavigation = target;
}
}

13
src/Squidex/app/shared/guards/unset-app.guard.spec.ts

@ -14,23 +14,22 @@ import { UnsetAppGuard } from './unset-app.guard';
describe('UnsetAppGuard', () => {
let appsState: IMock<AppsState>;
let appGuard: UnsetAppGuard;
beforeEach(() => {
appsState = Mock.ofType(AppsState);
appsState = Mock.ofType<AppsState>();
appGuard = new UnsetAppGuard(appsState.object);
});
it('should unselect app', () => {
appsState.setup(x => x.selectApp(null))
.returns(() => Observable.of(null));
const guard = new UnsetAppGuard(appsState.object);
let result = false;
guard.canActivate(<any>{}, <any>{})
.subscribe(value => {
result = value;
});
appGuard.canActivate().subscribe(value => {
result = value;
});
expect(result).toBeTruthy();

4
src/Squidex/app/shared/guards/unset-app.guard.ts

@ -6,7 +6,7 @@
*/
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
import { CanActivate } from '@angular/router';
import { Observable } from 'rxjs';
import { AppsState } from './../state/apps.state';
@ -18,7 +18,7 @@ export class UnsetAppGuard implements CanActivate {
) {
}
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
public canActivate(): Observable<boolean> {
return this.appsState.selectApp(null).map(a => a === null);
}
}

28
src/Squidex/app/shared/interceptors/auth.interceptor.spec.ts

@ -46,7 +46,7 @@ describe('AuthInterceptor', () => {
it('should append headers to request',
inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
authService.setup(x => x.userChanges).returns(() => { return Observable.of(<any>{ authToken: 'letmein' }); });
authService.setup(x => x.userChanges).returns(() => Observable.of(<any>{ authToken: 'letmein' }));
http.get('http://service/p/apps').subscribe();
@ -61,7 +61,7 @@ describe('AuthInterceptor', () => {
it('should not append headers for no auth headers',
inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
authService.setup(x => x.userChanges).returns(() => { return Observable.of(<any>{ authToken: 'letmein' }); });
authService.setup(x => x.userChanges).returns(() => Observable.of(<any>{ authToken: 'letmein' }));
http.get('http://service/p/apps', { headers: new HttpHeaders().set('NoAuth', '') }).subscribe();
@ -76,7 +76,7 @@ describe('AuthInterceptor', () => {
it('should not append headers for other requests',
inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
authService.setup(x => x.userChanges).returns(() => { return Observable.of(<any>{ authToken: 'letmein' }); });
authService.setup(x => x.userChanges).returns(() => Observable.of(<any>{ authToken: 'letmein' }));
http.get('http://cloud/p/apps').subscribe();
@ -91,14 +91,10 @@ describe('AuthInterceptor', () => {
it(`should logout for 401 status code`,
inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
authService.setup(x => x.userChanges).returns(() => { return Observable.of(<any>{ authToken: 'letmein' }); });
authService.setup(x => x.loginSilent()).returns(() => { return Observable.of(<any>{ authToken: 'letmereallyin' }); });
authService.setup(x => x.userChanges).returns(() => Observable.of(<any>{ authToken: 'letmein' }));
authService.setup(x => x.loginSilent()).returns(() => Observable.of(<any>{ authToken: 'letmereallyin' }));
http.get('http://service/p/apps').subscribe(
_ => { /* NOOP */ },
_ => { /* NOOP */ });
// const req = httpMock.expectOne('http://service/p/apps');
http.get('http://service/p/apps').onErrorResumeNext().subscribe();
httpMock.expectOne('http://service/p/apps').error(<any>{}, { status: 401 });
httpMock.expectOne('http://service/p/apps').error(<any>{}, { status: 401 });
@ -110,11 +106,9 @@ describe('AuthInterceptor', () => {
it(`should logout for ${statusCode} status code`,
inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
authService.setup(x => x.userChanges).returns(() => { return Observable.of(<any>{ authToken: 'letmein' }); });
authService.setup(x => x.userChanges).returns(() => Observable.of(<any>{ authToken: 'letmein' }));
http.get('http://service/p/apps').subscribe(
_ => { /* NOOP */ },
_ => { /* NOOP */ });
http.get('http://service/p/apps').onErrorResumeNext().subscribe();
const req = httpMock.expectOne('http://service/p/apps');
@ -128,11 +122,9 @@ describe('AuthInterceptor', () => {
it(`should not logout for ${statusCode} status code`,
inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
authService.setup(x => x.userChanges).returns(() => { return Observable.of(<any>{ authToken: 'letmein' }); });
authService.setup(x => x.userChanges).returns(() => Observable.of(<any>{ authToken: 'letmein' }));
http.get('http://service/p/apps').subscribe(
_ => { /* NOOP */ },
_ => { /* NOOP */ });
http.get('http://service/p/apps').onErrorResumeNext().subscribe();
const req = httpMock.expectOne('http://service/p/apps');

4
src/Squidex/app/shared/services/users-provider.service.spec.ts

@ -22,8 +22,8 @@ describe('UsersProviderService', () => {
let usersProviderService: UsersProviderService;
beforeEach(() => {
authService = Mock.ofType(AuthService);
usersService = Mock.ofType(UsersService);
authService = Mock.ofType<AuthService>();
usersService = Mock.ofType<UsersService>();
usersProviderService = new UsersProviderService(usersService.object, authService.object);
});

2
src/Squidex/app/shared/state/apps.state.spec.ts

@ -29,7 +29,7 @@ describe('AppsState', () => {
let appsState: AppsState;
beforeEach(() => {
appsService = Mock.ofType(AppsService);
appsService = Mock.ofType<AppsService>();
appsService.setup(x => x.getApps())
.returns(() => Observable.of(oldApps))

Loading…
Cancel
Save