Skip to content

Commit

Permalink
Fixed merge conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
rmathis committed Sep 10, 2019
2 parents ce2b648 + 965054d commit b9507b2
Show file tree
Hide file tree
Showing 16 changed files with 198 additions and 13 deletions.
2 changes: 2 additions & 0 deletions backend/src/main/resources/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,8 @@ message.no-filters-added=No filters have been added to this Metadata Provider
message.create-new-version-from-version=Create New Version from Previous Settings
message.restoring-this-version-will-copy=Restoring this version will copy the Version ({ date }) configuration and create a new Version from the selected version settings. You can then edit the configuration before saving the new version.

message.invalid-regex-pattern=Invalid Regular Expression

tooltip.entity-id=Entity ID
tooltip.service-provider-name=Service Provider Name (Dashboard Display Only)
tooltip.force-authn=Disallows use (or reuse) of authentication results and login flows that don\u0027t provide a real-time proof of user presence in the login process
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@
</div>
</ng-container>
</div>
<ng-container *ngFor="let version of property.value">
<div *ngIf="version && version[i]"
[ngbPopover]="version[i][prop]"
triggers="mouseenter:mouseleave"
container="body"
[ngStyle]="{'width': width}"
class="text-truncate"
popoverClass="popover-lg popover-info">
{{ version[i][prop] }}
</div>
<div *ngIf="!version || !version[i]" [ngStyle]="{'width': width}">
-
</div>
</ng-container>
</div>
</div>
<ng-container *ngIf="property.items.type === 'string'" [ngSwitch]="getItemType(property)">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ describe('EntityAttributesFilter Entity', () => {
expect(entity.resourceId).toBe('foo');
expect(entity.enabled).toBe(entity.filterEnabled);
expect(entity.id).toBe(entity.resourceId);
expect(entity.getId()).toBe(entity.entityId);
expect(entity.getDisplayId()).toBe(entity.entityId);
expect(entity.getId()).toBe(entity.resourceId);
expect(entity.getDisplayId()).toBe(entity.resourceId);
expect(entity.isDraft()).toBe(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ export class EntityAttributesFilterEntity implements MetadataFilter, MetadataEnt
}

getId(): string {
return this.entityId;
return this.resourceId;
}

getDisplayId(): string {
return this.entityId;
return this.resourceId;
}

isDraft(): boolean {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { NameIDFormatFilterEntity } from './nameid-format-filter';

describe('NameIDFormatFilterEntity Entity', () => {
let entity: NameIDFormatFilterEntity;
beforeEach(() => {
entity = new NameIDFormatFilterEntity({
resourceId: 'foo',
filterEnabled: false
});
});

it('should be an instance', () => {
expect(entity).toBeDefined();
expect(entity.resourceId).toBe('foo');
expect(entity.enabled).toBe(entity.filterEnabled);
expect(entity.id).toBe(entity.resourceId);
expect(entity.getId()).toBe(entity.resourceId);
expect(entity.getDisplayId()).toBe(entity.resourceId);
expect(entity.isDraft()).toBe(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ describe('Entity Attributes filter form', () => {
it('should return an empty object for validators', () => {
expect(Object.keys(EntityAttributesFilter.getValidators())).toEqual([
'/',
'/name'
'/name',
'/entityAttributesFilterTarget'
]);
});

Expand Down
16 changes: 16 additions & 0 deletions ui/src/app/metadata/filter/model/entity-attributes.filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { FormDefinition } from '../../../wizard/model';
import { MetadataFilter } from '../../domain/model';
import { removeNulls } from '../../../shared/util';
import { EntityAttributesFilterEntity } from '../../domain/entity';
import { RegexValidator } from '../../../shared/validation/regex.validator';
import { getFilterNames } from '../reducer';
import { memoize } from '../../../shared/memo';

const checkRegex = memoize(RegexValidator.isValidRegex);

export const EntityAttributesFilter: FormDefinition<MetadataFilter> = {
label: 'EntityAttributes',
Expand Down Expand Up @@ -37,6 +41,18 @@ export const EntityAttributesFilter: FormDefinition<MetadataFilter> = {
params: [value]
} : null;
return err;
},
'/entityAttributesFilterTarget': (value, property, form) => {
if (!form || !form.value || !form.value.entityAttributesFilterTarget ||
form.value.entityAttributesFilterTarget.entityAttributesFilterTargetType !== 'REGEX') {
return null;
}
return checkRegex(value.value[0]) ? null : {
code: 'INVALID_REGEX',
path: `#${property.path}`,
message: 'message.invalid-regex-pattern',
params: [value.value[0]]
};
}
};
return validators;
Expand Down
3 changes: 2 additions & 1 deletion ui/src/app/metadata/filter/model/nameid.filter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ describe('NameID Format filter form', () => {
it('should return an empty object for validators', () => {
expect(Object.keys(NameIDFilter.getValidators())).toEqual([
'/',
'/name'
'/name',
'/nameIdFormatFilterTarget'
]);
});

Expand Down
16 changes: 16 additions & 0 deletions ui/src/app/metadata/filter/model/nameid.filter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { FormDefinition } from '../../../wizard/model';
import { MetadataFilter } from '../../domain/model';
import { NameIDFormatFilterEntity } from '../../domain/entity/filter/nameid-format-filter';
import { RegexValidator } from '../../../shared/validation/regex.validator';
import { getFilterNames } from '../reducer';
import { memoize } from '../../../shared/memo';

const checkRegex = memoize(RegexValidator.isValidRegex);

export const NameIDFilter: FormDefinition<MetadataFilter> = {
label: 'NameIDFormat',
Expand Down Expand Up @@ -36,6 +40,18 @@ export const NameIDFilter: FormDefinition<MetadataFilter> = {
params: [value]
} : null;
return err;
},
'/nameIdFormatFilterTarget': (value, property, form) => {
if (!form || !form.value || !form.value.nameIdFormatFilterTarget ||
form.value.nameIdFormatFilterTarget.nameIdFormatFilterTargetType !== 'REGEX') {
return null;
}
return checkRegex(value.value[0]) ? null : {
code: 'INVALID_REGEX',
path: `#${property.path}`,
message: 'message.invalid-regex-pattern',
params: [value.value[0]]
};
}
};
return validators;
Expand Down
4 changes: 2 additions & 2 deletions ui/src/app/schema-form/widget/array/array.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ export interface FormError {
code: string;
description: string;
message: string;
params: any[];
params?: any[];
path: string;
schemaId: any;
schemaId?: any;
}

@Component({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,21 @@
</small>
</ng-container>
<ng-container *ngSwitchCase="'REGEX'">
<input [id]="formProperty._canonicalPath + '.target'" class="form-control" type="text" [formControl]="script" name="script" />
<small id="regex-help" class="form-text text-secondary">
<input [id]="formProperty._canonicalPath + '.target'"
class="form-control"
type="text"
[formControl]="script"
name="script" />
<small id="regex-help" class="form-text text-secondary" *ngIf="!(hasErrors$ | async)">
<translate-i18n key="message.required-for-regex">Required for Regex</translate-i18n>
&nbsp;
</small>
<small class="form-text text-danger px-2" *ngIf="hasErrors$ | async">
<ng-container *ngFor="let error of errors$ | async; let first=first;">
<ng-container *ngIf="!first">, </ng-container>
<translate-i18n [key]="error.message">{{ error.message }}</translate-i18n>
</ng-container>
</small>
</ng-container>
</div>
<div class="ml-2" *ngIf="targetType === 'ENTITY'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Component, OnDestroy, AfterViewInit } from '@angular/core';
import { FormControl, Validators, AbstractControl, ValidatorFn } from '@angular/forms';
import { ObjectWidget } from 'ngx-schema-form';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { distinctUntilChanged, skipWhile, map } from 'rxjs/operators';
import { Observable, Subject } from 'rxjs';
import { distinctUntilChanged, skipWhile, takeUntil, map } from 'rxjs/operators';

import * as fromRoot from '../../../app.reducer';
import * as fromFilters from '../../../metadata/filter/reducer';
Expand All @@ -17,7 +17,7 @@ import { QueryEntityIds, ClearSearch } from '../../../metadata/filter/action/sea
styleUrls: ['./filter-target.component.scss']
})
export class FilterTargetComponent extends ObjectWidget implements OnDestroy, AfterViewInit {

private ngUnsubscribe: Subject<null> = new Subject<null>();
ids$: Observable<string[]>;
ids: string[];

Expand All @@ -32,6 +32,9 @@ export class FilterTargetComponent extends ObjectWidget implements OnDestroy, Af
[Validators.required]
);

errors$: Observable<any[]>;
hasErrors$: Observable<boolean>;

constructor(
private store: Store<fromRoot.State>
) {
Expand All @@ -42,13 +45,15 @@ export class FilterTargetComponent extends ObjectWidget implements OnDestroy, Af
this.search
.valueChanges
.pipe(
takeUntil(this.ngUnsubscribe),
distinctUntilChanged()
)
.subscribe(query => this.searchEntityIds(query));

this.script
.valueChanges
.pipe(
takeUntil(this.ngUnsubscribe),
distinctUntilChanged(),
skipWhile(() => this.targetType === 'ENTITY')
)
Expand All @@ -61,6 +66,31 @@ export class FilterTargetComponent extends ObjectWidget implements OnDestroy, Af
super.ngAfterViewInit();
this.script.setValue(this.targets[0]);
this.search.setValidators(this.unique());

this.errors$ = this.formProperty.errorsChanges.pipe(
map(errors =>
errors && errors.length > 1 ?
Array
.from(new Set(errors.filter(e => e.code !== 'ARRAY_LENGTH_SHORT').map(e => e.code)))
.map(id => ({ ...errors.find(e => e.code === id) }))
: []
));

this.errors$
.pipe(
takeUntil(this.ngUnsubscribe),
map(errors => errors.reduce((collection, e) => ({ ...collection, [e.code]: e.message }), {})),
map(errors => Object.keys(errors).length > 0 ? errors : null)
)
.subscribe(errors => this.script.setErrors(
errors,
{
emitEvent: true
}
)
);

this.hasErrors$ = this.errors$.pipe(map(e => e && e.length > 0));
}

unique(): ValidatorFn {
Expand Down Expand Up @@ -138,5 +168,7 @@ export class FilterTargetComponent extends ObjectWidget implements OnDestroy, Af

ngOnDestroy(): void {
this.store.dispatch(new ClearSearch());
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
}
21 changes: 21 additions & 0 deletions ui/src/app/shared/memo.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { memoize } from './memo';

const fns = {
square(n) {
return n * n;
}
};

describe('memoize function', () => {
it('should return a memoized function', () => {
spyOn(fns, 'square').and.callThrough();
const memoized = memoize(fns.square);
const call1 = memoized(1);
const call2 = memoized(2);
const call3 = memoized(2);
expect(call1).toBe(1);
expect(call2).toBe(4);
expect(call3).toBe(4);
expect(fns.square).toHaveBeenCalledTimes(2);
});
});
15 changes: 15 additions & 0 deletions ui/src/app/shared/memo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export function memoize(func) {
const cache = {};
return function (...args: any[]) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
} else {
const val = func.apply(null, args);
cache[key] = val;
return val;
}
};
}

export default { memoize };
18 changes: 18 additions & 0 deletions ui/src/app/shared/validation/regex.validator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { RegexValidator } from './regex.validator';

describe('RegexValidator', () => {
describe('isValidRegex method', () => {
it('should return true if no error is thrown', () => {
expect(RegexValidator.isValidRegex('/abc/')).toBe(true);
expect(RegexValidator.isValidRegex('/*123/')).toBe(true);
});

it('should return false if an error is thrown trying to construct a regex', () => {
expect(RegexValidator.isValidRegex(')')).toBe(false);
});

it('should return false if the regex doesnt begin and end with slashes', () => {
expect(RegexValidator.isValidRegex('abc')).toBe(false);
});
});
});
18 changes: 18 additions & 0 deletions ui/src/app/shared/validation/regex.validator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const regexChecker = new RegExp('^\/|\/$', 'g');

export class RegexValidator {
static isValidRegex(pattern: string): boolean {
if (!pattern) {
return true;
}
let regex;
try {
regex = new RegExp(pattern);
} catch (err) {
return false;
}
return regexChecker.test(pattern);
}
}

export default RegexValidator;

0 comments on commit b9507b2

Please sign in to comment.