Browse Source

Merge pull request #9839 from abpframework/fix/9836

fix: use refreshAppState when updating config state
pull/9840/head
Mehmet Erim 5 years ago
committed by GitHub
parent
commit
21b497cd5d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      npm/ng-packs/packages/core/src/lib/services/config-state.service.ts
  2. 11
      npm/ng-packs/packages/core/src/lib/services/localization.service.ts
  3. 38
      npm/ng-packs/packages/core/src/lib/states/config.state.ts
  4. 23
      npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts
  5. 7
      npm/ng-packs/packages/core/src/lib/utils/auth-utils.ts
  6. 7
      npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts
  7. 17
      npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts
  8. 23
      npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts

23
npm/ng-packs/packages/core/src/lib/services/config-state.service.ts

@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { Observable, Subject } from 'rxjs';
import { map, take, switchMap } from 'rxjs/operators';
import { ApplicationConfigurationDto } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/models';
import { InternalStore } from '../utils/internal-store-utils';
import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';
@ -15,14 +15,29 @@ export class ConfigStateService {
return this.store.sliceUpdate;
}
constructor(private abpConfigService: AbpApplicationConfigurationService) {}
private updateSubject = new Subject();
constructor(private abpConfigService: AbpApplicationConfigurationService) {
this.initUpdateStream();
}
private initUpdateStream() {
this.updateSubject
.pipe(switchMap(() => this.abpConfigService.get()))
.subscribe(res => this.setState(res));
}
/**
* @deprecated do not use this method directly, instead call refreshAppState
* This method will be private in v5.0
*/
setState(state: ApplicationConfigurationDto) {
this.store.set(state);
}
refreshAppState() {
return this.abpConfigService.get().pipe(tap(res => this.setState(res)));
this.updateSubject.next();
return this.createOnUpdateStream(state => state).pipe(take(1));
}
getOne$(key: string) {

11
npm/ng-packs/packages/core/src/lib/services/localization.service.ts

@ -1,10 +1,9 @@
import { registerLocaleData } from '@angular/common';
import { Injectable, Injector, isDevMode, Optional, SkipSelf } from '@angular/core';
import { from, Observable, Subject } from 'rxjs';
import { filter, map, mapTo, switchMap, tap } from 'rxjs/operators';
import { filter, map, mapTo, switchMap } from 'rxjs/operators';
import { ABP } from '../models/common';
import { Config } from '../models/config';
import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';
import { ApplicationConfigurationDto } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/models';
import { CORE_OPTIONS } from '../tokens/options.token';
import { createLocalizer, createLocalizerWithFallback } from '../utils/localization-utils';
@ -35,7 +34,6 @@ export class LocalizationService {
@SkipSelf()
otherInstance: LocalizationService,
private configState: ConfigStateService,
private appConfigService: AbpApplicationConfigurationService,
) {
if (otherInstance) throw new Error('LocalizationService should have only one instance.');
@ -49,12 +47,7 @@ export class LocalizationService {
filter(
lang => this.configState.getDeep('localization.currentCulture.cultureName') !== lang,
),
switchMap(lang =>
this.appConfigService
.get()
.pipe(tap(res => this.configState.setState(res)))
.pipe(mapTo(lang)),
),
switchMap(lang => this.configState.refreshAppState().pipe(mapTo(lang))),
switchMap(lang => from(this.registerLocale(lang).then(() => lang))),
)
.subscribe(lang => this._languageChange$.next(lang));

38
npm/ng-packs/packages/core/src/lib/states/config.state.ts

@ -1,19 +1,17 @@
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Action, createSelector, Selector, State, StateContext, Store } from '@ngxs/store';
import { of, throwError } from 'rxjs';
import { catchError, distinctUntilChanged, switchMap, tap } from 'rxjs/operators';
import { throwError } from 'rxjs';
import { catchError, distinctUntilChanged } from 'rxjs/operators';
import snq from 'snq';
import { GetAppConfiguration, PatchConfigState, SetEnvironment } from '../actions/config.actions';
import { RestOccurError } from '../actions/rest.actions';
import { ApplicationConfiguration } from '../models/application-configuration';
import { Config } from '../models/config';
import { ConfigStateService } from '../services/config-state.service';
import { EnvironmentService } from '../services/environment.service';
import { SessionStateService } from '../services/session-state.service';
import { interpolate } from '../utils/string-utils';
import compare from 'just-compare';
import { ApplicationConfigurationDto } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/models';
/**
* @deprecated Use ConfigStateService instead. To be deleted in v5.0.
@ -143,11 +141,16 @@ export class ConfigState {
}
static getLocalizationResource(resourceName: string) {
const selector = createSelector([ConfigState], (state: Config.State): {
[key: string]: string;
} => {
return state.localization.values[resourceName];
});
const selector = createSelector(
[ConfigState],
(
state: Config.State,
): {
[key: string]: string;
} => {
return state.localization.values[resourceName];
},
);
return selector;
}
@ -217,9 +220,7 @@ export class ConfigState {
}
constructor(
private http: HttpClient,
private store: Store,
private sessionState: SessionStateService,
private environmentService: EnvironmentService,
private configState: ConfigStateService,
) {
@ -245,15 +246,12 @@ export class ConfigState {
addData({ patchState, dispatch }: StateContext<Config.State>) {
const apiName = 'default';
const api = this.store.selectSnapshot(ConfigState.getApiUrl(apiName));
return this.http
.get<ApplicationConfigurationDto>(`${api}/api/abp/application-configuration`)
.pipe(
tap(configuration => this.configState.setState(configuration)),
catchError((err: HttpErrorResponse) => {
dispatch(new RestOccurError(err));
return throwError(err);
}),
);
return this.configState.refreshAppState().pipe(
catchError((err: HttpErrorResponse) => {
dispatch(new RestOccurError(err));
return throwError(err);
}),
);
}
@Action(SetEnvironment)

23
npm/ng-packs/packages/core/src/lib/strategies/auth-flow.strategy.ts

@ -13,7 +13,6 @@ import { from, Observable, of, pipe } from 'rxjs';
import { filter, switchMap, tap } from 'rxjs/operators';
import { RestOccurError } from '../actions/rest.actions';
import { LoginParams } from '../models/auth';
import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';
import { ConfigStateService } from '../services/config-state.service';
import { EnvironmentService } from '../services/environment.service';
import { SessionStateService } from '../services/session-state.service';
@ -32,7 +31,6 @@ export abstract class AuthFlowStrategy {
protected oAuthService: OAuthService;
protected oAuthConfig: AuthConfig;
protected sessionState: SessionStateService;
protected appConfigService: AbpApplicationConfigurationService;
protected tenantKey: string;
abstract checkIfInternalAuth(queryParams?: Params): boolean;
@ -47,7 +45,6 @@ export abstract class AuthFlowStrategy {
this.environment = injector.get(EnvironmentService);
this.configState = injector.get(ConfigStateService);
this.oAuthService = injector.get(OAuthService);
this.appConfigService = injector.get(AbpApplicationConfigurationService);
this.sessionState = injector.get(SessionStateService);
this.oAuthConfig = this.environment.getEnvironment().oAuthConfig;
this.tenantKey = injector.get(TENANT_KEY);
@ -84,11 +81,9 @@ export abstract class AuthFlowStrategy {
.pipe(
filter(event => event instanceof OAuthErrorEvent),
tap(() => clearOAuthStorage()),
switchMap(() => this.appConfigService.get()),
switchMap(() => this.configState.refreshAppState()),
)
.subscribe(res => {
this.configState.setState(res);
});
.subscribe();
}
}
@ -148,9 +143,7 @@ export class AuthPasswordFlowStrategy extends AuthFlowStrategy {
} else {
this.oAuthService.logOut();
removeRememberMe();
this.appConfigService.get().subscribe(res => {
this.configState.setState(res);
});
this.configState.refreshAppState().subscribe();
}
});
}
@ -188,9 +181,8 @@ export class AuthPasswordFlowStrategy extends AuthFlowStrategy {
const router = this.injector.get(Router);
return pipe(
switchMap(() => this.appConfigService.get()),
tap(res => {
this.configState.setState(res);
switchMap(() => this.configState.refreshAppState()),
tap(() => {
setRememberMe(params.rememberMe);
if (params.redirectUrl) router.navigate([params.redirectUrl]);
}),
@ -201,9 +193,8 @@ export class AuthPasswordFlowStrategy extends AuthFlowStrategy {
const router = this.injector.get(Router);
return from(this.oAuthService.revokeTokenAndLogout(queryParams)).pipe(
switchMap(() => this.appConfigService.get()),
tap(res => {
this.configState.setState(res);
switchMap(() => this.configState.refreshAppState()),
tap(() => {
router.navigateByUrl('/');
removeRememberMe();
}),

7
npm/ng-packs/packages/core/src/lib/utils/auth-utils.ts

@ -4,7 +4,6 @@ import { OAuthStorage, TokenResponse } from 'angular-oauth2-oidc';
import { pipe } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';
import { LoginParams } from '../models/auth';
import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';
import { ConfigStateService } from '../services/config-state.service';
const cookieKey = 'rememberMe';
@ -15,13 +14,11 @@ export function pipeToLogin(
injector: Injector,
) {
const configState = injector.get(ConfigStateService);
const appConfigService = injector.get(AbpApplicationConfigurationService);
const router = injector.get(Router);
return pipe(
switchMap(() => appConfigService.get()),
tap(res => {
configState.setState(res);
switchMap(() => configState.refreshAppState()),
tap(() => {
setRememberMe(params.rememberMe);
if (params.redirectUrl) router.navigate([params.redirectUrl]);
}),

7
npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts

@ -5,7 +5,6 @@ import { tap, catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';
import { ABP } from '../models/common';
import { Environment } from '../models/environment';
import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service';
import { CurrentTenantDto } from '../proxy/volo/abp/asp-net-core/mvc/multi-tenancy/models';
import { AuthService } from '../services/auth.service';
import { ConfigStateService } from '../services/config-state.service';
@ -21,7 +20,6 @@ export function getInitialData(injector: Injector) {
const fn = async () => {
const environmentService = injector.get(EnvironmentService);
const configState = injector.get(ConfigStateService);
const appConfigService = injector.get(AbpApplicationConfigurationService);
const options = injector.get(CORE_OPTIONS) as ABP.Root;
environmentService.setState(options.environment as Environment);
@ -31,10 +29,9 @@ export function getInitialData(injector: Injector) {
if (options.skipGetAppConfiguration) return;
return appConfigService
.get()
return configState
.refreshAppState()
.pipe(
tap(res => configState.setState(res)),
tap(() => checkAccessToken(injector)),
tap(() => {
const currentTenant = configState.getOne('currentTenant') as CurrentTenantDto;

17
npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts

@ -1,12 +1,8 @@
import {
AbpApplicationConfigurationService,
ConfigStateService,
TrackByService,
} from '@abp/ng.core';
import { ConfigStateService, TrackByService } from '@abp/ng.core';
import { LocaleDirection } from '@abp/ng.theme.shared';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Store } from '@ngxs/store';
import { finalize, tap } from 'rxjs/operators';
import { finalize } from 'rxjs/operators';
import { FeatureManagement } from '../../models/feature-management';
import { FeaturesService } from '../../proxy/feature-management/features.service';
import {
@ -29,7 +25,8 @@ enum ValueTypes {
export class FeatureManagementComponent
implements
FeatureManagement.FeatureManagementComponentInputs,
FeatureManagement.FeatureManagementComponentOutputs {
FeatureManagement.FeatureManagementComponentOutputs
{
@Input()
providerKey: string;
@ -70,7 +67,6 @@ export class FeatureManagementComponent
protected service: FeaturesService,
protected store: Store,
protected configState: ConfigStateService,
protected appConfigService: AbpApplicationConfigurationService,
) {}
openModal() {
@ -122,10 +118,7 @@ export class FeatureManagementComponent
if (!this.providerKey) {
// to refresh host's features
this.appConfigService
.get()
.pipe(tap(res => this.configState.setState(res)))
.subscribe();
this.configState.refreshAppState().subscribe();
}
});
}

23
npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts

@ -1,8 +1,4 @@
import {
AbpApplicationConfigurationService,
ConfigStateService,
CurrentUserDto,
} from '@abp/ng.core';
import { ConfigStateService, CurrentUserDto } from '@abp/ng.core';
import { LocaleDirection } from '@abp/ng.theme.shared';
import { Component, EventEmitter, Input, Output, TrackByFunction } from '@angular/core';
import { Select, Store } from '@ngxs/store';
@ -39,7 +35,8 @@ type PermissionWithStyle = PermissionGrantInfoDto & {
export class PermissionManagementComponent
implements
PermissionManagement.PermissionManagementComponentInputs,
PermissionManagement.PermissionManagementComponentOutputs {
PermissionManagement.PermissionManagementComponentOutputs
{
@Input()
readonly providerName: string;
@ -105,21 +102,17 @@ export class PermissionManagementComponent
map<PermissionGrantInfoDto[], PermissionWithStyle[]>(permissions =>
permissions.map(
permission =>
(({
({
...permission,
style: { [margin]: findMargin(permissions, permission) },
isGranted: this.permissions.find(per => per.name === permission.name).isGranted,
} as any) as PermissionWithStyle),
} as any as PermissionWithStyle),
),
),
);
}
constructor(
protected store: Store,
protected configState: ConfigStateService,
protected appConfigService: AbpApplicationConfigurationService,
) {}
constructor(protected store: Store, protected configState: ConfigStateService) {}
getChecked(name: string) {
return (this.permissions.find(per => per.name === name) || { isGranted: false }).isGranted;
@ -253,9 +246,7 @@ export class PermissionManagementComponent
)
.pipe(
switchMap(() =>
this.shouldFetchAppConfig()
? this.appConfigService.get().pipe(tap(res => this.configState.setState(res)))
: of(null),
this.shouldFetchAppConfig() ? this.configState.refreshAppState() : of(null),
),
finalize(() => (this.modalBusy = false)),
)

Loading…
Cancel
Save