Browse Source

UI: oauth2 improvements, code cleanup

pull/11664/head
rusikv 2 years ago
parent
commit
519d6b4647
  1. 7
      ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client-dialog.component.ts
  2. 13
      ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client.component.ts
  3. 21
      ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/clients-table-config.resolver.ts
  4. 18
      ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain-table-config.resolver.ts
  5. 5
      ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain.component.html
  6. 5
      ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain.component.ts
  7. 22
      ui-ngx/src/app/modules/home/pages/admin/oauth2/mobile-apps/mobile-app-table-config.resolver.ts
  8. 8
      ui-ngx/src/app/modules/home/pages/admin/oauth2/mobile-apps/mobile-app.component.html
  9. 12
      ui-ngx/src/app/modules/home/pages/admin/oauth2/mobile-apps/mobile-app.component.ts
  10. 1
      ui-ngx/src/assets/locale/locale.constant-en_US.json

7
ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client-dialog.component.ts

@ -14,13 +14,13 @@
/// limitations under the License.
///
import { Component, OnDestroy, SkipSelf, ViewChild } from '@angular/core';
import { AfterViewInit, Component, OnDestroy, SkipSelf, ViewChild } from '@angular/core';
import { DialogComponent } from '@shared/components/dialog.component';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { Router } from '@angular/router';
import { MatDialogRef } from '@angular/material/dialog';
import { FormBuilder, FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms';
import { FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms';
import { getProviderHelpLink, OAuth2Client } from '@shared/models/oauth2.models';
import { OAuth2Service } from '@core/http/oauth2.service';
import { ClientComponent } from '@home/pages/admin/oauth2/clients/client.component';
@ -32,7 +32,7 @@ import { ErrorStateMatcher } from '@angular/material/core';
providers: [{provide: ErrorStateMatcher, useExisting: ClientDialogComponent}],
styleUrls: []
})
export class ClientDialogComponent extends DialogComponent<ClientDialogComponent, OAuth2Client> implements OnDestroy {
export class ClientDialogComponent extends DialogComponent<ClientDialogComponent, OAuth2Client> implements OnDestroy, AfterViewInit {
submitted = false;
@ -41,7 +41,6 @@ export class ClientDialogComponent extends DialogComponent<ClientDialogComponent
constructor(protected store: Store<AppState>,
protected router: Router,
protected dialogRef: MatDialogRef<ClientDialogComponent, OAuth2Client>,
private fb: FormBuilder,
private oauth2Service: OAuth2Service,
@SkipSelf() private errorStateMatcher: ErrorStateMatcher) {
super(store, router, dialogRef);

13
ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/client.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { ChangeDetectorRef, Component, Inject, Input, Optional } from '@angular/core';
import { ChangeDetectorRef, Component, Inject, Input, OnDestroy, Optional } from '@angular/core';
import { EntityComponent } from '@home/components/entity/entity.component';
import {
ClientAuthenticationMethod,
@ -54,7 +54,7 @@ import { coerceBoolean } from '@app/shared/decorators/coercion';
templateUrl: './client.component.html',
styleUrls: ['./client.component.scss']
})
export class ClientComponent extends EntityComponent<OAuth2Client, PageLink, OAuth2ClientInfo> {
export class ClientComponent extends EntityComponent<OAuth2Client, PageLink, OAuth2ClientInfo> implements OnDestroy {
@Input()
@coerceBoolean()
@ -109,7 +109,8 @@ export class ClientComponent extends EntityComponent<OAuth2Client, PageLink, OAu
protected translate: TranslateService,
private oauth2Service: OAuth2Service,
@Optional() @Inject('entity') protected entityValue: OAuth2Client,
@Optional() @Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig<OAuth2Client, PageLink, OAuth2ClientInfo>,
@Optional() @Inject('entitiesTableConfig')
protected entitiesTableConfigValue: EntityTableConfig<OAuth2Client, PageLink, OAuth2ClientInfo>,
protected cd: ChangeDetectorRef,
public fb: UntypedFormBuilder) {
super(store, fb, entityValue, entitiesTableConfigValue, cd);
@ -185,13 +186,13 @@ export class ClientComponent extends EntityComponent<OAuth2Client, PageLink, OAu
if (entity.scope.length === scopeControls.length) {
scopeControls.patchValue(entity.scope, {emitEvent: false});
} else {
const scopeControls: Array<AbstractControl> = [];
const newScopeControls: Array<AbstractControl> = [];
if (entity.scope) {
for (const scope of entity.scope) {
scopeControls.push(this.fb.control(scope, [Validators.required]));
newScopeControls.push(this.fb.control(scope, [Validators.required]));
}
}
this.entityForm.setControl('scope', this.fb.array(scopeControls));
this.entityForm.setControl('scope', this.fb.array(newScopeControls));
}
}

21
ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/clients-table-config.resolver.ts

@ -27,7 +27,6 @@ import {
OAuth2ClientInfo,
platformTypeTranslations
} from '@shared/models/oauth2.models';
import { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core';
import { DatePipe } from '@angular/common';
import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models';
@ -40,11 +39,11 @@ import { PageLink } from '@shared/models/page/page-link';
@Injectable()
export class ClientsTableConfigResolver implements Resolve<EntityTableConfig<OAuth2Client, PageLink, OAuth2ClientInfo>> {
private readonly config: EntityTableConfig<OAuth2Client, PageLink, OAuth2ClientInfo> = new EntityTableConfig<OAuth2Client, PageLink, OAuth2ClientInfo>();
private readonly config: EntityTableConfig<OAuth2Client, PageLink, OAuth2ClientInfo> =
new EntityTableConfig<OAuth2Client, PageLink, OAuth2ClientInfo>();
constructor(private translate: TranslateService,
private datePipe: DatePipe,
private utilsService: UtilsService,
private oauth2Service: OAuth2Service) {
this.config.tableTitle = this.translate.instant('admin.oauth2.clients');
this.config.selectionEnabled = false;
@ -53,9 +52,7 @@ export class ClientsTableConfigResolver implements Resolve<EntityTableConfig<OAu
this.config.entityTranslations = entityTypeTranslations.get(EntityType.OAUTH2_CLIENT);
this.config.entityResources = {
helpLinkId: null,
helpLinkIdForEntity(entity: OAuth2Client): string {
return getProviderHelpLink(entity.additionalInfo.providerName);
}
helpLinkIdForEntity: (entity: OAuth2Client) => getProviderHelpLink(entity.additionalInfo.providerName)
};
this.config.entityComponent = ClientComponent;
this.config.headerComponent = ClientTableHeaderComponent;
@ -66,20 +63,16 @@ export class ClientsTableConfigResolver implements Resolve<EntityTableConfig<OAu
new DateEntityTableColumn<OAuth2ClientInfo>('createdTime', 'common.created-time', this.datePipe, '170px'),
new EntityTableColumn<OAuth2ClientInfo>('title', 'admin.oauth2.title', '350px'),
new EntityTableColumn<OAuth2ClientInfo>('platforms', 'admin.oauth2.allowed-platforms', '100%',
(clientInfo) => {
return clientInfo.platforms && clientInfo.platforms.length ?
clientInfo.platforms.map(platform => this.translate.instant(platformTypeTranslations.get(platform))).join(', ') :
this.translate.instant('admin.oauth2.all-platforms');
}, () => ({}), false)
(clientInfo) => clientInfo.platforms && clientInfo.platforms.length ?
clientInfo.platforms.map(platform => this.translate.instant(platformTypeTranslations.get(platform))).join(', ') :
this.translate.instant('admin.oauth2.all-platforms'), () => ({}), false)
);
this.config.deleteEntityTitle = (client) => this.translate.instant('admin.oauth2.delete-client-title', {clientName: client.title});
this.config.deleteEntityContent = () => this.translate.instant('admin.oauth2.delete-client-text');
this.config.entitiesFetchFunction = pageLink => this.oauth2Service.findTenantOAuth2ClientInfos(pageLink);
this.config.loadEntity = id => this.oauth2Service.getOAuth2ClientById(id.id);
this.config.saveEntity = client => {
return this.oauth2Service.saveOAuth2Client(client);
}
this.config.saveEntity = client => this.oauth2Service.saveOAuth2Client(client);
this.config.deleteEntity = id => this.oauth2Service.deleteOauth2Client(id.id);
}

18
ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain-table-config.resolver.ts

@ -33,7 +33,7 @@ import { DomainComponent } from '@home/pages/admin/oauth2/domains/domain.compone
import { isEqual } from '@core/utils';
import { DomainTableHeaderComponent } from '@home/pages/admin/oauth2/domains/domain-table-header.component';
import { Direction } from '@app/shared/models/page/sort-order';
import { map } from 'rxjs';
import { map, Observable, of, mergeMap } from 'rxjs';
@Injectable()
export class DomainTableConfigResolver implements Resolve<EntityTableConfig<DomainInfo>> {
@ -87,18 +87,22 @@ export class DomainTableConfigResolver implements Resolve<EntityTableConfig<Doma
this.config.loadEntity = id => this.domainService.getDomainInfoById(id.id);
this.config.saveEntity = (domain, originalDomain) => {
const clientsIds = domain.oauth2ClientInfos as Array<string> || [];
let clientsTask: Observable<void>;
if (domain.id && !isEqual(domain.oauth2ClientInfos?.sort(),
originalDomain.oauth2ClientInfos?.map(info => info.id ? info.id.id : info).sort())) {
this.domainService.updateOauth2Clients(domain.id.id, clientsIds).subscribe();
clientsTask = this.domainService.updateOauth2Clients(domain.id.id, clientsIds);
} else {
clientsTask = of(null);
}
delete domain.oauth2ClientInfos;
return this.domainService.saveDomain(domain, domain.id ? [] : clientsIds).pipe(
map(domain => {
(domain as DomainInfo).oauth2ClientInfos = clientsIds;
return domain;
return clientsTask.pipe(
mergeMap(() => this.domainService.saveDomain(domain, domain.id ? [] : clientsIds)),
map(savedDomain => {
(savedDomain as DomainInfo).oauth2ClientInfos = clientsIds;
return savedDomain;
})
);
}
};
this.config.deleteEntity = id => this.domainService.deleteDomain(id.id);
}

5
ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain.component.html

@ -54,10 +54,9 @@
<tb-entity-list [entityType]="entityType.OAUTH2_CLIENT" formControlName="oauth2ClientInfos"
labelText="{{ 'admin.oauth2.clients' | translate }}"
placeholderText="{{ 'admin.oauth2.add-client' | translate }}">
<button #createTargetButton
mat-button color="primary" matSuffix
<button mat-button color="primary" matSuffix
[disabled]="!isEdit"
(click)="createClient($event, createTargetButton)">
(click)="createClient($event)">
<span style="white-space: nowrap">{{ 'admin.oauth2.create-new' | translate }}</span>
</button>
</tb-entity-list>

5
ui-ngx/src/app/modules/home/pages/admin/oauth2/domains/domain.component.ts

@ -26,7 +26,6 @@ import { Store } from '@ngrx/store';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { WINDOW } from '@core/services/window.service';
import { isDefinedAndNotNull } from '@core/utils';
import { MatButton } from '@angular/material/button';
import { MatDialog } from '@angular/material/dialog';
import { ClientDialogComponent } from '@home/pages/admin/oauth2/clients/client-dialog.component';
import { EntityType } from '@shared/models/entity-type.models';
@ -38,7 +37,7 @@ import { EntityType } from '@shared/models/entity-type.models';
})
export class DomainComponent extends EntityComponent<DomainInfo> {
private loginProcessingUrl: string = '';
private loginProcessingUrl = '';
entityType = EntityType;
@ -83,7 +82,7 @@ export class DomainComponent extends EntityComponent<DomainInfo> {
return domainName !== '' ? `${domainName}${this.loginProcessingUrl}` : '';
}
createClient($event: Event, button: MatButton) {
createClient($event: Event) {
if ($event) {
$event.stopPropagation();
$event.preventDefault();

22
ui-ngx/src/app/modules/home/pages/admin/oauth2/mobile-apps/mobile-app-table-config.resolver.ts

@ -25,7 +25,6 @@ import {
EntityTableConfig
} from '@home/models/entity/entities-table-config.models';
import { MobileApp, MobileAppInfo } from '@shared/models/oauth2.models';
import { UtilsService } from '@core/services/utils.service';
import { TranslateService } from '@ngx-translate/core';
import { DatePipe } from '@angular/common';
import { EntityType, entityTypeResources, entityTypeTranslations } from '@shared/models/entity-type.models';
@ -34,7 +33,7 @@ import { Direction } from '@app/shared/models/page/sort-order';
import { MobileAppService } from '@core/http/mobile-app.service';
import { MobileAppComponent } from '@home/pages/admin/oauth2/mobile-apps/mobile-app.component';
import { MobileAppTableHeaderComponent } from '@home/pages/admin/oauth2/mobile-apps/mobile-app-table-header.component';
import { map } from 'rxjs';
import { map, Observable, of, mergeMap } from 'rxjs';
@Injectable()
export class MobileAppTableConfigResolver implements Resolve<EntityTableConfig<MobileAppInfo>> {
@ -43,7 +42,6 @@ export class MobileAppTableConfigResolver implements Resolve<EntityTableConfig<M
constructor(private translate: TranslateService,
private datePipe: DatePipe,
private utilsService: UtilsService,
private mobileAppService: MobileAppService) {
this.config.tableTitle = this.translate.instant('admin.oauth2.mobile-apps');
this.config.selectionEnabled = false;
@ -66,7 +64,7 @@ export class MobileAppTableConfigResolver implements Resolve<EntityTableConfig<M
name: this.translate.instant('admin.oauth2.copy-mobile-app-secret'),
icon: 'content_copy',
style: {
'padding-top': '1px',
padding: '4px',
'font-size': '16px',
color: 'rgba(0,0,0,.87)'
},
@ -93,18 +91,22 @@ export class MobileAppTableConfigResolver implements Resolve<EntityTableConfig<M
this.config.loadEntity = id => this.mobileAppService.getMobileAppInfoById(id.id);
this.config.saveEntity = (mobileApp, originalMobileApp) => {
const clientsIds = mobileApp.oauth2ClientInfos as Array<string> || [];
let clientsTask: Observable<void>;
if (mobileApp.id && !isEqual(mobileApp.oauth2ClientInfos?.sort(),
originalMobileApp.oauth2ClientInfos?.map(info => info.id ? info.id.id : info).sort())) {
this.mobileAppService.updateOauth2Clients(mobileApp.id.id, clientsIds).subscribe();
clientsTask = this.mobileAppService.updateOauth2Clients(mobileApp.id.id, clientsIds);
} else {
clientsTask = of(null);
}
delete mobileApp.oauth2ClientInfos;
return this.mobileAppService.saveMobileApp(mobileApp as MobileApp, mobileApp.id ? [] : clientsIds).pipe(
map(mobileApp => {
(mobileApp as MobileAppInfo).oauth2ClientInfos = clientsIds;
return mobileApp;
return clientsTask.pipe(
mergeMap(() => this.mobileAppService.saveMobileApp(mobileApp as MobileApp, mobileApp.id ? [] : clientsIds)),
map(savedMobileApp => {
(savedMobileApp as MobileAppInfo).oauth2ClientInfos = clientsIds;
return savedMobileApp;
})
);
}
};
this.config.deleteEntity = id => this.mobileAppService.deleteMobileApp(id.id);
}

8
ui-ngx/src/app/modules/home/pages/admin/oauth2/mobile-apps/mobile-app.component.html

@ -28,6 +28,9 @@
<mat-error *ngIf="entityForm.get('pkgName').hasError('maxlength')">
{{ 'admin.oauth2.mobile-package-max-length' | translate }}
</mat-error>
<mat-error *ngIf="entityForm.get('pkgName').hasError('pattern')">
{{ 'admin.oauth2.mobile-package-spaces' | translate }}
</mat-error>
</mat-form-field>
</div>
<div class="tb-form-row tb-standard-fields no-border no-padding">
@ -63,10 +66,9 @@
<tb-entity-list [entityType]="entityType.OAUTH2_CLIENT" formControlName="oauth2ClientInfos"
labelText="{{ 'admin.oauth2.clients' | translate }}"
placeholderText="{{ 'admin.oauth2.add-client' | translate }}">
<button #createTargetButton
mat-button color="primary" matSuffix
<button mat-button color="primary" matSuffix
[disabled]="!isEdit"
(click)="createClient($event, createTargetButton)">
(click)="createClient($event)">
<span style="white-space: nowrap">{{ 'admin.oauth2.create-new' | translate }}</span>
</button>
</tb-entity-list>

12
ui-ngx/src/app/modules/home/pages/admin/oauth2/mobile-apps/mobile-app.component.ts

@ -19,14 +19,11 @@ import { ChangeDetectorRef, Component, Inject } from '@angular/core';
import { EntityComponent } from '@home/components/entity/entity.component';
import { MobileAppInfo } from '@shared/models/oauth2.models';
import { AppState } from '@core/core.state';
import { OAuth2Service } from '@core/http/oauth2.service';
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
import { TranslateService } from '@ngx-translate/core';
import { Store } from '@ngrx/store';
import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { WINDOW } from '@core/services/window.service';
import { isDefinedAndNotNull, randomAlphanumeric } from '@core/utils';
import { MatButton } from '@angular/material/button';
import { MatDialog } from '@angular/material/dialog';
import { ClientDialogComponent } from '@home/pages/admin/oauth2/clients/client-dialog.component';
import { EntityType } from '@shared/models/entity-type.models';
@ -42,19 +39,18 @@ export class MobileAppComponent extends EntityComponent<MobileAppInfo> {
constructor(protected store: Store<AppState>,
protected translate: TranslateService,
private oauth2Service: OAuth2Service,
@Inject('entity') protected entityValue: MobileAppInfo,
@Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig<MobileAppInfo>,
protected cd: ChangeDetectorRef,
public fb: UntypedFormBuilder,
@Inject(WINDOW) private window: Window,
private dialog: MatDialog) {
super(store, fb, entityValue, entitiesTableConfigValue, cd);
}
buildForm(entity: MobileAppInfo): UntypedFormGroup {
return this.fb.group({
pkgName: [entity?.pkgName ? entity.pkgName : '', [Validators.required, Validators.maxLength(255)]],
pkgName: [entity?.pkgName ? entity.pkgName : '', [Validators.required, Validators.maxLength(255),
Validators.pattern(/^\S+$/)]],
appSecret: [entity?.appSecret ? entity.appSecret : btoa(randomAlphanumeric(64)),
[Validators.required, this.base64Format]],
oauth2Enabled: isDefinedAndNotNull(entity?.oauth2Enabled) ? entity.oauth2Enabled : true,
@ -68,10 +64,10 @@ export class MobileAppComponent extends EntityComponent<MobileAppInfo> {
appSecret: entity.appSecret,
oauth2Enabled: entity.oauth2Enabled,
oauth2ClientInfos: entity.oauth2ClientInfos?.map(info => info.id ? info.id.id : info)
})
});
}
createClient($event: Event, button: MatButton) {
createClient($event: Event) {
if ($event) {
$event.stopPropagation();
$event.preventDefault();

1
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -323,6 +323,7 @@
"mobile-package-hint": "For Android: your own unique Application ID. For iOS: Product bundle identifier.",
"mobile-package-unique": "Application package must be unique.",
"mobile-package-max-length": "Application package should be less than 256",
"mobile-package-spaces": "Application package should not contain spaces",
"mobile-app-secret": "Application secret",
"mobile-app-secret-hint": "Base64 encoded string representing at least 512 bits of data.",
"mobile-app-secret-required": "Application secret is required.",

Loading…
Cancel
Save