12 changed files with 845 additions and 9 deletions
@ -0,0 +1,364 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2020 The Thingsboard Authors |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
--> |
|||
<div> |
|||
<mat-card class="settings-card"> |
|||
<mat-card-title> |
|||
<div fxLayout="row"> |
|||
<span class="mat-headline" translate>admin.oauth2.settings</span> |
|||
<span fxFlex></span> |
|||
<div tb-help="oauth2Settings"></div> |
|||
</div> |
|||
</mat-card-title> |
|||
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async"> |
|||
</mat-progress-bar> |
|||
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div> |
|||
<mat-card-content style="padding-top: 16px;"> |
|||
<form [formGroup]="oauth2SettingsForm" (ngSubmit)="save()"> |
|||
<fieldset [disabled]="isLoading$ | async"> |
|||
<ng-container formArrayName="clientsDomainsParams"> |
|||
<div class="container"> |
|||
<mat-accordion multi> |
|||
<ng-container *ngFor="let domain of clientsDomainsParams.controls; let i = index; let last = last;"> |
|||
<mat-expansion-panel [formGroupName]="i" [expanded]="last"> |
|||
<mat-expansion-panel-header> |
|||
<mat-panel-title fxLayoutAlign="start center"> |
|||
{{ domain.get('domainName').value ? domain.get('domainName').value : ("admin.new-domain" | translate) }} |
|||
</mat-panel-title> |
|||
<mat-panel-description fxLayoutAlign="end center"> |
|||
<button mat-icon-button (click)="deleteDomain($event, i)"> |
|||
<mat-icon>delete</mat-icon> |
|||
</button> |
|||
</mat-panel-description> |
|||
</mat-expansion-panel-header> |
|||
|
|||
<mat-form-field class="mat-block"> |
|||
<mat-label translate>admin.domain-name</mat-label> |
|||
<input matInput formControlName="domainName" required> |
|||
<mat-error *ngIf="domain.get('domainName').hasError('pattern')"> |
|||
{{ 'admin.error-verification-url' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
|
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.redirect-uri-template</mat-label> |
|||
<input matInput formControlName="redirectUriTemplate" required> |
|||
<mat-error |
|||
*ngIf="domain.get('redirectUriTemplate').hasError('required')"> |
|||
{{ 'admin.oauth2.redirect-uri-template-required' | translate }} |
|||
</mat-error> |
|||
<mat-error |
|||
*ngIf="domain.get('redirectUriTemplate').hasError('pattern')"> |
|||
{{ 'admin.oauth2.uri-pattern-error' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
|
|||
<ng-container formArrayName="clientRegistrations"> |
|||
<div class="container"> |
|||
<mat-card *ngFor="let registration of clientDomainRegistrations(domain).controls; let j = index;" |
|||
class="registration-card"> |
|||
<section [formGroupName]="j"> |
|||
<div fxLayoutAlign="end center"> |
|||
<button mat-icon-button (click)="deleteRegistration($event, domain, j)"> |
|||
<mat-icon>delete</mat-icon> |
|||
</button> |
|||
</div> |
|||
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> |
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.registration-id</mat-label> |
|||
<input matInput formControlName="registrationId" required> |
|||
<mat-error *ngIf="registration.get('registrationId').hasError('required')"> |
|||
{{ 'admin.oauth2.registration-id-required' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
|
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.client-name</mat-label> |
|||
<input matInput formControlName="clientName" required> |
|||
<mat-error *ngIf="registration.get('clientName').hasError('required')"> |
|||
{{ 'admin.oauth2.client-name-required' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
</div> |
|||
|
|||
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> |
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.client-id</mat-label> |
|||
<input matInput formControlName="clientId" required> |
|||
<mat-error *ngIf="registration.get('clientId').hasError('required')"> |
|||
{{ 'admin.oauth2.client-id-required' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
|
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.client-secret</mat-label> |
|||
<input matInput formControlName="clientSecret" required> |
|||
<mat-error *ngIf="registration.get('clientSecret').hasError('required')"> |
|||
{{ 'admin.oauth2.client-secret-required' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
</div> |
|||
|
|||
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> |
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.access-token-uri</mat-label> |
|||
<input matInput formControlName="accessTokenUri" required> |
|||
<mat-error *ngIf="registration.get('accessTokenUri').hasError('required')"> |
|||
{{ 'admin.oauth2.access-token-uri-required' | translate }} |
|||
</mat-error> |
|||
<mat-error *ngIf="registration.get('accessTokenUri').hasError('pattern')"> |
|||
{{ 'admin.oauth2.uri-pattern-error' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
|
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.authorization-uri</mat-label> |
|||
<input matInput formControlName="authorizationUri" required> |
|||
<mat-error *ngIf="registration.get('authorizationUri').hasError('required')"> |
|||
{{ 'admin.oauth2.authorization-uri-required' | translate }} |
|||
</mat-error> |
|||
<mat-error *ngIf="registration.get('authorizationUri').hasError('pattern')"> |
|||
{{ 'admin.oauth2.uri-pattern-error' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
</div> |
|||
|
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.scope</mat-label> |
|||
<mat-chip-list #scopeList> |
|||
<mat-chip |
|||
*ngFor="let scope of registration.get('scope').value; let k = index;" |
|||
removable |
|||
(removed)="removeScope(k, registration)"> |
|||
{{scope}} |
|||
<mat-icon matChipRemove>cancel</mat-icon> |
|||
</mat-chip> |
|||
<input [matChipInputFor]="scopeList" |
|||
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" |
|||
matChipInputAddOnBlur |
|||
(matChipInputTokenEnd)="addScope($event, registration)"> |
|||
</mat-chip-list> |
|||
</mat-form-field> |
|||
|
|||
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> |
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.jwk-set-uri</mat-label> |
|||
<input matInput formControlName="jwkSetUri" required> |
|||
<mat-error *ngIf="registration.get('jwkSetUri').hasError('required')"> |
|||
{{ 'admin.oauth2.jwk-set-uri-required' | translate }} |
|||
</mat-error> |
|||
<mat-error *ngIf="registration.get('jwkSetUri').hasError('pattern')"> |
|||
{{ 'admin.oauth2.uri-pattern-error' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
|
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.user-info-uri</mat-label> |
|||
<input matInput formControlName="userInfoUri" required> |
|||
<mat-error *ngIf="registration.get('userInfoUri').hasError('required')"> |
|||
{{ 'admin.oauth2.user-info-uri-required' | translate }} |
|||
</mat-error> |
|||
<mat-error *ngIf="registration.get('userInfoUri').hasError('pattern')"> |
|||
{{ 'admin.oauth2.uri-pattern-error' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
</div> |
|||
|
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.client-authentication-method</mat-label> |
|||
<mat-select formControlName="clientAuthenticationMethod"> |
|||
<mat-option *ngFor="let clientAuthenticationMethod of clientAuthenticationMethods" |
|||
[value]="clientAuthenticationMethod"> |
|||
{{ clientAuthenticationMethod | uppercase }} |
|||
</mat-option> |
|||
</mat-select> |
|||
</mat-form-field> |
|||
|
|||
<mat-form-field class="mat-block"> |
|||
<mat-label translate>admin.oauth2.user-name-attribute-name</mat-label> |
|||
<input matInput formControlName="userNameAttributeName" required> |
|||
<mat-error *ngIf="registration.get('userNameAttributeName').hasError('required')"> |
|||
{{ 'admin.oauth2.user-name-attribute-name-required' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
|
|||
<section formGroupName="mapperConfig"> |
|||
<div fxLayout="column" fxLayoutGap="8px"> |
|||
<mat-checkbox formControlName="allowUserCreation"> |
|||
{{ 'admin.oauth2.allow-user-creation' | translate }} |
|||
</mat-checkbox> |
|||
<mat-checkbox formControlName="activateUser"> |
|||
{{ 'admin.oauth2.activate-user' | translate }} |
|||
</mat-checkbox> |
|||
</div> |
|||
|
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.type</mat-label> |
|||
<mat-select formControlName="type"> |
|||
<mat-option *ngFor="let converterTypeExternalUser of converterTypesExternalUser" |
|||
[value]="converterTypeExternalUser"> |
|||
{{ converterTypeExternalUser }} |
|||
</mat-option> |
|||
</mat-select> |
|||
</mat-form-field> |
|||
|
|||
<section formGroupName="basic" |
|||
*ngIf="registration.get('mapperConfig.type').value === 'BASIC'"> |
|||
<mat-form-field class="mat-block"> |
|||
<mat-label translate>admin.oauth2.email-attribute-key</mat-label> |
|||
<input matInput formControlName="emailAttributeKey" required> |
|||
<mat-error |
|||
*ngIf="registration.get('mapperConfig.basic.emailAttributeKey').hasError('required')"> |
|||
{{ 'admin.oauth2.email-attribute-key-required' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
|
|||
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> |
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.first-name-attribute-key</mat-label> |
|||
<input matInput formControlName="firstNameAttributeKey"> |
|||
</mat-form-field> |
|||
|
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.last-name-attribute-key</mat-label> |
|||
<input matInput formControlName="lastNameAttributeKey"> |
|||
</mat-form-field> |
|||
</div> |
|||
|
|||
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> |
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.tenant-name-strategy</mat-label> |
|||
<mat-select formControlName="tenantNameStrategy"> |
|||
<mat-option *ngFor="let tenantNameStrategy of tenantNameStrategies" |
|||
[value]="tenantNameStrategy"> |
|||
{{ tenantNameStrategy }} |
|||
</mat-option> |
|||
</mat-select> |
|||
</mat-form-field> |
|||
|
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.tenant-name-pattern</mat-label> |
|||
<input matInput |
|||
formControlName="tenantNamePattern" |
|||
[required]="registration.get('mapperConfig.basic.tenantNameStrategy').value === 'CUSTOM'"> |
|||
<mat-error |
|||
*ngIf="registration.get('mapperConfig.basic.tenantNamePattern').hasError('required')"> |
|||
{{ 'admin.oauth2.tenant-name-pattern-required' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
</div> |
|||
|
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.customer-name-pattern</mat-label> |
|||
<input matInput formControlName="customerNamePattern"> |
|||
</mat-form-field> |
|||
|
|||
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> |
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.default-dashboard-name</mat-label> |
|||
<input matInput formControlName="defaultDashboardName"> |
|||
</mat-form-field> |
|||
|
|||
<mat-checkbox fxFlex formControlName="alwaysFullScreen" class="checkbox-row"> |
|||
{{ 'admin.oauth2.always-fullscreen' | translate}} |
|||
</mat-checkbox> |
|||
</div> |
|||
|
|||
</section> |
|||
|
|||
<section formGroupName="custom" |
|||
*ngIf="registration.get('mapperConfig.type').value === 'CUSTOM'"> |
|||
<mat-form-field class="mat-block"> |
|||
<mat-label translate>admin.oauth2.url</mat-label> |
|||
<input matInput formControlName="url" required> |
|||
<mat-error |
|||
*ngIf="registration.get('mapperConfig.custom.url').hasError('required')"> |
|||
{{ 'admin.oauth2.url-required' | translate }} |
|||
</mat-error> |
|||
<mat-error |
|||
*ngIf="registration.get('mapperConfig.custom.url').hasError('pattern')"> |
|||
{{ 'admin.oauth2.url-pattern' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
|
|||
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> |
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>common.username</mat-label> |
|||
<input matInput formControlName="username"> |
|||
</mat-form-field> |
|||
|
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>common.password</mat-label> |
|||
<input matInput formControlName="password"> |
|||
</mat-form-field> |
|||
</div> |
|||
</section> |
|||
</section> |
|||
|
|||
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px"> |
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.login-button-label</mat-label> |
|||
<input matInput formControlName="loginButtonLabel" required> |
|||
<mat-error |
|||
*ngIf="registration.get('loginButtonLabel').hasError('required')"> |
|||
{{ 'admin.oauth2.login-button-label-required' | translate }} |
|||
</mat-error> |
|||
</mat-form-field> |
|||
|
|||
<mat-form-field fxFlex class="mat-block"> |
|||
<mat-label translate>admin.oauth2.login-button-icon</mat-label> |
|||
<input matInput formControlName="loginButtonIcon"> |
|||
</mat-form-field> |
|||
</div> |
|||
</section> |
|||
</mat-card> |
|||
</div> |
|||
</ng-container> |
|||
|
|||
<div fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="8px"> |
|||
<button mat-button mat-raised-button color="primary" |
|||
[disabled]="(isLoading$ | async)" |
|||
(click)="addRegistration(domain)" |
|||
type="button"> |
|||
{{'admin.add-registration' | translate}} |
|||
</button> |
|||
</div> |
|||
|
|||
</mat-expansion-panel> |
|||
</ng-container> |
|||
</mat-accordion> |
|||
</div> |
|||
</ng-container> |
|||
|
|||
<div fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="8px"> |
|||
<button mat-button mat-raised-button color="primary" |
|||
[disabled]="(isLoading$ | async)" |
|||
(click)="addDomain()" |
|||
type="button"> |
|||
{{'admin.add-domain' | translate}} |
|||
</button> |
|||
<button mat-button mat-raised-button color="primary" |
|||
[disabled]="(isLoading$ | async) || oauth2SettingsForm.invalid || !oauth2SettingsForm.dirty" |
|||
type="submit"> |
|||
{{'action.save' | translate}} |
|||
</button> |
|||
</div> |
|||
</fieldset> |
|||
</form> |
|||
</mat-card-content> |
|||
</mat-card> |
|||
</div> |
|||
@ -0,0 +1,28 @@ |
|||
/** |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0 |
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
:host{ |
|||
.checkbox-row { |
|||
margin-top: 16px; |
|||
} |
|||
|
|||
.registration-card{ |
|||
margin-bottom: 8px; |
|||
} |
|||
|
|||
.container{ |
|||
margin-bottom: 16px; |
|||
} |
|||
} |
|||
@ -0,0 +1,284 @@ |
|||
///
|
|||
/// Copyright © 2016-2020 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
import { Component, Inject, OnDestroy, OnInit } from '@angular/core'; |
|||
import { AbstractControl, FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; |
|||
import { ClientRegistration, DomainParams, OAuth2Settings } from '@shared/models/settings.models'; |
|||
import { Store } from '@ngrx/store'; |
|||
import { AppState } from '@core/core.state'; |
|||
import { AdminService } from '@core/http/admin.service'; |
|||
import { PageComponent } from '@shared/components/page.component'; |
|||
import { HasConfirmForm } from '@core/guards/confirm-on-exit.guard'; |
|||
import { COMMA, ENTER } from '@angular/cdk/keycodes'; |
|||
import { MatChipInputEvent } from '@angular/material/chips'; |
|||
import { WINDOW } from '@core/services/window.service'; |
|||
import { Subscription } from 'rxjs'; |
|||
import { DialogService } from '@core/services/dialog.service'; |
|||
import { TranslateService } from '@ngx-translate/core'; |
|||
|
|||
@Component({ |
|||
selector: 'tb-oauth2-settings', |
|||
templateUrl: './oauth2-settings.component.html', |
|||
styleUrls: ['./oauth2-settings.component.scss', './settings-card.scss'] |
|||
}) |
|||
export class OAuth2SettingsComponent extends PageComponent implements OnInit, HasConfirmForm, OnDestroy { |
|||
|
|||
private URL_REGEXP = /^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.?+=&%@\-/]*)?$/; |
|||
private subscriptions: Subscription[] = []; |
|||
|
|||
readonly separatorKeysCodes: number[] = [ENTER, COMMA]; |
|||
|
|||
oauth2SettingsForm: FormGroup; |
|||
oauth2Settings: OAuth2Settings; |
|||
|
|||
clientAuthenticationMethods = ['basic', 'post']; |
|||
converterTypesExternalUser = ['BASIC', 'CUSTOM']; |
|||
tenantNameStrategies = ['DOMAIN', 'EMAIL', 'CUSTOM']; |
|||
|
|||
constructor(protected store: Store<AppState>, |
|||
private adminService: AdminService, |
|||
private fb: FormBuilder, |
|||
private dialogService: DialogService, |
|||
private translate: TranslateService, |
|||
@Inject(WINDOW) private window: Window) { |
|||
super(store); |
|||
} |
|||
|
|||
ngOnInit(): void { |
|||
this.buildOAuth2SettingsForm(); |
|||
this.adminService.getOAuth2Settings().subscribe( |
|||
(oauth2Settings) => { |
|||
this.oauth2Settings = oauth2Settings; |
|||
this.initOAuth2Settings(this.oauth2Settings); |
|||
this.oauth2SettingsForm.reset(this.oauth2Settings); |
|||
} |
|||
); |
|||
} |
|||
|
|||
ngOnDestroy() { |
|||
super.ngOnDestroy(); |
|||
this.subscriptions.forEach((subscription) => { |
|||
subscription.unsubscribe(); |
|||
}) |
|||
} |
|||
|
|||
get clientsDomainsParams(): FormArray { |
|||
return this.oauth2SettingsForm.get('clientsDomainsParams') as FormArray; |
|||
} |
|||
|
|||
private get formBasicGroup(): FormGroup { |
|||
const basicGroup = this.fb.group({ |
|||
emailAttributeKey: ['email', [Validators.required]], |
|||
firstNameAttributeKey: [''], |
|||
lastNameAttributeKey: [''], |
|||
tenantNameStrategy: ['DOMAIN'], |
|||
tenantNamePattern: [null], |
|||
customerNamePattern: [null], |
|||
defaultDashboardName: [null], |
|||
alwaysFullScreen: [false], |
|||
}); |
|||
|
|||
this.subscriptions.push(basicGroup.get('tenantNameStrategy').valueChanges.subscribe((domain) => { |
|||
if (domain === 'CUSTOM') { |
|||
basicGroup.get('tenantNamePattern').setValidators(Validators.required); |
|||
} else { |
|||
basicGroup.get('tenantNamePattern').clearValidators(); |
|||
} |
|||
})); |
|||
|
|||
return basicGroup; |
|||
} |
|||
|
|||
get formCustomGroup(): FormGroup { |
|||
return this.fb.group({ |
|||
url: [null, [Validators.required, Validators.pattern(this.URL_REGEXP)]], |
|||
username: [null], |
|||
password: [null] |
|||
}) |
|||
} |
|||
|
|||
private buildOAuth2SettingsForm(): void { |
|||
this.oauth2SettingsForm = this.fb.group({ |
|||
clientsDomainsParams: this.fb.array([]) |
|||
}); |
|||
} |
|||
|
|||
private initOAuth2Settings(oauth2Settings: OAuth2Settings): void { |
|||
oauth2Settings.clientsDomainsParams.forEach((domaindomain) => { |
|||
this.clientsDomainsParams.push(this.buildSettingsDomain(domaindomain)); |
|||
}); |
|||
} |
|||
|
|||
private buildSettingsDomain(domainParams?: DomainParams): FormGroup { |
|||
let url = this.window.location.protocol + '//' + this.window.location.hostname; |
|||
const port = this.window.location.port; |
|||
if (port !== '80' && port !== '443') { |
|||
url += ':' + port; |
|||
} |
|||
url += '/login/oauth2/code/'; |
|||
const formDomain = this.fb.group({ |
|||
domainName: ['', [Validators.required, Validators.pattern('((?![:/]).)*$')]], |
|||
redirectUriTemplate: [url, [Validators.required, Validators.pattern(this.URL_REGEXP)]], |
|||
clientRegistrations: this.fb.array([]) |
|||
}); |
|||
|
|||
this.subscriptions.push(formDomain.get('domainName').valueChanges.subscribe((domain) => { |
|||
if (!domain) { |
|||
domain = this.window.location.hostname |
|||
} |
|||
const uri = this.window.location.protocol + `//${domain}/login/oauth2/code/`; |
|||
formDomain.get('redirectUriTemplate').patchValue(uri); |
|||
})); |
|||
|
|||
if(domainParams){ |
|||
domainParams.clientRegistrations.forEach((registration) => { |
|||
this.clientDomainRegistrations(formDomain).push(this.buildSettingsRegistration(registration)); |
|||
}) |
|||
} else { |
|||
this.clientDomainRegistrations(formDomain).push(this.buildSettingsRegistration()); |
|||
} |
|||
|
|||
return formDomain; |
|||
} |
|||
|
|||
private buildSettingsRegistration(registrationData?: ClientRegistration): FormGroup { |
|||
const clientRegistration = this.fb.group({ |
|||
registrationId: [null, [Validators.required]], |
|||
clientName: [null, [Validators.required]], |
|||
loginButtonLabel: [null, [Validators.required]], |
|||
loginButtonIcon: [null], |
|||
clientId: ['', [Validators.required]], |
|||
clientSecret: ['', [Validators.required]], |
|||
accessTokenUri: ['', [Validators.required, Validators.pattern(this.URL_REGEXP)]], |
|||
authorizationUri: ['', [Validators.required, Validators.pattern(this.URL_REGEXP)]], |
|||
scope: this.fb.array([], [Validators.required]), |
|||
jwkSetUri: ['', [Validators.required, Validators.pattern(this.URL_REGEXP)]], |
|||
userInfoUri: ['', [Validators.required, Validators.pattern(this.URL_REGEXP)]], |
|||
clientAuthenticationMethod: ['post', [Validators.required]], |
|||
userNameAttributeName: ['email', [Validators.required]], |
|||
mapperConfig: this.fb.group({ |
|||
allowUserCreation: [true], |
|||
activateUser: [false], |
|||
type: ['BASIC', [Validators.required]], |
|||
basic: this.formBasicGroup |
|||
} |
|||
) |
|||
}); |
|||
|
|||
this.subscriptions.push(clientRegistration.get('mapperConfig.type').valueChanges.subscribe((value) => { |
|||
const mapperConfig = clientRegistration.get('mapperConfig') as FormGroup; |
|||
if (value === 'BASIC') { |
|||
mapperConfig.removeControl('custom'); |
|||
mapperConfig.addControl('basic', this.formBasicGroup); |
|||
} else { |
|||
mapperConfig.removeControl('basic'); |
|||
mapperConfig.addControl('custom', this.formCustomGroup); |
|||
} |
|||
})); |
|||
|
|||
if(registrationData){ |
|||
registrationData.scope.forEach(() => { |
|||
(clientRegistration.get('scope') as FormArray).push(this.fb.control('')) |
|||
}) |
|||
if(registrationData.mapperConfig.type !== 'BASIC'){ |
|||
clientRegistration.get('mapperConfig.type').patchValue('CUSTOM'); |
|||
} |
|||
} |
|||
|
|||
return clientRegistration; |
|||
} |
|||
|
|||
save(): void { |
|||
console.log(this.oauth2SettingsForm.value); |
|||
this.adminService.saveOAuth2Settings(this.oauth2SettingsForm.value).subscribe( |
|||
(oauth2Settings) => { |
|||
this.oauth2Settings = oauth2Settings; |
|||
this.oauth2SettingsForm.markAsPristine(); |
|||
this.oauth2SettingsForm.markAsUntouched(); |
|||
} |
|||
); |
|||
} |
|||
|
|||
confirmForm(): FormGroup { |
|||
return this.oauth2SettingsForm; |
|||
} |
|||
|
|||
addScope(event: MatChipInputEvent, control: AbstractControl): void { |
|||
const input = event.input; |
|||
const value = event.value; |
|||
const controller = control.get('scope') as FormArray; |
|||
if ((value.trim() !== '')) { |
|||
controller.push(this.fb.control(value.trim())); |
|||
} |
|||
|
|||
if (input) { |
|||
input.value = ''; |
|||
} |
|||
} |
|||
|
|||
removeScope(i: number, control: AbstractControl): void { |
|||
const controller = control.get('scope') as FormArray; |
|||
controller.removeAt(i); |
|||
} |
|||
|
|||
addDomain(): void { |
|||
this.clientsDomainsParams.push(this.buildSettingsDomain()); |
|||
} |
|||
|
|||
deleteDomain($event: Event, index: number): void { |
|||
if ($event) { |
|||
$event.stopPropagation(); |
|||
$event.preventDefault(); |
|||
} |
|||
|
|||
const domainName = this.clientsDomainsParams.at(index).get('domainName').value; |
|||
this.dialogService.confirm( |
|||
this.translate.instant('admin.oauth2.delete-domain-title', {domainName}), |
|||
this.translate.instant('admin.oauth2.delete-domain-text'), null, |
|||
this.translate.instant('action.delete') |
|||
).subscribe((data) => { |
|||
if (data) { |
|||
this.clientsDomainsParams.removeAt(index); |
|||
} |
|||
}) |
|||
} |
|||
|
|||
clientDomainRegistrations(control: AbstractControl): FormArray { |
|||
return control.get('clientRegistrations') as FormArray; |
|||
} |
|||
|
|||
addRegistration(control: AbstractControl): void { |
|||
this.clientDomainRegistrations(control).push(this.buildSettingsRegistration()); |
|||
} |
|||
|
|||
deleteRegistration($event: Event, controler: AbstractControl, index: number): void { |
|||
if ($event) { |
|||
$event.stopPropagation(); |
|||
$event.preventDefault(); |
|||
} |
|||
|
|||
const registrationId = this.clientDomainRegistrations(controler).at(index).get('registrationId').value; |
|||
this.dialogService.confirm( |
|||
this.translate.instant('admin.oauth2.delete-registration-title', {name: registrationId}), |
|||
this.translate.instant('admin.oauth2.delete-registration-text'), null, |
|||
this.translate.instant('action.delete') |
|||
).subscribe((data) => { |
|||
if (data) { |
|||
this.clientDomainRegistrations(controler).removeAt(index); |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
Loading…
Reference in new issue