Browse Source

Merge pull request #15917 from abpframework/feat-local-storage-service

Feat local storage service
pull/15933/head
Mahmut Gundogdu 4 years ago
committed by GitHub
parent
commit
e951395282
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      npm/ng-packs/packages/core/src/lib/services/index.ts
  2. 28
      npm/ng-packs/packages/core/src/lib/services/local-storage.service.ts
  3. 10
      npm/ng-packs/packages/core/src/lib/services/session-state.service.ts
  4. 52
      npm/ng-packs/packages/core/src/lib/tests/local-storage.service.spec.ts
  5. 6
      npm/ng-packs/packages/oauth/src/lib/oauth.module.ts
  6. 3
      npm/ng-packs/packages/oauth/src/lib/strategies/auth-flow-strategy.ts
  7. 8
      npm/ng-packs/packages/oauth/src/lib/strategies/auth-password-flow-strategy.ts
  8. 19
      npm/ng-packs/packages/oauth/src/lib/utils/auth-utils.ts

1
npm/ng-packs/packages/core/src/lib/services/index.ts

@ -18,3 +18,4 @@ export * from './routes.service';
export * from './session-state.service'; export * from './session-state.service';
export * from './subscription.service'; export * from './subscription.service';
export * from './track-by.service'; export * from './track-by.service';
export * from './local-storage.service';

28
npm/ng-packs/packages/core/src/lib/services/local-storage.service.ts

@ -0,0 +1,28 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class AbpLocalStorageService implements Storage {
constructor() {}
[name: string]: any;
get length(): number {
return localStorage.length;
}
clear(): void {
localStorage.clear();
}
getItem(key: string): string {
return localStorage.getItem(key);
}
key(index: number): string {
return localStorage.key(index);
}
removeItem(key: string): void {
localStorage.removeItem(key);
}
setItem(key: string, value: string): void {
localStorage.setItem(key, value);
}
}

10
npm/ng-packs/packages/core/src/lib/services/session-state.service.ts

@ -5,6 +5,7 @@ import { Session } from '../models/session';
import { CurrentTenantDto } from '../proxy/volo/abp/asp-net-core/mvc/multi-tenancy/models'; import { CurrentTenantDto } from '../proxy/volo/abp/asp-net-core/mvc/multi-tenancy/models';
import { InternalStore } from '../utils/internal-store-utils'; import { InternalStore } from '../utils/internal-store-utils';
import { ConfigStateService } from './config-state.service'; import { ConfigStateService } from './config-state.service';
import { AbpLocalStorageService } from './local-storage.service';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
@ -13,16 +14,19 @@ export class SessionStateService {
private readonly store = new InternalStore({} as Session.State); private readonly store = new InternalStore({} as Session.State);
private updateLocalStorage = () => { private updateLocalStorage = () => {
localStorage.setItem('abpSession', JSON.stringify(this.store.state)); this.localStorageService.setItem('abpSession', JSON.stringify(this.store.state));
}; };
constructor(private configState: ConfigStateService) { constructor(
private configState: ConfigStateService,
private localStorageService: AbpLocalStorageService,
) {
this.init(); this.init();
this.setInitialLanguage(); this.setInitialLanguage();
} }
private init() { private init() {
const session = localStorage.getItem('abpSession'); const session = this.localStorageService.getItem('abpSession');
if (session) { if (session) {
this.store.set(JSON.parse(session)); this.store.set(JSON.parse(session));
} }

52
npm/ng-packs/packages/core/src/lib/tests/local-storage.service.spec.ts

@ -0,0 +1,52 @@
import { TestBed } from '@angular/core/testing';
import { AbpLocalStorageService } from '../services/local-storage.service';
describe('LocalStorageService', () => {
let service: AbpLocalStorageService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AbpLocalStorageService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
it('should be called getItem', () => {
const spy = jest.spyOn(service, 'getItem');
service.getItem('test');
expect(spy).toHaveBeenCalled();
});
it('should be called setItem', () => {
const spy = jest.spyOn(service, 'setItem');
service.setItem('test', 'value');
expect(spy).toHaveBeenCalled();
});
it('should be called removeItem', () => {
const spy = jest.spyOn(service, 'removeItem');
service.removeItem('test');
expect(spy).toHaveBeenCalled();
});
it('should be called clear', () => {
const spy = jest.spyOn(service, 'clear');
service.clear();
expect(spy).toHaveBeenCalled();
});
it('should be called key', () => {
const spy = jest.spyOn(service, 'key');
service.key(0);
expect(spy).toHaveBeenCalled();
});
it('should be called length', () => {
const spy = jest.spyOn(service, 'length', 'get');
service.length;
expect(spy).toHaveBeenCalled();
});
});

6
npm/ng-packs/packages/oauth/src/lib/oauth.module.ts

@ -2,14 +2,14 @@ import { APP_INITIALIZER, ModuleWithProviders, NgModule, Provider } from '@angul
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { OAuthModule, OAuthStorage } from 'angular-oauth2-oidc'; import { OAuthModule, OAuthStorage } from 'angular-oauth2-oidc';
import { import {
AbpLocalStorageService,
ApiInterceptor, ApiInterceptor,
AuthGuard, AuthGuard,
AuthService, AuthService,
CHECK_AUTHENTICATION_STATE_FN_KEY, CHECK_AUTHENTICATION_STATE_FN_KEY,
noop, noop,
PIPE_TO_LOGIN_FN_KEY PIPE_TO_LOGIN_FN_KEY,
} from '@abp/ng.core'; } from '@abp/ng.core';
import { storageFactory } from './utils/storage.factory';
import { AbpOAuthService } from './services'; import { AbpOAuthService } from './services';
import { OAuthConfigurationHandler } from './handlers/oauth-configuration.handler'; import { OAuthConfigurationHandler } from './handlers/oauth-configuration.handler';
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { HTTP_INTERCEPTORS } from '@angular/common/http';
@ -59,7 +59,7 @@ export class AbpOAuthModule {
useFactory: noop, useFactory: noop,
}, },
OAuthModule.forRoot().providers as Provider[], OAuthModule.forRoot().providers as Provider[],
{ provide: OAuthStorage, useFactory: storageFactory }, { provide: OAuthStorage, useClass: AbpLocalStorageService },
], ],
}; };
} }

3
npm/ng-packs/packages/oauth/src/lib/strategies/auth-flow-strategy.ts

@ -9,6 +9,7 @@ import {
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { filter, switchMap, tap } from 'rxjs/operators'; import { filter, switchMap, tap } from 'rxjs/operators';
import { import {
AbpLocalStorageService,
ConfigStateService, ConfigStateService,
EnvironmentService, EnvironmentService,
HttpErrorReporterService, HttpErrorReporterService,
@ -29,6 +30,7 @@ export abstract class AuthFlowStrategy {
protected oAuthService: OAuthService2; protected oAuthService: OAuthService2;
protected oAuthConfig!: AuthConfig; protected oAuthConfig!: AuthConfig;
protected sessionState: SessionStateService; protected sessionState: SessionStateService;
protected localStorageService: AbpLocalStorageService;
protected tenantKey: string; protected tenantKey: string;
abstract checkIfInternalAuth(queryParams?: Params): boolean; abstract checkIfInternalAuth(queryParams?: Params): boolean;
@ -50,6 +52,7 @@ export abstract class AuthFlowStrategy {
this.configState = injector.get(ConfigStateService); this.configState = injector.get(ConfigStateService);
this.oAuthService = injector.get(OAuthService2); this.oAuthService = injector.get(OAuthService2);
this.sessionState = injector.get(SessionStateService); this.sessionState = injector.get(SessionStateService);
this.localStorageService = injector.get(AbpLocalStorageService);
this.oAuthConfig = this.environment.getEnvironment().oAuthConfig || {}; this.oAuthConfig = this.environment.getEnvironment().oAuthConfig || {};
this.tenantKey = injector.get(TENANT_KEY); this.tenantKey = injector.get(TENANT_KEY);

8
npm/ng-packs/packages/oauth/src/lib/strategies/auth-password-flow-strategy.ts

@ -4,7 +4,7 @@ import { Params, Router } from '@angular/router';
import { from, Observable, pipe } from 'rxjs'; import { from, Observable, pipe } from 'rxjs';
import { HttpHeaders } from '@angular/common/http'; import { HttpHeaders } from '@angular/common/http';
import { AuthFlowStrategy } from './auth-flow-strategy'; import { AuthFlowStrategy } from './auth-flow-strategy';
import { pipeToLogin, removeRememberMe, setRememberMe } from '../utils/auth-utils'; import { pipeToLogin, removeRememberMe } from '../utils/auth-utils';
import { LoginParams } from '@abp/ng.core'; import { LoginParams } from '@abp/ng.core';
import { clearOAuthStorage } from '../utils/clear-o-auth-storage'; import { clearOAuthStorage } from '../utils/clear-o-auth-storage';
@ -33,7 +33,7 @@ export class AuthPasswordFlowStrategy extends AuthFlowStrategy {
this.refreshToken(); this.refreshToken();
} else { } else {
this.oAuthService.logOut(); this.oAuthService.logOut();
removeRememberMe(); removeRememberMe(this.localStorageService);
this.configState.refreshAppState().subscribe(); this.configState.refreshAppState().subscribe();
} }
}); });
@ -74,7 +74,7 @@ export class AuthPasswordFlowStrategy extends AuthFlowStrategy {
switchMap(() => this.configState.refreshAppState()), switchMap(() => this.configState.refreshAppState()),
tap(() => { tap(() => {
router.navigateByUrl('/'); router.navigateByUrl('/');
removeRememberMe(); removeRememberMe(this.localStorageService);
}), }),
); );
} }
@ -82,7 +82,7 @@ export class AuthPasswordFlowStrategy extends AuthFlowStrategy {
protected refreshToken() { protected refreshToken() {
return this.oAuthService.refreshToken().catch(() => { return this.oAuthService.refreshToken().catch(() => {
clearOAuthStorage(); clearOAuthStorage();
removeRememberMe(); removeRememberMe(this.localStorageService);
}); });
} }
} }

19
npm/ng-packs/packages/oauth/src/lib/utils/auth-utils.ts

@ -7,7 +7,7 @@ import {
ConfigStateService, ConfigStateService,
LoginParams, LoginParams,
PipeToLoginFn, PipeToLoginFn,
SetTokenResponseToStorageFn, AbpLocalStorageService,
} from '@abp/ng.core'; } from '@abp/ng.core';
const cookieKey = 'rememberMe'; const cookieKey = 'rememberMe';
@ -19,25 +19,28 @@ export const pipeToLogin: PipeToLoginFn = function (
) { ) {
const configState = injector.get(ConfigStateService); const configState = injector.get(ConfigStateService);
const router = injector.get(Router); const router = injector.get(Router);
const localStorage = injector.get(AbpLocalStorageService);
return pipe( return pipe(
switchMap(() => configState.refreshAppState()), switchMap(() => configState.refreshAppState()),
tap(() => { tap(() => {
setRememberMe(params.rememberMe); setRememberMe(params.rememberMe, localStorage);
if (params.redirectUrl) router.navigate([params.redirectUrl]); if (params.redirectUrl) router.navigate([params.redirectUrl]);
}), }),
); );
}; };
export function setRememberMe(remember: boolean | undefined) { export function setRememberMe(
removeRememberMe(); remember: boolean | undefined,
localStorage.setItem(storageKey, 'true'); localStorageService: AbpLocalStorageService,
) {
removeRememberMe(localStorageService);
localStorageService.setItem(storageKey, 'true');
document.cookie = `${cookieKey}=true; path=/${ document.cookie = `${cookieKey}=true; path=/${
remember ? ' ;expires=Fri, 31 Dec 9999 23:59:59 GMT' : '' remember ? ' ;expires=Fri, 31 Dec 9999 23:59:59 GMT' : ''
}`; }`;
} }
export function removeRememberMe() { export function removeRememberMe(localStorageService: AbpLocalStorageService) {
localStorage.removeItem(storageKey); localStorageService.removeItem(storageKey);
document.cookie = cookieKey + '= ; path=/; expires = Thu, 01 Jan 1970 00:00:00 GMT'; document.cookie = cookieKey + '= ; path=/; expires = Thu, 01 Jan 1970 00:00:00 GMT';
} }

Loading…
Cancel
Save