Browse Source

Merge pull request #2267 from abpframework/feat/policy-condition

feat(core): add condition check to getGrantedPolicy
pull/2272/head
Yasin Aydın 7 years ago
committed by GitHub
parent
commit
04623304d9
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      npm/ng-packs/packages/core/src/lib/pipes/sort.pipe.ts
  2. 99
      npm/ng-packs/packages/core/src/lib/states/config.state.ts
  3. 138
      npm/ng-packs/packages/core/src/lib/tests/config.state.spec.ts
  4. 24
      npm/ng-packs/packages/core/src/lib/tests/sort.pipe.spec.ts

20
npm/ng-packs/packages/core/src/lib/pipes/sort.pipe.ts

@ -5,7 +5,11 @@ export type SortOrder = 'asc' | 'desc';
name: 'abpSort', name: 'abpSort',
}) })
export class SortPipe implements PipeTransform { export class SortPipe implements PipeTransform {
transform(value: any[], sortOrder: SortOrder | string = 'asc', sortKey?: string): any { transform(
value: any[],
sortOrder: SortOrder | string = 'asc',
sortKey?: string,
): any {
sortOrder = sortOrder && (sortOrder.toLowerCase() as any); sortOrder = sortOrder && (sortOrder.toLowerCase() as any);
if (!value || (sortOrder !== 'asc' && sortOrder !== 'desc')) return value; if (!value || (sortOrder !== 'asc' && sortOrder !== 'desc')) return value;
@ -17,7 +21,9 @@ export class SortPipe implements PipeTransform {
numberArray = value.filter(item => typeof item === 'number').sort(); numberArray = value.filter(item => typeof item === 'number').sort();
stringArray = value.filter(item => typeof item === 'string').sort(); stringArray = value.filter(item => typeof item === 'string').sort();
} else { } else {
numberArray = value.filter(item => typeof item[sortKey] === 'number').sort((a, b) => a[sortKey] - b[sortKey]); numberArray = value
.filter(item => typeof item[sortKey] === 'number')
.sort((a, b) => a[sortKey] - b[sortKey]);
stringArray = value stringArray = value
.filter(item => typeof item[sortKey] === 'string') .filter(item => typeof item[sortKey] === 'string')
.sort((a, b) => { .sort((a, b) => {
@ -26,7 +32,15 @@ export class SortPipe implements PipeTransform {
else return 0; else return 0;
}); });
} }
const sorted = numberArray.concat(stringArray); const sorted = [
...numberArray,
...stringArray,
...value.filter(
item =>
typeof (sortKey ? item[sortKey] : item) !== 'number' &&
typeof (sortKey ? item[sortKey] : item) !== 'string',
),
];
return sortOrder === 'asc' ? sorted : sorted.reverse(); return sortOrder === 'asc' ? sorted : sorted.reverse();
} }
} }

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

@ -1,8 +1,18 @@
import { Action, createSelector, Selector, State, StateContext, Store } from '@ngxs/store'; import {
Action,
createSelector,
Selector,
State,
StateContext,
Store,
} from '@ngxs/store';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators'; import { switchMap, tap } from 'rxjs/operators';
import snq from 'snq'; import snq from 'snq';
import { GetAppConfiguration, PatchRouteByName } from '../actions/config.actions'; import {
GetAppConfiguration,
PatchRouteByName,
} from '../actions/config.actions';
import { SetLanguage } from '../actions/session.actions'; import { SetLanguage } from '../actions/session.actions';
import { ABP } from '../models/common'; import { ABP } from '../models/common';
import { Config } from '../models/config'; import { Config } from '../models/config';
@ -73,9 +83,12 @@ export class ConfigState {
} }
static getApiUrl(key?: string) { static getApiUrl(key?: string) {
const selector = createSelector([ConfigState], (state: Config.State): string => { const selector = createSelector(
return state.environment.apis[key || 'default'].url; [ConfigState],
}); (state: Config.State): string => {
return state.environment.apis[key || 'default'].url;
},
);
return selector; return selector;
} }
@ -90,10 +103,19 @@ export class ConfigState {
static getSettings(keyword?: string) { static getSettings(keyword?: string) {
const selector = createSelector([ConfigState], (state: Config.State) => { const selector = createSelector([ConfigState], (state: Config.State) => {
if (keyword) { if (keyword) {
const keys = snq(() => Object.keys(state.setting.values).filter(key => key.indexOf(keyword) > -1), []); const keys = snq(
() =>
Object.keys(state.setting.values).filter(
key => key.indexOf(keyword) > -1,
),
[],
);
if (keys.length) { if (keys.length) {
return keys.reduce((acc, key) => ({ ...acc, [key]: state.setting.values[key] }), {}); return keys.reduce(
(acc, key) => ({ ...acc, [key]: state.setting.values[key] }),
{},
);
} }
} }
@ -103,15 +125,40 @@ export class ConfigState {
} }
static getGrantedPolicy(key: string) { static getGrantedPolicy(key: string) {
const selector = createSelector([ConfigState], (state: Config.State): boolean => { const selector = createSelector(
if (!key) return true; [ConfigState],
return snq(() => state.auth.grantedPolicies[key], false); (state: Config.State): boolean => {
}); if (!key) return true;
const getPolicy = k => snq(() => state.auth.grantedPolicies[k], false);
const orRegexp = /\|\|/g;
const andRegexp = /&&/g;
if (orRegexp.test(key)) {
const keys = key.split('||').filter(k => !!k);
if (keys.length !== 2) return false;
return getPolicy(keys[0].trim()) || getPolicy(keys[1].trim());
} else if (andRegexp.test(key)) {
const keys = key.split('&&').filter(k => !!k);
if (keys.length !== 2) return false;
return getPolicy(keys[0].trim()) && getPolicy(keys[1].trim());
}
return getPolicy(key);
},
);
return selector; return selector;
} }
static getLocalization(key: string | Config.LocalizationWithDefault, ...interpolateParams: string[]) { static getLocalization(
key: string | Config.LocalizationWithDefault,
...interpolateParams: string[]
) {
let defaultValue: string; let defaultValue: string;
if (typeof key !== 'string') { if (typeof key !== 'string') {
@ -164,7 +211,10 @@ export class ConfigState {
return selector; return selector;
} }
constructor(private appConfigurationService: ApplicationConfigurationService, private store: Store) {} constructor(
private appConfigurationService: ApplicationConfigurationService,
private store: Store,
) {}
@Action(GetAppConfiguration) @Action(GetAppConfiguration)
addData({ patchState, dispatch }: StateContext<Config.State>) { addData({ patchState, dispatch }: StateContext<Config.State>) {
@ -175,19 +225,25 @@ export class ConfigState {
}), }),
), ),
switchMap(configuration => { switchMap(configuration => {
let defaultLang: string = configuration.setting.values['Abp.Localization.DefaultLanguage']; let defaultLang: string =
configuration.setting.values['Abp.Localization.DefaultLanguage'];
if (defaultLang.includes(';')) { if (defaultLang.includes(';')) {
defaultLang = defaultLang.split(';')[0]; defaultLang = defaultLang.split(';')[0];
} }
return this.store.selectSnapshot(SessionState.getLanguage) ? of(null) : dispatch(new SetLanguage(defaultLang)); return this.store.selectSnapshot(SessionState.getLanguage)
? of(null)
: dispatch(new SetLanguage(defaultLang));
}), }),
); );
} }
@Action(PatchRouteByName) @Action(PatchRouteByName)
patchRoute({ patchState, getState }: StateContext<Config.State>, { name, newValue }: PatchRouteByName) { patchRoute(
{ patchState, getState }: StateContext<Config.State>,
{ name, newValue }: PatchRouteByName,
) {
let routes: ABP.FullRoute[] = getState().routes; let routes: ABP.FullRoute[] = getState().routes;
const index = routes.findIndex(route => route.name === name); const index = routes.findIndex(route => route.name === name);
@ -208,7 +264,9 @@ function patchRouteDeep(
): ABP.FullRoute[] { ): ABP.FullRoute[] {
routes = routes.map(route => { routes = routes.map(route => {
if (route.name === name) { if (route.name === name) {
newValue.url = `${parentUrl}/${(!newValue.path && newValue.path === '' ? route.path : newValue.path) || ''}`; newValue.url = `${parentUrl}/${(!newValue.path && newValue.path === ''
? route.path
: newValue.path) || ''}`;
if (newValue.children && newValue.children.length) { if (newValue.children && newValue.children.length) {
newValue.children = newValue.children.map(child => ({ newValue.children = newValue.children.map(child => ({
@ -219,7 +277,12 @@ function patchRouteDeep(
return { ...route, ...newValue }; return { ...route, ...newValue };
} else if (route.children && route.children.length) { } else if (route.children && route.children.length) {
route.children = patchRouteDeep(route.children, name, newValue, (parentUrl || '/') + route.path); route.children = patchRouteDeep(
route.children,
name,
newValue,
(parentUrl || '/') + route.path,
);
} }
return route; return route;

138
npm/ng-packs/packages/core/src/lib/tests/config.state.spec.ts

@ -1,8 +1,15 @@
import { createServiceFactory, SpectatorService, SpyObject } from '@ngneat/spectator/jest'; import {
createServiceFactory,
SpectatorService,
SpyObject,
} from '@ngneat/spectator/jest';
import { Store } from '@ngxs/store'; import { Store } from '@ngxs/store';
import { ReplaySubject, timer, Subject, of } from 'rxjs'; import { ReplaySubject, timer, Subject, of } from 'rxjs';
import { Config } from '../models/config'; import { Config } from '../models/config';
import { ApplicationConfigurationService, ConfigStateService } from '../services'; import {
ApplicationConfigurationService,
ConfigStateService,
} from '../services';
import { ConfigState } from '../states'; import { ConfigState } from '../states';
import { SetLanguage, PatchRouteByName } from '../actions'; import { SetLanguage, PatchRouteByName } from '../actions';
@ -91,6 +98,7 @@ export const CONFIG_STATE_DATA = {
}, },
grantedPolicies: { grantedPolicies: {
'Abp.Identity': false, 'Abp.Identity': false,
'Abp.Account': true,
}, },
}, },
setting: { setting: {
@ -126,7 +134,10 @@ describe('ConfigState', () => {
store = spectator.get(Store); store = spectator.get(Store);
service = spectator.service; service = spectator.service;
appConfigService = spectator.get(ApplicationConfigurationService); appConfigService = spectator.get(ApplicationConfigurationService);
state = new ConfigState(spectator.get(ApplicationConfigurationService), store); state = new ConfigState(
spectator.get(ApplicationConfigurationService),
store,
);
}); });
describe('#getAll', () => { describe('#getAll', () => {
@ -137,24 +148,34 @@ describe('ConfigState', () => {
describe('#getApplicationInfo', () => { describe('#getApplicationInfo', () => {
it('should return application property', () => { it('should return application property', () => {
expect(ConfigState.getApplicationInfo(CONFIG_STATE_DATA)).toEqual(CONFIG_STATE_DATA.environment.application); expect(ConfigState.getApplicationInfo(CONFIG_STATE_DATA)).toEqual(
CONFIG_STATE_DATA.environment.application,
);
}); });
}); });
describe('#getOne', () => { describe('#getOne', () => {
it('should return one property', () => { it('should return one property', () => {
expect(ConfigState.getOne('environment')(CONFIG_STATE_DATA)).toEqual(CONFIG_STATE_DATA.environment); expect(ConfigState.getOne('environment')(CONFIG_STATE_DATA)).toEqual(
CONFIG_STATE_DATA.environment,
);
}); });
}); });
describe('#getDeep', () => { describe('#getDeep', () => {
it('should return deeper', () => { it('should return deeper', () => {
expect(ConfigState.getDeep('environment.localization.defaultResourceName')(CONFIG_STATE_DATA)).toEqual( expect(
CONFIG_STATE_DATA.environment.localization.defaultResourceName, ConfigState.getDeep('environment.localization.defaultResourceName')(
); CONFIG_STATE_DATA,
expect(ConfigState.getDeep(['environment', 'localization', 'defaultResourceName'])(CONFIG_STATE_DATA)).toEqual( ),
CONFIG_STATE_DATA.environment.localization.defaultResourceName, ).toEqual(CONFIG_STATE_DATA.environment.localization.defaultResourceName);
); expect(
ConfigState.getDeep([
'environment',
'localization',
'defaultResourceName',
])(CONFIG_STATE_DATA),
).toEqual(CONFIG_STATE_DATA.environment.localization.defaultResourceName);
expect(ConfigState.getDeep('test')(null)).toBeFalsy(); expect(ConfigState.getDeep('test')(null)).toBeFalsy();
}); });
@ -162,21 +183,33 @@ describe('ConfigState', () => {
describe('#getRoute', () => { describe('#getRoute', () => {
it('should return route', () => { it('should return route', () => {
expect(ConfigState.getRoute(null, '::Menu:Home')(CONFIG_STATE_DATA)).toEqual(CONFIG_STATE_DATA.flattedRoutes[0]); expect(
expect(ConfigState.getRoute('identity')(CONFIG_STATE_DATA)).toEqual(CONFIG_STATE_DATA.flattedRoutes[1]); ConfigState.getRoute(null, '::Menu:Home')(CONFIG_STATE_DATA),
).toEqual(CONFIG_STATE_DATA.flattedRoutes[0]);
expect(ConfigState.getRoute('identity')(CONFIG_STATE_DATA)).toEqual(
CONFIG_STATE_DATA.flattedRoutes[1],
);
}); });
}); });
describe('#getApiUrl', () => { describe('#getApiUrl', () => {
it('should return api url', () => { it('should return api url', () => {
expect(ConfigState.getApiUrl('other')(CONFIG_STATE_DATA)).toEqual(CONFIG_STATE_DATA.environment.apis.other.url); expect(ConfigState.getApiUrl('other')(CONFIG_STATE_DATA)).toEqual(
expect(ConfigState.getApiUrl()(CONFIG_STATE_DATA)).toEqual(CONFIG_STATE_DATA.environment.apis.default.url); CONFIG_STATE_DATA.environment.apis.other.url,
);
expect(ConfigState.getApiUrl()(CONFIG_STATE_DATA)).toEqual(
CONFIG_STATE_DATA.environment.apis.default.url,
);
}); });
}); });
describe('#getSetting', () => { describe('#getSetting', () => {
it('should return a setting', () => { it('should return a setting', () => {
expect(ConfigState.getSetting('Abp.Localization.DefaultLanguage')(CONFIG_STATE_DATA)).toEqual( expect(
ConfigState.getSetting('Abp.Localization.DefaultLanguage')(
CONFIG_STATE_DATA,
),
).toEqual(
CONFIG_STATE_DATA.setting.values['Abp.Localization.DefaultLanguage'], CONFIG_STATE_DATA.setting.values['Abp.Localization.DefaultLanguage'],
); );
}); });
@ -184,41 +217,82 @@ describe('ConfigState', () => {
describe('#getSettings', () => { describe('#getSettings', () => {
it('should return settings', () => { it('should return settings', () => {
expect(ConfigState.getSettings('Localization')(CONFIG_STATE_DATA)).toEqual({ expect(
ConfigState.getSettings('Localization')(CONFIG_STATE_DATA),
).toEqual({
'Abp.Localization.DefaultLanguage': 'en', 'Abp.Localization.DefaultLanguage': 'en',
}); });
expect(ConfigState.getSettings('AllSettings')(CONFIG_STATE_DATA)).toEqual(CONFIG_STATE_DATA.setting.values); expect(ConfigState.getSettings('AllSettings')(CONFIG_STATE_DATA)).toEqual(
CONFIG_STATE_DATA.setting.values,
);
}); });
}); });
describe('#getGrantedPolicy', () => { describe('#getGrantedPolicy', () => {
it('should return a granted policy', () => { it('should return a granted policy', () => {
expect(ConfigState.getGrantedPolicy('Abp.Identity')(CONFIG_STATE_DATA)).toBe(false); expect(
ConfigState.getGrantedPolicy('Abp.Identity')(CONFIG_STATE_DATA),
).toBe(false);
expect(
ConfigState.getGrantedPolicy('Abp.Identity || Abp.Account')(
CONFIG_STATE_DATA,
),
).toBe(true);
expect(
ConfigState.getGrantedPolicy('Abp.Account && Abp.Identity')(
CONFIG_STATE_DATA,
),
).toBe(false);
expect(
ConfigState.getGrantedPolicy('Abp.Account &&')(CONFIG_STATE_DATA),
).toBe(false);
expect(
ConfigState.getGrantedPolicy('|| Abp.Account')(CONFIG_STATE_DATA),
).toBe(false);
expect(ConfigState.getGrantedPolicy('')(CONFIG_STATE_DATA)).toBe(true); expect(ConfigState.getGrantedPolicy('')(CONFIG_STATE_DATA)).toBe(true);
}); });
}); });
describe('#getLocalization', () => { describe('#getLocalization', () => {
it('should return a localization', () => { it('should return a localization', () => {
expect(ConfigState.getLocalization('AbpIdentity::Identity')(CONFIG_STATE_DATA)).toBe('identity'); expect(
ConfigState.getLocalization('AbpIdentity::Identity')(CONFIG_STATE_DATA),
expect(ConfigState.getLocalization('AbpIdentity::NoIdentity')(CONFIG_STATE_DATA)).toBe('AbpIdentity::NoIdentity'); ).toBe('identity');
expect(ConfigState.getLocalization({ key: '', defaultValue: 'default' })(CONFIG_STATE_DATA)).toBe('default'); expect(
ConfigState.getLocalization('AbpIdentity::NoIdentity')(
expect(ConfigState.getLocalization("::'{0}' and '{1}' do not match.", 'first', 'second')(CONFIG_STATE_DATA)).toBe( CONFIG_STATE_DATA,
'first and second do not match.', ),
); ).toBe('AbpIdentity::NoIdentity');
expect(
ConfigState.getLocalization({ key: '', defaultValue: 'default' })(
CONFIG_STATE_DATA,
),
).toBe('default');
expect(
ConfigState.getLocalization(
"::'{0}' and '{1}' do not match.",
'first',
'second',
)(CONFIG_STATE_DATA),
).toBe('first and second do not match.');
try { try {
ConfigState.getLocalization('::Test')({ ConfigState.getLocalization('::Test')({
...CONFIG_STATE_DATA, ...CONFIG_STATE_DATA,
environment: { ...CONFIG_STATE_DATA.environment, localization: {} as any }, environment: {
...CONFIG_STATE_DATA.environment,
localization: {} as any,
},
}); });
expect(false).toBeTruthy(); // fail expect(false).toBeTruthy(); // fail
} catch (error) { } catch (error) {
expect((error as Error).message).toContain('Please check your environment'); expect((error as Error).message).toContain(
'Please check your environment',
);
} }
}); });
}); });
@ -273,7 +347,9 @@ describe('ConfigState', () => {
name: 'Home', name: 'Home',
path: 'home', path: 'home',
url: '/home', url: '/home',
children: [{ path: 'dashboard', name: 'Dashboard', url: '/home/dashboard' }], children: [
{ path: 'dashboard', name: 'Dashboard', url: '/home/dashboard' },
],
}); });
}); });

24
npm/ng-packs/packages/core/src/lib/tests/sort.pipe.spec.ts

@ -17,10 +17,28 @@ describe('SortPipe', () => {
}); });
test('should sort object array in given order with given key', () => { test('should sort object array in given order with given key', () => {
const array = [{ key: 5 }, { key: 'b' }, { key: 1 }, { key: 'a' }]; const array = [
{ key: 5 },
{ key: 'b' },
{ key: 1 },
{ key: 'a' },
{ key: null },
];
expect(pipe.transform(array, 'asc', 'key')).toEqual([{ key: 1 }, { key: 5 }, { key: 'a' }, { key: 'b' }]); expect(pipe.transform(array, 'asc', 'key')).toEqual([
expect(pipe.transform(array, 'desc', 'key')).toEqual([{ key: 'b' }, { key: 'a' }, { key: 5 }, { key: 1 }]); { key: 1 },
{ key: 5 },
{ key: 'a' },
{ key: 'b' },
{ key: null },
]);
expect(pipe.transform(array, 'desc', 'key')).toEqual([
{ key: null },
{ key: 'b' },
{ key: 'a' },
{ key: 5 },
{ key: 1 },
]);
}); });
test('should require an array as value', () => { test('should require an array as value', () => {

Loading…
Cancel
Save