Commit 9c5b353a17a21d3d392afc2e3b43d2849100cf8f
1 parent
fe00a9bd
UI: Added validation unique domain
Showing
3 changed files
with
60 additions
and
56 deletions
... | ... | @@ -59,30 +59,31 @@ |
59 | 59 | <section *ngFor="let domainInfo of clientDomainInfos(domain).controls; let n = index; trackBy: trackByParams" |
60 | 60 | class="domains-list"> |
61 | 61 | <div [formGroupName]="n" fxLayout="row" fxLayoutGap="8px"> |
62 | - <div fxLayout="row" fxLayout.xs="column" fxFlex fxLayoutGap="8px"> | |
63 | - <div fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px" fxFlex.gt-xs="50"> | |
64 | - <mat-form-field fxFlex="30" fxFlex.xs class="mat-block"> | |
65 | - <mat-label translate>admin.oauth2.protocol</mat-label> | |
66 | - <mat-select formControlName="scheme"> | |
67 | - <mat-option *ngFor="let protocol of protocols" [value]="protocol"> | |
68 | - {{ domainSchemaTranslations.get(protocol) | translate | uppercase }} | |
69 | - </mat-option> | |
70 | - </mat-select> | |
71 | - </mat-form-field> | |
72 | - | |
73 | - <mat-form-field fxFlex class="mat-block"> | |
74 | - <mat-label translate>admin.domain-name</mat-label> | |
75 | - <input matInput formControlName="name" required> | |
76 | - <mat-error *ngIf="domainInfo.get('name').hasError('pattern')"> | |
77 | - {{ 'admin.error-verification-url' | translate }} | |
78 | - </mat-error> | |
79 | - <mat-error *ngIf="domainInfo.get('name').hasError('unique')"> | |
80 | - {{ 'admin.domain-name-unique' | translate }} | |
81 | - </mat-error> | |
82 | - </mat-form-field> | |
62 | + <div fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px"> | |
63 | + <div fxLayout="column" fxFlex.sm="60" fxFlex.gt-sm="50"> | |
64 | + <div fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px"> | |
65 | + <mat-form-field fxFlex="30" fxFlex.xs class="mat-block"> | |
66 | + <mat-label translate>admin.oauth2.protocol</mat-label> | |
67 | + <mat-select formControlName="scheme"> | |
68 | + <mat-option *ngFor="let protocol of protocols" [value]="protocol"> | |
69 | + {{ domainSchemaTranslations.get(protocol) | translate | uppercase }} | |
70 | + </mat-option> | |
71 | + </mat-select> | |
72 | + </mat-form-field> | |
73 | + <mat-form-field fxFlex class="mat-block"> | |
74 | + <mat-label translate>admin.domain-name</mat-label> | |
75 | + <input matInput formControlName="name" required> | |
76 | + <mat-error *ngIf="domainInfo.get('name').hasError('pattern')"> | |
77 | + {{ 'admin.error-verification-url' | translate }} | |
78 | + </mat-error> | |
79 | + </mat-form-field> | |
80 | + </div> | |
81 | + <mat-error *ngIf="domainInfo.hasError('unique')"> | |
82 | + {{ 'admin.domain-name-unique' | translate }} | |
83 | + </mat-error> | |
83 | 84 | </div> |
84 | 85 | |
85 | - <div fxFlex> | |
86 | + <div fxFlex fxLayout="column"> | |
86 | 87 | <mat-form-field fxFlex class="mat-block"> |
87 | 88 | <mat-label translate>admin.oauth2.redirect-uri-template</mat-label> |
88 | 89 | <input matInput [value]="redirectURI(domainInfo)" readonly> |
... | ... | @@ -94,8 +95,7 @@ |
94 | 95 | </button> |
95 | 96 | </mat-form-field> |
96 | 97 | |
97 | - <mat-form-field fxFlex *ngIf="domainInfo.get('scheme').value === 'MIXED'" | |
98 | - class="mat-block"> | |
98 | + <mat-form-field fxFlex *ngIf="domainInfo.get('scheme').value === 'MIXED'" class="mat-block"> | |
99 | 99 | <mat-label></mat-label> |
100 | 100 | <input matInput [value]="redirectURIMixed(domainInfo)" readonly> |
101 | 101 | <button mat-icon-button color="primary" matSuffix type="button" |
... | ... | @@ -106,7 +106,6 @@ |
106 | 106 | </button> |
107 | 107 | </mat-form-field> |
108 | 108 | </div> |
109 | - | |
110 | 109 | </div> |
111 | 110 | |
112 | 111 | <div fxLayout="column" fxLayoutAlign="center start"> | ... | ... |
... | ... | @@ -178,13 +178,14 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha |
178 | 178 | } |
179 | 179 | } |
180 | 180 | |
181 | - private uniqueDomainValidator(control: AbstractControl): { [key: string]: boolean } | null { | |
182 | - if (control.parent?.parent?.value) { | |
183 | - const domain = control.value; | |
184 | - const listProtocols = control.parent.parent.value | |
181 | + private uniqueDomainValidator(control: FormGroup): { [key: string]: boolean } | null { | |
182 | + if (control.parent?.value) { | |
183 | + const domain = control.value.name; | |
184 | + const listProtocols = control.parent.getRawValue() | |
185 | 185 | .filter((domainInfo) => domainInfo.name === domain) |
186 | 186 | .map((domainInfo) => domainInfo.scheme); |
187 | - if (listProtocols.length > 1 && listProtocols.indexOf(DomainSchema.MIXED) > -1) { | |
187 | + if (listProtocols.length > 1 && listProtocols.indexOf(DomainSchema.MIXED) > -1 || | |
188 | + new Set(listProtocols).size !== listProtocols.length) { | |
188 | 189 | return {unique: true}; |
189 | 190 | } |
190 | 191 | } |
... | ... | @@ -228,10 +229,9 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha |
228 | 229 | const domain = this.fb.group({ |
229 | 230 | name: [domainInfo ? domainInfo.name : this.window.location.hostname, [ |
230 | 231 | Validators.required, |
231 | - Validators.pattern('((?![:/]).)*$'), | |
232 | - this.uniqueDomainValidator]], | |
232 | + Validators.pattern('((?![:/]).)*$')]], | |
233 | 233 | scheme: [domainInfo?.scheme ? domainInfo.scheme : DomainSchema.HTTPS, Validators.required] |
234 | - }); | |
234 | + }, {validators: this.uniqueDomainValidator}); | |
235 | 235 | return domain; |
236 | 236 | } |
237 | 237 | |
... | ... | @@ -288,6 +288,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha |
288 | 288 | this.changeMapperConfigType(clientRegistration, registrationData.mapperConfig.type, registrationData.mapperConfig); |
289 | 289 | } else { |
290 | 290 | this.changeMapperConfigType(clientRegistration, MapperConfigType.BASIC); |
291 | + this.setProviderDefaultValue(defaultProviderName, clientRegistration); | |
291 | 292 | } |
292 | 293 | |
293 | 294 | this.subscriptions.push(clientRegistration.get('mapperConfig.type').valueChanges.subscribe((value) => { |
... | ... | @@ -296,33 +297,37 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha |
296 | 297 | |
297 | 298 | this.subscriptions.push(clientRegistration.get('additionalInfo.providerName').valueChanges.subscribe((provider) => { |
298 | 299 | (clientRegistration.get('scope') as FormArray).clear(); |
299 | - if (provider === 'Custom') { | |
300 | - const defaultSettings = {...this.defaultProvider, ...{id: clientRegistration.get('id').value}}; | |
301 | - clientRegistration.reset(defaultSettings, {emitEvent: false}); | |
302 | - clientRegistration.get('accessTokenUri').enable(); | |
303 | - clientRegistration.get('authorizationUri').enable(); | |
304 | - clientRegistration.get('jwkSetUri').enable(); | |
305 | - clientRegistration.get('userInfoUri').enable(); | |
306 | - } else { | |
307 | - const template = this.templates.get(provider); | |
308 | - delete template.id; | |
309 | - delete template.additionalInfo; | |
310 | - template.clientId = ''; | |
311 | - template.clientSecret = ''; | |
312 | - template.scope.forEach(() => { | |
313 | - (clientRegistration.get('scope') as FormArray).push(this.fb.control('')); | |
314 | - }); | |
315 | - clientRegistration.get('accessTokenUri').disable(); | |
316 | - clientRegistration.get('authorizationUri').disable(); | |
317 | - clientRegistration.get('jwkSetUri').disable(); | |
318 | - clientRegistration.get('userInfoUri').disable(); | |
319 | - clientRegistration.patchValue(template, {emitEvent: false}); | |
320 | - } | |
300 | + this.setProviderDefaultValue(provider, clientRegistration); | |
321 | 301 | })); |
322 | 302 | |
323 | 303 | return clientRegistration; |
324 | 304 | } |
325 | 305 | |
306 | + private setProviderDefaultValue(provider: string, clientRegistration: FormGroup) { | |
307 | + if (provider === 'Custom') { | |
308 | + const defaultSettings = {...this.defaultProvider, ...{id: clientRegistration.get('id').value}}; | |
309 | + clientRegistration.reset(defaultSettings, {emitEvent: false}); | |
310 | + clientRegistration.get('accessTokenUri').enable(); | |
311 | + clientRegistration.get('authorizationUri').enable(); | |
312 | + clientRegistration.get('jwkSetUri').enable(); | |
313 | + clientRegistration.get('userInfoUri').enable(); | |
314 | + } else { | |
315 | + const template = this.templates.get(provider); | |
316 | + delete template.id; | |
317 | + delete template.additionalInfo; | |
318 | + template.clientId = ''; | |
319 | + template.clientSecret = ''; | |
320 | + template.scope.forEach(() => { | |
321 | + (clientRegistration.get('scope') as FormArray).push(this.fb.control('')); | |
322 | + }); | |
323 | + clientRegistration.get('accessTokenUri').disable(); | |
324 | + clientRegistration.get('authorizationUri').disable(); | |
325 | + clientRegistration.get('jwkSetUri').disable(); | |
326 | + clientRegistration.get('userInfoUri').disable(); | |
327 | + clientRegistration.patchValue(template, {emitEvent: false}); | |
328 | + } | |
329 | + } | |
330 | + | |
326 | 331 | private changeMapperConfigType(control: AbstractControl, type: MapperConfigType, predefinedValue?: MapperConfig) { |
327 | 332 | const mapperConfig = control.get('mapperConfig') as FormGroup; |
328 | 333 | if (type === MapperConfigType.BASIC) { | ... | ... |
... | ... | @@ -121,7 +121,7 @@ |
121 | 121 | "minimum-max-failed-login-attempts-range": "Maximum number of failed login attempts can't be negative", |
122 | 122 | "user-lockout-notification-email": "In case user account lockout, send notification to email", |
123 | 123 | "domain-name": "Domain name", |
124 | - "domain-name-unique": "Domain name need to unique for the system.", | |
124 | + "domain-name-unique": "Domain name and protocol need to unique.", | |
125 | 125 | "error-verification-url": "A domain name shouldn't contain symbols '/' and ':'. Example: thingsboard.io", |
126 | 126 | "oauth2": { |
127 | 127 | "access-token-uri": "Access token URI", | ... | ... |