Browse Source

RX Everything!

pull/65/merge
Sebastian Stehle 9 years ago
parent
commit
d87093ee90
  1. 2
      src/Squidex.Domain.Users/UserExtensions.cs
  2. 4
      src/Squidex.Domain.Users/UserManagerExtensions.cs
  3. 2
      src/Squidex/Controllers/UI/Extensions.cs
  4. 4
      src/Squidex/app/features/content/pages/content/content-page.component.ts
  5. 9
      src/Squidex/app/features/dashboard/pages/dashboard-page.component.ts
  6. 6
      src/Squidex/app/framework/angular/can-deactivate.guard.spec.ts
  7. 2
      src/Squidex/app/framework/angular/can-deactivate.guard.ts
  8. 13
      src/Squidex/app/shared/guards/app-must-exist.guard.spec.ts
  9. 14
      src/Squidex/app/shared/guards/app-must-exist.guard.ts
  10. 13
      src/Squidex/app/shared/guards/must-be-authenticated.guard.spec.ts
  11. 16
      src/Squidex/app/shared/guards/must-be-authenticated.guard.ts
  12. 13
      src/Squidex/app/shared/guards/must-be-not-authenticated.guard.spec.ts
  13. 16
      src/Squidex/app/shared/guards/must-be-not-authenticated.guard.ts
  14. 6
      src/Squidex/app/shared/guards/resolve-app-languages.guard.spec.ts
  15. 16
      src/Squidex/app/shared/guards/resolve-app-languages.guard.ts
  16. 6
      src/Squidex/app/shared/guards/resolve-content.guard.spec.ts
  17. 16
      src/Squidex/app/shared/guards/resolve-content.guard.ts
  18. 8
      src/Squidex/app/shared/guards/resolve-published-schema.guard.spec.ts
  19. 18
      src/Squidex/app/shared/guards/resolve-published-schema.guard.ts
  20. 6
      src/Squidex/app/shared/guards/resolve-schema.guard.spec.ts
  21. 16
      src/Squidex/app/shared/guards/resolve-schema.guard.ts
  22. 6
      src/Squidex/app/shared/guards/resolve-user.guard.spec.ts
  23. 16
      src/Squidex/app/shared/guards/resolve-user.guard.ts
  24. 16
      src/Squidex/app/shared/interceptors/auth.interceptor.spec.ts
  25. 38
      src/Squidex/app/shared/interceptors/auth.interceptor.ts
  26. 49
      src/Squidex/app/shared/services/apps-store.service.spec.ts
  27. 18
      src/Squidex/app/shared/services/apps-store.service.ts
  28. 82
      src/Squidex/app/shared/services/auth.service.ts
  29. 14
      src/Squidex/app/shell/pages/internal/profile-menu.component.ts

2
src/Squidex.Domain.Users/UserExtensions.cs

@ -18,7 +18,7 @@ namespace Squidex.Domain.Users
{ {
public static class UserExtensions public static class UserExtensions
{ {
public static void UpdateDisplayName(this IUser user, string displayName) public static void SetDisplayName(this IUser user, string displayName)
{ {
user.SetClaim(SquidexClaimTypes.SquidexDisplayName, displayName); user.SetClaim(SquidexClaimTypes.SquidexDisplayName, displayName);
} }

4
src/Squidex.Domain.Users/UserManagerExtensions.cs

@ -56,7 +56,7 @@ namespace Squidex.Domain.Users
try try
{ {
user.UpdateDisplayName(displayName); user.SetDisplayName(displayName);
user.SetPictureUrlFromGravatar(email); user.SetPictureUrlFromGravatar(email);
await DoChecked(() => userManager.CreateAsync(user), "Cannot create user."); await DoChecked(() => userManager.CreateAsync(user), "Cannot create user.");
@ -92,7 +92,7 @@ namespace Squidex.Domain.Users
if (!string.IsNullOrWhiteSpace(displayName)) if (!string.IsNullOrWhiteSpace(displayName))
{ {
user.UpdateDisplayName(displayName); user.SetDisplayName(displayName);
} }
await DoChecked(() => userManager.UpdateAsync(user), "Cannot update user."); await DoChecked(() => userManager.UpdateAsync(user), "Cannot update user.");

2
src/Squidex/Controllers/UI/Extensions.cs

@ -19,7 +19,7 @@ namespace Squidex.Controllers.UI
public static Task<IdentityResult> UpdateAsync(this UserManager<IUser> userManager, IUser user, string email, string displayName) public static Task<IdentityResult> UpdateAsync(this UserManager<IUser> userManager, IUser user, string email, string displayName)
{ {
user.UpdateEmail(email); user.UpdateEmail(email);
user.UpdateDisplayName(displayName); user.SetDisplayName(displayName);
return userManager.UpdateAsync(user); return userManager.UpdateAsync(user);
} }

4
src/Squidex/app/features/content/pages/content/content-page.component.ts

@ -91,9 +91,9 @@ export class ContentPageComponent extends AppComponentBase implements CanCompone
}); });
} }
public canDeactivate(): Observable<boolean> | Promise<boolean> | boolean { public canDeactivate(): Observable<boolean> {
if (!this.contentForm.dirty) { if (!this.contentForm.dirty) {
return true; return Observable.of(true);
} else { } else {
this.cancelDialog.show(); this.cancelDialog.show();

9
src/Squidex/app/features/dashboard/pages/dashboard-page.component.ts

@ -154,14 +154,7 @@ export class DashboardPageComponent extends AppComponentBase implements OnInit,
}; };
}); });
this.authenticationSubscription = this.profileDisplayName = this.authService.user.displayName;
this.authService.isAuthenticated.subscribe(() => {
const user = this.authService.user;
if (user) {
this.profileDisplayName = user.displayName;
}
});
} }
public showForum() { public showForum() {

6
src/Squidex/app/framework/angular/can-deactivate.guard.spec.ts

@ -5,6 +5,8 @@
* Copyright (c) Sebastian Stehle. All rights reserved * Copyright (c) Sebastian Stehle. All rights reserved
*/ */
import { Observable } from 'rxjs';
import { CanDeactivateGuard } from './can-deactivate.guard'; import { CanDeactivateGuard } from './can-deactivate.guard';
describe('CanDeactivateGuard', () => { describe('CanDeactivateGuard', () => {
@ -15,13 +17,13 @@ describe('CanDeactivateGuard', () => {
canDeactivate: () => { canDeactivate: () => {
called = true; called = true;
return true; return Observable.of(true);
} }
}; };
const result = new CanDeactivateGuard().canDeactivate(component); const result = new CanDeactivateGuard().canDeactivate(component);
expect(result).toBeTruthy(); expect(result).toBeDefined();
expect(called).toBeTruthy(); expect(called).toBeTruthy();
}); });
}); });

2
src/Squidex/app/framework/angular/can-deactivate.guard.ts

@ -10,7 +10,7 @@ import { CanDeactivate } from '@angular/router';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
export interface CanComponentDeactivate { export interface CanComponentDeactivate {
canDeactivate(): Observable<boolean> | Promise<boolean> | boolean; canDeactivate(): Observable<boolean>;
} }
@Injectable() @Injectable()

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

@ -6,6 +6,7 @@
*/ */
import { IMock, Mock } from 'typemoq'; import { IMock, Mock } from 'typemoq';
import { Observable } from 'rxjs';
import { AppsStoreService } from 'shared'; import { AppsStoreService } from 'shared';
@ -21,14 +22,14 @@ describe('AppMustExistGuard', () => {
it('should navigate to 404 page if app is not found', (done) => { it('should navigate to 404 page if app is not found', (done) => {
appsStore.setup(x => x.selectApp('my-app')) appsStore.setup(x => x.selectApp('my-app'))
.returns(() => Promise.resolve(false)); .returns(() => Observable.of(false));
const router = new RouterMockup(); const router = new RouterMockup();
const route = <any> { params: { appName: 'my-app' } }; const route = <any> { params: { appName: 'my-app' } };
const guard = new AppMustExistGuard(appsStore.object, <any>router); const guard = new AppMustExistGuard(appsStore.object, <any>router);
guard.canActivate(route, <any>{}) guard.canActivate(route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']); expect(router.lastNavigation).toEqual(['/404']);
@ -38,14 +39,14 @@ describe('AppMustExistGuard', () => {
it('should navigate to 404 page if app loading fails', (done) => { it('should navigate to 404 page if app loading fails', (done) => {
appsStore.setup(x => x.selectApp('my-app')) appsStore.setup(x => x.selectApp('my-app'))
.returns(() => Promise.reject<boolean>('error')); .returns(() => Observable.throw('error'));
const router = new RouterMockup(); const router = new RouterMockup();
const route = <any> { params: { appName: 'my-app' } }; const route = <any> { params: { appName: 'my-app' } };
const guard = new AppMustExistGuard(appsStore.object, <any>router); const guard = new AppMustExistGuard(appsStore.object, <any>router);
guard.canActivate(route, <any>{}) guard.canActivate(route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']); expect(router.lastNavigation).toEqual(['/404']);
@ -55,14 +56,14 @@ describe('AppMustExistGuard', () => {
it('should return true if app is found', (done) => { it('should return true if app is found', (done) => {
appsStore.setup(x => x.selectApp('my-app')) appsStore.setup(x => x.selectApp('my-app'))
.returns(() => Promise.resolve(true)); .returns(() => Observable.of(true));
const router = new RouterMockup(); const router = new RouterMockup();
const route = <any> { params: { appName: 'my-app' } }; const route = <any> { params: { appName: 'my-app' } };
const guard = new AppMustExistGuard(appsStore.object, <any>router); const guard = new AppMustExistGuard(appsStore.object, <any>router);
guard.canActivate(route, <any>{}) guard.canActivate(route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeTruthy(); expect(result).toBeTruthy();
expect(router.lastNavigation).toBeUndefined(); expect(router.lastNavigation).toBeUndefined();

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

@ -7,6 +7,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { AppsStoreService } from './../services/apps-store.service'; import { AppsStoreService } from './../services/apps-store.service';
@ -18,21 +19,20 @@ export class AppMustExistGuard implements CanActivate {
) { ) {
} }
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> { public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
const appName = route.params['appName']; const appName = route.params['appName'];
const result = const result =
this.appsStore.selectApp(appName) this.appsStore.selectApp(appName)
.then(hasApp => { .do(dto => {
if (!hasApp) { if (!dto) {
this.router.navigate(['/404']); this.router.navigate(['/404']);
} }
})
return hasApp; .catch(error => {
}, () => {
this.router.navigate(['/404']); this.router.navigate(['/404']);
return false; return Observable.of(false);
}); });
return result; return result;

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

@ -6,6 +6,7 @@
*/ */
import { IMock, Mock } from 'typemoq'; import { IMock, Mock } from 'typemoq';
import { Observable } from 'rxjs';
import { AuthService } from 'shared'; import { AuthService } from 'shared';
@ -20,14 +21,14 @@ describe('MustBeAuthenticatedGuard', () => {
}); });
it('should navigate to default page if not authenticated', (done) => { it('should navigate to default page if not authenticated', (done) => {
authService.setup(x => x.checkLogin()) authService.setup(x => x.userChanges)
.returns(() => Promise.resolve(false)); .returns(() => Observable.of(null));
const router = new RouterMockup(); const router = new RouterMockup();
const guard = new MustBeAuthenticatedGuard(authService.object, <any>router); const guard = new MustBeAuthenticatedGuard(authService.object, <any>router);
guard.canActivate(<any>{}, <any>{}) guard.canActivate(<any>{}, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['']); expect(router.lastNavigation).toEqual(['']);
@ -36,14 +37,14 @@ describe('MustBeAuthenticatedGuard', () => {
}); });
it('should return true if authenticated', (done) => { it('should return true if authenticated', (done) => {
authService.setup(x => x.checkLogin()) authService.setup(x => x.userChanges)
.returns(() => Promise.resolve(true)); .returns(() => Observable.of(<any>{}));
const router = new RouterMockup(); const router = new RouterMockup();
const guard = new MustBeAuthenticatedGuard(authService.object, <any>router); const guard = new MustBeAuthenticatedGuard(authService.object, <any>router);
guard.canActivate(<any>{}, <any>{}) guard.canActivate(<any>{}, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeTruthy(); expect(result).toBeTruthy();
expect(router.lastNavigation).toBeUndefined(); expect(router.lastNavigation).toBeUndefined();

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

@ -7,6 +7,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './../services/auth.service'; import { AuthService } from './../services/auth.service';
@ -18,12 +19,13 @@ export class MustBeAuthenticatedGuard implements CanActivate {
) { ) {
} }
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> { public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authService.checkLogin().then(isAuthenticated => { return this.authService.userChanges.first()
if (!isAuthenticated) { .do(user => {
this.router.navigate(['']); if (!user) {
} this.router.navigate(['']);
return isAuthenticated; }
}); })
.map(user => !!user);
} }
} }

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

@ -6,6 +6,7 @@
*/ */
import { IMock, Mock } from 'typemoq'; import { IMock, Mock } from 'typemoq';
import { Observable } from 'rxjs';
import { AuthService } from 'shared'; import { AuthService } from 'shared';
@ -20,14 +21,14 @@ describe('MustBeNotAuthenticatedGuard', () => {
}); });
it('should navigate to app page if authenticated', (done) => { it('should navigate to app page if authenticated', (done) => {
authService.setup(x => x.checkLogin()) authService.setup(x => x.userChanges)
.returns(() => Promise.resolve(true)); .returns(() => Observable.of(<any>{}));
const router = new RouterMockup(); const router = new RouterMockup();
const guard = new MustBeNotAuthenticatedGuard(authService.object, <any>router); const guard = new MustBeNotAuthenticatedGuard(authService.object, <any>router);
guard.canActivate(<any>{}, <any>{}) guard.canActivate(<any>{}, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['app']); expect(router.lastNavigation).toEqual(['app']);
@ -36,14 +37,14 @@ describe('MustBeNotAuthenticatedGuard', () => {
}); });
it('should return true if not authenticated', (done) => { it('should return true if not authenticated', (done) => {
authService.setup(x => x.checkLogin()) authService.setup(x => x.userChanges)
.returns(() => Promise.resolve(false)); .returns(() => Observable.of(null));
const router = new RouterMockup(); const router = new RouterMockup();
const guard = new MustBeNotAuthenticatedGuard(authService.object, <any>router); const guard = new MustBeNotAuthenticatedGuard(authService.object, <any>router);
guard.canActivate(<any>{}, <any>{}) guard.canActivate(<any>{}, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeTruthy(); expect(result).toBeTruthy();
expect(router.lastNavigation).toBeUndefined(); expect(router.lastNavigation).toBeUndefined();

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

@ -7,6 +7,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './../services/auth.service'; import { AuthService } from './../services/auth.service';
@ -18,12 +19,13 @@ export class MustBeNotAuthenticatedGuard implements CanActivate {
) { ) {
} }
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> { public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authService.checkLogin().then(isAuthenticated => { return this.authService.userChanges.first()
if (isAuthenticated) { .do(user => {
this.router.navigate(['app']); if (user) {
} this.router.navigate(['app']);
return !isAuthenticated; }
}); })
.map(user => !user);
} }
} }

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

@ -43,7 +43,7 @@ describe('ResolveAppLanguagesGuard', () => {
const guard = new ResolveAppLanguagesGuard(appLanguagesService.object, <any>router); const guard = new ResolveAppLanguagesGuard(appLanguagesService.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']); expect(router.lastNavigation).toEqual(['/404']);
@ -59,7 +59,7 @@ describe('ResolveAppLanguagesGuard', () => {
const guard = new ResolveAppLanguagesGuard(appLanguagesService.object, <any>router); const guard = new ResolveAppLanguagesGuard(appLanguagesService.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']); expect(router.lastNavigation).toEqual(['/404']);
@ -77,7 +77,7 @@ describe('ResolveAppLanguagesGuard', () => {
const guard = new ResolveAppLanguagesGuard(appLanguagesService.object, <any>router); const guard = new ResolveAppLanguagesGuard(appLanguagesService.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBe(languages); expect(result).toBe(languages);
done(); done();

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

@ -7,6 +7,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { allParams } from 'framework'; import { allParams } from 'framework';
@ -20,7 +21,7 @@ export class ResolveAppLanguagesGuard implements Resolve<AppLanguageDto[]> {
) { ) {
} }
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<AppLanguageDto[]> { public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<AppLanguageDto[]> {
const params = allParams(route); const params = allParams(route);
const appName = params['appName']; const appName = params['appName'];
@ -30,19 +31,16 @@ export class ResolveAppLanguagesGuard implements Resolve<AppLanguageDto[]> {
} }
const result = const result =
this.appLanguagesService.getLanguages(appName).toPromise() this.appLanguagesService.getLanguages(appName)
.then(dto => { .do(dto => {
if (!dto) { if (!dto) {
this.router.navigate(['/404']); this.router.navigate(['/404']);
return null;
} }
})
return dto; .catch(error => {
}, error => {
this.router.navigate(['/404']); this.router.navigate(['/404']);
return null; return Observable.of(null);
}); });
return result; return result;

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

@ -62,7 +62,7 @@ describe('ResolveContentGuard', () => {
const guard = new ResolveContentGuard(appsStore.object, <any>router); const guard = new ResolveContentGuard(appsStore.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']); expect(router.lastNavigation).toEqual(['/404']);
@ -78,7 +78,7 @@ describe('ResolveContentGuard', () => {
const guard = new ResolveContentGuard(appsStore.object, <any>router); const guard = new ResolveContentGuard(appsStore.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']); expect(router.lastNavigation).toEqual(['/404']);
@ -96,7 +96,7 @@ describe('ResolveContentGuard', () => {
const guard = new ResolveContentGuard(appsStore.object, <any>router); const guard = new ResolveContentGuard(appsStore.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBe(content); expect(result).toBe(content);
done(); done();

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

@ -7,6 +7,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { allParams } from 'framework'; import { allParams } from 'framework';
@ -20,7 +21,7 @@ export class ResolveContentGuard implements Resolve<ContentDto> {
) { ) {
} }
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<ContentDto> { public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<ContentDto> {
const params = allParams(route); const params = allParams(route);
const appName = params['appName']; const appName = params['appName'];
@ -42,19 +43,16 @@ export class ResolveContentGuard implements Resolve<ContentDto> {
} }
const result = const result =
this.contentsService.getContent(appName, schemaName, contentId).toPromise() this.contentsService.getContent(appName, schemaName, contentId)
.then(dto => { .do(dto => {
if (!dto) { if (!dto) {
this.router.navigate(['/404']); this.router.navigate(['/404']);
return null;
} }
})
return dto; .catch(error => {
}, error => {
this.router.navigate(['/404']); this.router.navigate(['/404']);
return null; return Observable.of(null);
}); });
return result; return result;

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

@ -51,7 +51,7 @@ describe('ResolvePublishedSchemaGuard', () => {
const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>router); const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']); expect(router.lastNavigation).toEqual(['/404']);
@ -67,7 +67,7 @@ describe('ResolvePublishedSchemaGuard', () => {
const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>router); const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']); expect(router.lastNavigation).toEqual(['/404']);
@ -85,7 +85,7 @@ describe('ResolvePublishedSchemaGuard', () => {
const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>router); const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']); expect(router.lastNavigation).toEqual(['/404']);
@ -103,7 +103,7 @@ describe('ResolvePublishedSchemaGuard', () => {
const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>router); const guard = new ResolvePublishedSchemaGuard(schemasService.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBe(schema); expect(result).toBe(schema);
done(); done();

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

@ -7,6 +7,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { allParams } from 'framework'; import { allParams } from 'framework';
@ -20,7 +21,7 @@ export class ResolvePublishedSchemaGuard implements Resolve<SchemaDetailsDto> {
) { ) {
} }
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<SchemaDetailsDto> { public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<SchemaDetailsDto> {
const params = allParams(route); const params = allParams(route);
const appName = params['appName']; const appName = params['appName'];
@ -36,19 +37,16 @@ export class ResolvePublishedSchemaGuard implements Resolve<SchemaDetailsDto> {
} }
const result = const result =
this.schemasService.getSchema(appName, schemaName).toPromise() this.schemasService.getSchema(appName, schemaName).map(dto => dto && dto.isPublished ? dto : null)
.then(dto => { .do(dto => {
if (!dto || !dto.isPublished) { if (!dto) {
this.router.navigate(['/404']); this.router.navigate(['/404']);
return null;
} }
})
return dto; .catch(error => {
}, error => {
this.router.navigate(['/404']); this.router.navigate(['/404']);
return null; return Observable.of(error);
}); });
return result; return result;

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

@ -51,7 +51,7 @@ describe('ResolveSchemaGuard', () => {
const guard = new ResolveSchemaGuard(schemasService.object, <any>router); const guard = new ResolveSchemaGuard(schemasService.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']); expect(router.lastNavigation).toEqual(['/404']);
@ -67,7 +67,7 @@ describe('ResolveSchemaGuard', () => {
const guard = new ResolveSchemaGuard(schemasService.object, <any>router); const guard = new ResolveSchemaGuard(schemasService.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']); expect(router.lastNavigation).toEqual(['/404']);
@ -85,7 +85,7 @@ describe('ResolveSchemaGuard', () => {
const guard = new ResolveSchemaGuard(schemasService.object, <any>router); const guard = new ResolveSchemaGuard(schemasService.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBe(schema); expect(result).toBe(schema);
done(); done();

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

@ -7,6 +7,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { allParams } from 'framework'; import { allParams } from 'framework';
@ -20,7 +21,7 @@ export class ResolveSchemaGuard implements Resolve<SchemaDetailsDto> {
) { ) {
} }
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<SchemaDetailsDto> { public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<SchemaDetailsDto> {
const params = allParams(route); const params = allParams(route);
const appName = params['appName']; const appName = params['appName'];
@ -36,19 +37,16 @@ export class ResolveSchemaGuard implements Resolve<SchemaDetailsDto> {
} }
const result = const result =
this.schemasService.getSchema(appName, schemaName).toPromise() this.schemasService.getSchema(appName, schemaName)
.then(dto => { .do(dto => {
if (!dto) { if (!dto) {
this.router.navigate(['/404']); this.router.navigate(['/404']);
return null;
} }
})
return dto; .catch(error => {
}, error => {
this.router.navigate(['/404']); this.router.navigate(['/404']);
return null; return Observable.of(error);
}); });
return result; return result;

6
src/Squidex/app/shared/guards/resolve-user.guard.spec.ts

@ -43,7 +43,7 @@ describe('ResolveUserGuard', () => {
const guard = new ResolveUserGuard(usersService.object, <any>router); const guard = new ResolveUserGuard(usersService.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']); expect(router.lastNavigation).toEqual(['/404']);
@ -59,7 +59,7 @@ describe('ResolveUserGuard', () => {
const guard = new ResolveUserGuard(usersService.object, <any>router); const guard = new ResolveUserGuard(usersService.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
expect(router.lastNavigation).toEqual(['/404']); expect(router.lastNavigation).toEqual(['/404']);
@ -77,7 +77,7 @@ describe('ResolveUserGuard', () => {
const guard = new ResolveUserGuard(usersService.object, <any>router); const guard = new ResolveUserGuard(usersService.object, <any>router);
guard.resolve(<any>route, <any>{}) guard.resolve(<any>route, <any>{})
.then(result => { .subscribe(result => {
expect(result).toBe(user); expect(result).toBe(user);
done(); done();

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

@ -7,6 +7,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { allParams } from 'framework'; import { allParams } from 'framework';
@ -20,7 +21,7 @@ export class ResolveUserGuard implements Resolve<UserDto> {
) { ) {
} }
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<UserDto> { public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<UserDto> {
const params = allParams(route); const params = allParams(route);
const userId = params['userId']; const userId = params['userId'];
@ -30,19 +31,16 @@ export class ResolveUserGuard implements Resolve<UserDto> {
} }
const result = const result =
this.userManagementService.getUser(userId).toPromise() this.userManagementService.getUser(userId)
.then(dto => { .do(dto => {
if (!dto) { if (!dto) {
this.router.navigate(['/404']); this.router.navigate(['/404']);
return null;
} }
})
return dto; .catch(error => {
}, error => {
this.router.navigate(['/404']); this.router.navigate(['/404']);
return null; return Observable.of(null);
}); });
return result; return result;

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

@ -8,6 +8,7 @@
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpClient, HttpHeaders, HTTP_INTERCEPTORS } from '@angular/common/http'; import { HttpClient, HttpHeaders, HTTP_INTERCEPTORS } from '@angular/common/http';
import { inject, TestBed } from '@angular/core/testing'; import { inject, TestBed } from '@angular/core/testing';
import { Observable } from 'rxjs';
import { IMock, Mock, Times } from 'typemoq'; import { IMock, Mock, Times } from 'typemoq';
import { import {
@ -16,12 +17,11 @@ import {
AuthInterceptor AuthInterceptor
} from './../'; } from './../';
describe('AppClientsService', () => { describe('AuthInterceptor', () => {
let authService: IMock<AuthService> = null; let authService: IMock<AuthService> = null;
beforeEach(() => { beforeEach(() => {
authService = Mock.ofType(AuthService); authService = Mock.ofType(AuthService);
authService.setup(x => x.user).returns(() => { return <any>{ authToken: 'letmein' }; });
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [
@ -46,6 +46,8 @@ describe('AppClientsService', () => {
it('should append headers to request', it('should append headers to request',
inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => { inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
authService.setup(x => x.userChanges).returns(() => { return Observable.of(<any>{ authToken: 'letmein' }); });
http.get('http://service/p/apps').subscribe(); http.get('http://service/p/apps').subscribe();
const req = httpMock.expectOne('http://service/p/apps'); const req = httpMock.expectOne('http://service/p/apps');
@ -59,6 +61,8 @@ describe('AppClientsService', () => {
it('should not append headers for no auth headers', it('should not append headers for no auth headers',
inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => { inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
authService.setup(x => x.userChanges).returns(() => { return Observable.of(<any>{ authToken: 'letmein' }); });
http.get('http://service/p/apps', { headers: new HttpHeaders().set('NoAuth', '') }).subscribe(); http.get('http://service/p/apps', { headers: new HttpHeaders().set('NoAuth', '') }).subscribe();
const req = httpMock.expectOne('http://service/p/apps'); const req = httpMock.expectOne('http://service/p/apps');
@ -72,6 +76,8 @@ describe('AppClientsService', () => {
it('should not append headers for other requests', it('should not append headers for other requests',
inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => { inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
authService.setup(x => x.userChanges).returns(() => { return Observable.of(<any>{ authToken: 'letmein' }); });
http.get('http://cloud/p/apps').subscribe(); http.get('http://cloud/p/apps').subscribe();
const req = httpMock.expectOne('http://cloud/p/apps'); const req = httpMock.expectOne('http://cloud/p/apps');
@ -85,7 +91,7 @@ describe('AppClientsService', () => {
it(`should logout for 404 status code when user is expired.`, it(`should logout for 404 status code when user is expired.`,
inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => { inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
authService.setup(x => x.user).returns(() => { return <any>{ authToken: 'letmein', isExpired: true }; }); authService.setup(x => x.userChanges).returns(() => { return Observable.of(<any>{ authToken: 'letmein', isExpired: true }); });
http.get('http://service/p/apps').subscribe( http.get('http://service/p/apps').subscribe(
_ => { /* NOOP */ }, _ => { /* NOOP */ },
@ -102,6 +108,8 @@ describe('AppClientsService', () => {
it(`should logout for ${statusCode} status code`, it(`should logout for ${statusCode} status code`,
inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => { inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
authService.setup(x => x.userChanges).returns(() => { return Observable.of(<any>{ authToken: 'letmein' }); });
http.get('http://service/p/apps').subscribe( http.get('http://service/p/apps').subscribe(
_ => { /* NOOP */ }, _ => { /* NOOP */ },
_ => { /* NOOP */ }); _ => { /* NOOP */ });
@ -118,6 +126,8 @@ describe('AppClientsService', () => {
it(`should not logout for ${statusCode} status code`, it(`should not logout for ${statusCode} status code`,
inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => { inject([HttpClient, HttpTestingController], (http: HttpClient, httpMock: HttpTestingController) => {
authService.setup(x => x.userChanges).returns(() => { return Observable.of(<any>{ authToken: 'letmein' }); });
http.get('http://service/p/apps').subscribe( http.get('http://service/p/apps').subscribe(
_ => { /* NOOP */ }, _ => { /* NOOP */ },
_ => { /* NOOP */ }); _ => { /* NOOP */ });

38
src/Squidex/app/shared/interceptors/auth.interceptor.ts

@ -24,26 +24,30 @@ export class AuthInterceptor implements HttpInterceptor {
public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.url.indexOf(this.baseUrl) === 0 && !req.headers.has('NoAuth')) { if (req.url.indexOf(this.baseUrl) === 0 && !req.headers.has('NoAuth')) {
const authReq = req.clone({ return this.authService.userChanges.first().switchMap(user => {
headers: req.headers const token = user ? user.authToken : '';
.set('Authorization', this.authService.user ? this.authService.user.authToken : '')
.set('Accept-Language', '*') const authReq = req.clone({
.set('Pragma', 'no-cache') headers: req.headers
}); .set('Authorization', token)
.set('Accept-Language', '*')
.set('Pragma', 'no-cache')
});
return next.handle(authReq) return next.handle(authReq)
.catch((error: HttpErrorResponse) => { .catch((error: HttpErrorResponse) => {
if (error.status === 404 && (!this.authService.user || this.authService.user.isExpired)) { if (error.status === 404 && (!user || user.isExpired)) {
this.authService.logoutRedirect(); this.authService.logoutRedirect();
return Observable.empty<Response>(); return Observable.empty<Response>();
} else if (error.status === 401 || error.status === 403) { } else if (error.status === 401 || error.status === 403) {
this.authService.logoutRedirect(); this.authService.logoutRedirect();
return Observable.empty<Response>(); return Observable.empty<Response>();
} }
return Observable.throw(error); return Observable.throw(error);
}); });
});
} else { } else {
return next.handle(req); return next.handle(req);
} }

49
src/Squidex/app/shared/services/apps-store.service.spec.ts

@ -12,7 +12,6 @@ import {
AppDto, AppDto,
AppsService, AppsService,
AppsStoreService, AppsStoreService,
AuthService,
CreateAppDto, CreateAppDto,
DateTime DateTime
} from './../'; } from './../';
@ -24,23 +23,17 @@ describe('AppsStoreService', () => {
const newApp = new AppDto('id', 'new-name', 'Owner', now, now); const newApp = new AppDto('id', 'new-name', 'Owner', now, now);
let appsService: IMock<AppsService>; let appsService: IMock<AppsService>;
let authService: IMock<AuthService>;
beforeEach(() => { beforeEach(() => {
appsService = Mock.ofType(AppsService); appsService = Mock.ofType(AppsService);
authService = Mock.ofType(AuthService);
}); });
it('should load when authenticated once', () => { it('should load automatically', () => {
authService.setup(x => x.isAuthenticated)
.returns(() => Observable.of(true))
.verifiable(Times.once());
appsService.setup(x => x.getApps()) appsService.setup(x => x.getApps())
.returns(() => Observable.of(oldApps)) .returns(() => Observable.of(oldApps))
.verifiable(Times.once()); .verifiable(Times.once());
const store = new AppsStoreService(authService.object, appsService.object); const store = new AppsStoreService(appsService.object);
let result1: AppDto[] | null = null; let result1: AppDto[] | null = null;
let result2: AppDto[] | null = null; let result2: AppDto[] | null = null;
@ -60,10 +53,6 @@ describe('AppsStoreService', () => {
}); });
it('should add app to cache when created', () => { it('should add app to cache when created', () => {
authService.setup(x => x.isAuthenticated)
.returns(() => Observable.of(true))
.verifiable(Times.once());
appsService.setup(x => x.getApps()) appsService.setup(x => x.getApps())
.returns(() => Observable.of(oldApps)) .returns(() => Observable.of(oldApps))
.verifiable(Times.once()); .verifiable(Times.once());
@ -72,7 +61,7 @@ describe('AppsStoreService', () => {
.returns(() => Observable.of(newApp)) .returns(() => Observable.of(newApp))
.verifiable(Times.once()); .verifiable(Times.once());
const store = new AppsStoreService(authService.object, appsService.object); const store = new AppsStoreService(appsService.object);
let result1: AppDto[] | null = null; let result1: AppDto[] | null = null;
let result2: AppDto[] | null = null; let result2: AppDto[] | null = null;
@ -93,42 +82,14 @@ describe('AppsStoreService', () => {
appsService.verifyAll(); appsService.verifyAll();
}); });
it('should not add app to cache when cache is null', () => {
authService.setup(x => x.isAuthenticated)
.returns(() => Observable.of(false))
.verifiable(Times.once());
appsService.setup(x => x.postApp(It.isAny()))
.returns(() => Observable.of(newApp))
.verifiable(Times.once());
const store = new AppsStoreService(authService.object, appsService.object);
let result: AppDto[] | null = null;
store.createApp(new CreateAppDto('new-name'), now).subscribe(x => { /* Do Nothing */ });
store.apps.subscribe(x => {
result = x;
}).unsubscribe();
expect(result).toBeNull();
appsService.verifyAll();
});
it('should select app', (done) => { it('should select app', (done) => {
authService.setup(x => x.isAuthenticated)
.returns(() => Observable.of(true))
.verifiable(Times.once());
appsService.setup(x => x.getApps()) appsService.setup(x => x.getApps())
.returns(() => Observable.of(oldApps)) .returns(() => Observable.of(oldApps))
.verifiable(Times.once()); .verifiable(Times.once());
const store = new AppsStoreService(authService.object, appsService.object); const store = new AppsStoreService(appsService.object);
store.selectApp('old-name').then((isSelected) => { store.selectApp('old-name').subscribe(isSelected => {
expect(isSelected).toBeTruthy(); expect(isSelected).toBeTruthy();
appsService.verifyAll(); appsService.verifyAll();

18
src/Squidex/app/shared/services/apps-store.service.ts

@ -16,8 +16,6 @@ import {
CreateAppDto CreateAppDto
} from './apps.service'; } from './apps.service';
import { AuthService } from './auth.service';
@Injectable() @Injectable()
export class AppsStoreService { export class AppsStoreService {
private readonly apps$ = new ReplaySubject<AppDto[]>(); private readonly apps$ = new ReplaySubject<AppDto[]>();
@ -32,21 +30,21 @@ export class AppsStoreService {
} }
constructor( constructor(
private readonly authService: AuthService,
private readonly appsService: AppsService private readonly appsService: AppsService
) { ) {
if (!appsService) { if (!appsService) {
return; return;
} }
this.authService.isAuthenticated.filter(t => !!t).first() this.appsService.getApps()
.switchMap(() => this.appsService.getApps())
.subscribe(apps => { .subscribe(apps => {
this.apps$.next(apps); this.apps$.next(apps);
}, error => {
this.apps$.next([]);
}); });
} }
public selectApp(name: string | null): Promise<boolean> { public selectApp(name: string | null): Observable<boolean> {
return Observable.create((observer: Observer<boolean>) => { return Observable.create((observer: Observer<boolean>) => {
this.apps$.subscribe(apps => { this.apps$.subscribe(apps => {
const app = apps.find(x => x.name === name) || null; const app = apps.find(x => x.name === name) || null;
@ -58,7 +56,7 @@ export class AppsStoreService {
}, error => { }, error => {
observer.error(error); observer.error(error);
}); });
}).toPromise(); });
} }
public createApp(dto: CreateAppDto, now?: DateTime): Observable<AppDto> { public createApp(dto: CreateAppDto, now?: DateTime): Observable<AppDto> {
@ -69,10 +67,8 @@ export class AppsStoreService {
return new AppDto(created.id, dto.name, 'Owner', now, now); return new AppDto(created.id, dto.name, 'Owner', now, now);
}) })
.do(app => { .do(app => {
this.apps$.defaultIfEmpty().first().subscribe(apps => { this.apps$.first().subscribe(apps => {
if (apps) { this.apps$.next(apps.concat([app]));
this.apps$.next(apps.concat([app]));
}
}); });
}); });
} }

82
src/Squidex/app/shared/services/auth.service.ts

@ -6,7 +6,7 @@
*/ */
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs'; import { Observable, ReplaySubject } from 'rxjs';
import { import {
Log, Log,
@ -54,22 +54,15 @@ export class Profile {
@Injectable() @Injectable()
export class AuthService { export class AuthService {
private readonly userManager: UserManager; private readonly userManager: UserManager;
private readonly isAuthenticatedChanged$ = new Subject<boolean>(); private readonly user$ = new ReplaySubject<Profile | null>();
private loginCompleted: boolean | null = false; private currentUser: Profile = null;
private loginCache: Promise<boolean> | null = null;
private currentUser: Profile | null = null;
private readonly isAuthenticatedChangedPublished$ =
this.isAuthenticatedChanged$
.distinctUntilChanged()
.publishReplay(1);
public get user(): Profile | null { public get user(): Profile | null {
return this.currentUser; return this.currentUser;
} }
public get isAuthenticated(): Observable<boolean> { public get userChanges(): Observable<Profile | null> {
return this.isAuthenticatedChangedPublished$; return this.user$;
} }
constructor(apiUrl: ApiUrlConfig) { constructor(apiUrl: ApiUrlConfig) {
@ -92,27 +85,18 @@ export class AuthService {
}); });
this.userManager.events.addUserLoaded(user => { this.userManager.events.addUserLoaded(user => {
this.onAuthenticated(user); this.user$.next(new Profile(user));
}); });
this.userManager.events.addUserUnloaded(() => { this.userManager.events.addUserUnloaded(() => {
this.onDeauthenticated(); this.user$.next(null);
}); });
this.checkLogin(); this.user$.subscribe(user => {
this.currentUser = user;
this.isAuthenticatedChangedPublished$.connect(); });
}
public checkLogin(): Promise<boolean> { this.userManager.signinSilent();
if (this.loginCompleted) {
return Promise.resolve(this.currentUser !== null);
} else {
if (!this.loginCache) {
this.loginCache = this.checkState(this.userManager.signinSilent());
}
return this.loginCache;
}
} }
public logoutRedirect(): Observable<any> { public logoutRedirect(): Observable<any> {
@ -123,6 +107,10 @@ export class AuthService {
return Observable.fromPromise(this.userManager.signoutRedirectCallback()); return Observable.fromPromise(this.userManager.signoutRedirectCallback());
} }
public loginPopup(): Observable<any> {
return Observable.fromPromise(this.userManager.signinPopup());
}
public loginRedirect(): Observable<any> { public loginRedirect(): Observable<any> {
return Observable.fromPromise(this.userManager.signinRedirect()); return Observable.fromPromise(this.userManager.signinRedirect());
} }
@ -130,44 +118,4 @@ export class AuthService {
public loginRedirectComplete(): Observable<any> { public loginRedirectComplete(): Observable<any> {
return Observable.fromPromise(this.userManager.signinRedirectCallback()); return Observable.fromPromise(this.userManager.signinRedirectCallback());
} }
public loginPopup(): Observable<boolean> {
const promise = this.checkState(this.userManager.signinPopup());
return Observable.fromPromise(promise);
}
private onAuthenticated(user: User) {
this.currentUser = new Profile(user);
this.isAuthenticatedChanged$.next(true);
}
private onDeauthenticated() {
this.currentUser = null;
this.isAuthenticatedChanged$.next(false);
}
private checkState(promise: Promise<User>): Promise<boolean> {
const resultPromise =
promise
.then(user => {
this.loginCache = null;
this.loginCompleted = null;
this.onAuthenticated(user);
return !!this.currentUser;
}).catch((err) => {
this.loginCache = null;
this.loginCompleted = null;
this.onDeauthenticated();
return false;
});
return resultPromise;
}
} }

14
src/Squidex/app/shell/pages/internal/profile-menu.component.ts

@ -47,16 +47,12 @@ export class ProfileMenuComponent implements OnInit, OnDestroy {
public ngOnInit() { public ngOnInit() {
this.authenticationSubscription = this.authenticationSubscription =
this.authService.isAuthenticated.first() this.authService.userChanges.filter(user => !!user)
.subscribe(() => { .subscribe(user => {
const user = this.authService.user; this.profileId = user.id;
this.profileDisplayName = user.displayName;
if (user) { this.isAdmin = user.isAdmin;
this.profileId = user.id;
this.profileDisplayName = user.displayName;
this.isAdmin = user.isAdmin;
}
}); });
} }

Loading…
Cancel
Save