mirror of
https://github.com/zitadel/zitadel.git
synced 2025-02-28 15:17:24 +00:00
chore(console): resolve warnings due to dependency update (#4270)
* cli, core * material cdk * schematics * chore(deps): bump ngx-color from 7.3.3 to 8.0.2 in /console (#4228) Bumps [ngx-color](https://github.com/scttcper/ngx-color) from 7.3.3 to 8.0.2. - [Release notes](https://github.com/scttcper/ngx-color/releases) - [Commits](https://github.com/scttcper/ngx-color/compare/v7.3.3...v8.0.2) --- updated-dependencies: - dependency-name: ngx-color dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * eslint-plugin * chore(deps): bump moment from 2.29.3 to 2.29.4 in /console (#3926) Bumps [moment](https://github.com/moment/moment) from 2.29.3 to 2.29.4. - [Release notes](https://github.com/moment/moment/releases) - [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md) - [Commits](https://github.com/moment/moment/compare/2.29.3...2.29.4) --- updated-dependencies: - dependency-name: moment dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump codemirror from 5.65.6 to 6.0.1 in /console (#3928) Bumps [codemirror](https://github.com/codemirror/basic-setup) from 5.65.6 to 6.0.1. - [Release notes](https://github.com/codemirror/basic-setup/releases) - [Changelog](https://github.com/codemirror/basic-setup/blob/main/CHANGELOG.md) - [Commits](https://github.com/codemirror/basic-setup/commits/6.0.1) --- updated-dependencies: - dependency-name: codemirror dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * lock * use codemirror 5 * remove redundant null undefined checks * i18n, undefined checks * remove redundant null and undefined checks * checks * fix: resolve null check warnings * commonjs deps Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
parent
2f647ce9a2
commit
861464598a
@ -22,18 +22,14 @@
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets",
|
||||
"src/manifest.webmanifest"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": [
|
||||
"./node_modules/tinycolor2/dist/tinycolor-min.js"
|
||||
],
|
||||
"assets": ["src/favicon.ico", "src/assets", "src/manifest.webmanifest"],
|
||||
"styles": ["src/styles.scss"],
|
||||
"scripts": ["./node_modules/tinycolor2/dist/tinycolor-min.js"],
|
||||
"allowedCommonJsDependencies": [
|
||||
"fast-sha256",
|
||||
"buffer",
|
||||
"moment",
|
||||
"grpc-web",
|
||||
"@angular/common/locales/de",
|
||||
"codemirror/mode/javascript/javascript",
|
||||
"src/app/proto/generated/zitadel/admin_pb",
|
||||
@ -130,27 +126,15 @@
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets",
|
||||
"src/manifest.webmanifest"
|
||||
],
|
||||
"styles": [
|
||||
"./node_modules/@angular/material/prebuilt-themes/pink-bluegrey.css",
|
||||
"src/styles.scss"
|
||||
],
|
||||
"scripts": [
|
||||
"./node_modules/tinycolor2/dist/tinycolor-min.js"
|
||||
]
|
||||
"assets": ["src/favicon.ico", "src/assets", "src/manifest.webmanifest"],
|
||||
"styles": ["./node_modules/@angular/material/prebuilt-themes/pink-bluegrey.css", "src/styles.scss"],
|
||||
"scripts": ["./node_modules/tinycolor2/dist/tinycolor-min.js"]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-eslint/builder:lint",
|
||||
"options": {
|
||||
"lintFilePatterns": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.html"
|
||||
]
|
||||
"lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
|
||||
}
|
||||
},
|
||||
"e2e": {
|
||||
@ -173,8 +157,6 @@
|
||||
},
|
||||
"cli": {
|
||||
"analytics": "2b4e8e6c-f053-4562-b7a6-00c6c06a6791",
|
||||
"schematicCollections": [
|
||||
"@angular-eslint/schematics"
|
||||
]
|
||||
"schematicCollections": ["@angular-eslint/schematics"]
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
<div class="accounts-card">
|
||||
<cnsl-avatar
|
||||
(click)="editUserProfile()"
|
||||
*ngIf="user.human?.profile && user.human?.profile?.displayName"
|
||||
*ngIf="user && user.human?.profile && user.human?.profile?.displayName"
|
||||
class="avatar"
|
||||
[ngClass]="{ 'iam-user': iamuser }"
|
||||
[forColor]="user.preferredLoginName"
|
||||
[avatarUrl]="user.human?.profile?.avatarUrl || ''"
|
||||
[name]="
|
||||
user.human && user.human.profile && user.human.profile?.displayName
|
||||
user.human && user.human.profile && user.human.profile.displayName
|
||||
? user.human.profile.displayName
|
||||
: user.human?.profile?.firstName + ' ' + user.human?.profile?.lastName
|
||||
"
|
||||
@ -15,8 +15,8 @@
|
||||
>
|
||||
</cnsl-avatar>
|
||||
|
||||
<span class="u-name">{{ user.human?.profile?.displayName ? user.human?.profile?.displayName : 'A' }}</span>
|
||||
<span class="u-email" *ngIf="user.preferredLoginName">{{ user.preferredLoginName }}</span>
|
||||
<span class="u-name">{{ user?.human?.profile?.displayName ? user?.human?.profile?.displayName : 'A' }}</span>
|
||||
<span class="u-email" *ngIf="user?.preferredLoginName">{{ user?.preferredLoginName }}</span>
|
||||
|
||||
<button (click)="editUserProfile()" mat-stroked-button>{{ 'USER.EDITACCOUNT' | translate }}</button>
|
||||
<div class="l-accounts">
|
||||
|
@ -11,7 +11,7 @@ import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
styleUrls: ['./accounts-card.component.scss'],
|
||||
})
|
||||
export class AccountsCardComponent implements OnInit {
|
||||
@Input() public user!: User.AsObject;
|
||||
@Input() public user?: User.AsObject;
|
||||
@Input() public iamuser: boolean | null = false;
|
||||
|
||||
@Output() public closedCard: EventEmitter<void> = new EventEmitter();
|
||||
@ -22,12 +22,7 @@ export class AccountsCardComponent implements OnInit {
|
||||
this.userService
|
||||
.listMyUserSessions()
|
||||
.then((sessions) => {
|
||||
this.sessions = sessions.resultList;
|
||||
const index = this.sessions.findIndex((user) => user.loginName === this.user.preferredLoginName);
|
||||
if (index > -1) {
|
||||
this.sessions.splice(index, 1);
|
||||
}
|
||||
|
||||
this.sessions = sessions.resultList.filter((user) => user.loginName !== this.user?.preferredLoginName);
|
||||
this.loadingUsers = false;
|
||||
})
|
||||
.catch(() => {
|
||||
|
@ -18,7 +18,7 @@
|
||||
<mat-datepicker #picker [startAt]="startDate"></mat-datepicker>
|
||||
<span cnslError *ngIf="dateControl?.errors?.matDatepickerMin?.min">
|
||||
{{ 'USER.MACHINE.CHOOSEDATEAFTER' | translate }}:
|
||||
{{ dateControl?.errors?.matDatepickerMin.min.toDate() | localizedDate: 'EEE dd. MMM' }}
|
||||
{{ dateControl.errors?.matDatepickerMin.min.toDate() | localizedDate: 'EEE dd. MMM' }}
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<mat-datepicker #picker startView="year" [startAt]="startDate"></mat-datepicker>
|
||||
<span cnslError *ngIf="dateControl?.errors?.matDatepickerMin?.min">
|
||||
{{ 'USER.PERSONALACCESSTOKEN.ADD.CHOOSEDATEAFTER' | translate }}:
|
||||
{{ dateControl?.errors?.matDatepickerMin.min.toDate() | localizedDate: 'EEE dd. MMM' }}
|
||||
{{ dateControl.errors?.matDatepickerMin.min.toDate() | localizedDate: 'EEE dd. MMM' }}
|
||||
</span>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
|
@ -27,15 +27,19 @@ export class ClientKeysComponent implements OnInit {
|
||||
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
|
||||
public dataSource: MatTableDataSource<Key.AsObject> = new MatTableDataSource<Key.AsObject>();
|
||||
public selection: SelectionModel<Key.AsObject> = new SelectionModel<Key.AsObject>(true, []);
|
||||
public keyResult!: ListAppKeysResponse.AsObject;
|
||||
public keyResult?: ListAppKeysResponse.AsObject;
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
@Input() public displayedColumns: string[] = ['select', 'id', 'type', 'creationDate', 'expirationDate', 'actions'];
|
||||
|
||||
@Output() public changedSelection: EventEmitter<Array<Key.AsObject>> = new EventEmitter();
|
||||
|
||||
constructor(public translate: TranslateService, private mgmtService: ManagementService, private dialog: MatDialog,
|
||||
private toast: ToastService) {
|
||||
constructor(
|
||||
public translate: TranslateService,
|
||||
private mgmtService: ManagementService,
|
||||
private dialog: MatDialog,
|
||||
private toast: ToastService,
|
||||
) {
|
||||
this.selection.changed.subscribe(() => {
|
||||
this.changedSelection.emit(this.selection.selected);
|
||||
});
|
||||
@ -45,7 +49,6 @@ export class ClientKeysComponent implements OnInit {
|
||||
this.getData(10, 0);
|
||||
}
|
||||
|
||||
|
||||
public isAllSelected(): boolean {
|
||||
const numSelected = this.selection.selected.length;
|
||||
const numRows = this.dataSource.data.length;
|
||||
@ -53,24 +56,24 @@ export class ClientKeysComponent implements OnInit {
|
||||
}
|
||||
|
||||
public masterToggle(): void {
|
||||
this.isAllSelected() ?
|
||||
this.selection.clear() :
|
||||
this.dataSource.data.forEach(row => this.selection.select(row));
|
||||
this.isAllSelected() ? this.selection.clear() : this.dataSource.data.forEach((row) => this.selection.select(row));
|
||||
}
|
||||
|
||||
|
||||
public changePage(event: PageEvent): void {
|
||||
this.getData(event.pageSize, event.pageIndex * event.pageSize);
|
||||
}
|
||||
|
||||
public deleteKey(key: Key.AsObject): void {
|
||||
this.mgmtService.removeAppKey(this.projectId, this.appId, key.id).then(() => {
|
||||
this.selection.clear();
|
||||
this.toast.showInfo('USER.TOAST.SELECTEDKEYSDELETED', true);
|
||||
this.getData(10, 0);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
this.mgmtService
|
||||
.removeAppKey(this.projectId, this.appId, key.id)
|
||||
.then(() => {
|
||||
this.selection.clear();
|
||||
this.toast.showInfo('USER.TOAST.SELECTEDKEYSDELETED', true);
|
||||
this.getData(10, 0);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
|
||||
public openAddKey(): void {
|
||||
@ -96,28 +99,26 @@ export class ClientKeysComponent implements OnInit {
|
||||
}
|
||||
|
||||
if (type) {
|
||||
this.mgmtService.addAppKey(
|
||||
this.projectId,
|
||||
this.appId,
|
||||
type,
|
||||
date ? date : undefined,
|
||||
).then((response) => {
|
||||
if (response) {
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
}, 1000);
|
||||
this.mgmtService
|
||||
.addAppKey(this.projectId, this.appId, type, date ? date : undefined)
|
||||
.then((response) => {
|
||||
if (response) {
|
||||
setTimeout(() => {
|
||||
this.refreshPage();
|
||||
}, 1000);
|
||||
|
||||
this.dialog.open(ShowKeyDialogComponent, {
|
||||
data: {
|
||||
key: response,
|
||||
type: AddKeyDialogType.AUTHNKEY,
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
}
|
||||
}).catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
this.dialog.open(ShowKeyDialogComponent, {
|
||||
data: {
|
||||
key: response,
|
||||
type: AddKeyDialogType.AUTHNKEY,
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -126,14 +127,17 @@ export class ClientKeysComponent implements OnInit {
|
||||
private async getData(limit: number, offset: number): Promise<void> {
|
||||
this.loadingSubject.next(true);
|
||||
if (this.projectId && this.appId) {
|
||||
this.mgmtService.listAppKeys(this.projectId, this.appId, limit, offset).then(resp => {
|
||||
this.keyResult = resp;
|
||||
this.dataSource.data = this.keyResult.resultList;
|
||||
this.loadingSubject.next(false);
|
||||
}).catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
this.loadingSubject.next(false);
|
||||
});
|
||||
this.mgmtService
|
||||
.listAppKeys(this.projectId, this.appId, limit, offset)
|
||||
.then((resp) => {
|
||||
this.keyResult = resp;
|
||||
this.dataSource.data = this.keyResult.resultList;
|
||||
this.loadingSubject.next(false);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
this.loadingSubject.next(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,14 +9,14 @@
|
||||
class="logo"
|
||||
alt="home logo"
|
||||
*ngIf="isDarkTheme; else customlighttheme"
|
||||
[src]="labelpolicy?.iconUrlDark ? labelpolicy.iconUrlDark : './assets/images/zitadel-logo-solo-light.svg'"
|
||||
[src]="labelpolicy.iconUrlDark ? labelpolicy.iconUrlDark : './assets/images/zitadel-logo-solo-light.svg'"
|
||||
(error)="errorHandler($event, './assets/images/zitadel-logo-solo-light.svg')"
|
||||
/>
|
||||
<ng-template #customlighttheme>
|
||||
<img
|
||||
alt="home logo"
|
||||
class="logo"
|
||||
[src]="labelpolicy?.iconUrl ? labelpolicy.iconUrl : './assets/images/zitadel-logo-solo-dark.svg'"
|
||||
[src]="labelpolicy.iconUrl ? labelpolicy.iconUrl : './assets/images/zitadel-logo-solo-dark.svg'"
|
||||
(error)="errorHandler($event, './assets/images/zitadel-logo-solo-dark.svg')"
|
||||
/>
|
||||
</ng-template>
|
||||
@ -78,7 +78,7 @@
|
||||
|
||||
<div class="org-context">
|
||||
<a *ngIf="org" matRipple [matRippleUnbounded]="false" class="org-link" id="orglink" [routerLink]="['/org']">
|
||||
{{ org?.name ? org.name : 'NO NAME' }}</a
|
||||
{{ org.name ? org.name : 'NO NAME' }}</a
|
||||
>
|
||||
|
||||
<div class="org-context-wrapper" *ngIf="org">
|
||||
@ -212,7 +212,7 @@
|
||||
class="avatar-toggle dontcloseonclick"
|
||||
[active]="showAccount"
|
||||
[avatarUrl]="user.human?.profile?.avatarUrl || ''"
|
||||
[forColor]="user?.preferredLoginName || ''"
|
||||
[forColor]="user.preferredLoginName || ''"
|
||||
[name]="
|
||||
user.human?.profile?.displayName
|
||||
? user.human?.profile?.displayName ?? ''
|
||||
|
@ -21,8 +21,8 @@ export class HeaderComponent implements OnDestroy {
|
||||
@ViewChild('input', { static: false }) input!: ElementRef;
|
||||
|
||||
@Input() public isDarkTheme: boolean = true;
|
||||
@Input() public user!: User.AsObject;
|
||||
@Input() public labelpolicy!: LabelPolicy.AsObject;
|
||||
@Input() public user?: User.AsObject;
|
||||
@Input() public labelpolicy?: LabelPolicy.AsObject;
|
||||
public showOrgContext: boolean = false;
|
||||
|
||||
public orgs$: Observable<Org.AsObject[]> = of([]);
|
||||
|
@ -9,9 +9,9 @@ import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { ListIDPsResponse } from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import { IDP, IDPLoginPolicyLink, IDPOwnerType, IDPState, IDPStylingType } from 'src/app/proto/generated/zitadel/idp_pb';
|
||||
import {
|
||||
AddCustomLoginPolicyRequest,
|
||||
AddCustomLoginPolicyResponse,
|
||||
ListOrgIDPsResponse,
|
||||
AddCustomLoginPolicyRequest,
|
||||
AddCustomLoginPolicyResponse,
|
||||
ListOrgIDPsResponse,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { LoginPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
@ -33,7 +33,7 @@ export class IdpTableComponent implements OnInit {
|
||||
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
|
||||
public dataSource: MatTableDataSource<IDP.AsObject> = new MatTableDataSource<IDP.AsObject>();
|
||||
public selection: SelectionModel<IDP.AsObject> = new SelectionModel<IDP.AsObject>(true, []);
|
||||
public idpResult!: ListIDPsResponse.AsObject | ListOrgIDPsResponse.AsObject;
|
||||
public idpResult?: ListIDPsResponse.AsObject | ListOrgIDPsResponse.AsObject;
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<cnsl-top-view
|
||||
title="{{ idp?.name ? idp.name : ('IDP.DETAIL.TITLE' | translate) }}"
|
||||
title="{{ idp?.name ? idp?.name : ('IDP.DETAIL.TITLE' | translate) }}"
|
||||
[sub]="idp?.oidcConfig ? ('IDP.TYPES.1' | translate) : idp?.jwtConfig ? ('IDP.TYPES.3' | translate) : ''"
|
||||
[isActive]="idp?.state === IDPState.IDP_STATE_ACTIVE"
|
||||
[isInactive]="idp?.state === IDPState.IDP_STATE_INACTIVE"
|
||||
|
@ -8,15 +8,15 @@ import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
import {
|
||||
UpdateIDPJWTConfigRequest,
|
||||
UpdateIDPOIDCConfigRequest,
|
||||
UpdateIDPRequest,
|
||||
UpdateIDPJWTConfigRequest,
|
||||
UpdateIDPOIDCConfigRequest,
|
||||
UpdateIDPRequest,
|
||||
} from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import { IDP, IDPState, IDPStylingType, OIDCMappingField } from 'src/app/proto/generated/zitadel/idp_pb';
|
||||
import {
|
||||
UpdateOrgIDPJWTConfigRequest,
|
||||
UpdateOrgIDPOIDCConfigRequest,
|
||||
UpdateOrgIDPRequest,
|
||||
UpdateOrgIDPJWTConfigRequest,
|
||||
UpdateOrgIDPOIDCConfigRequest,
|
||||
UpdateOrgIDPRequest,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||
@ -42,7 +42,7 @@ export class IdpComponent implements OnDestroy {
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
public readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE];
|
||||
|
||||
public idp!: IDP.AsObject;
|
||||
public idp?: IDP.AsObject;
|
||||
private destroy$: Subject<void> = new Subject();
|
||||
public projectId: string = '';
|
||||
|
||||
@ -189,7 +189,7 @@ export class IdpComponent implements OnDestroy {
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((resp) => {
|
||||
if (resp) {
|
||||
if (this.idp && resp) {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
(this.service as ManagementService)
|
||||
.removeOrgIDP(this.idp.id)
|
||||
@ -217,21 +217,21 @@ export class IdpComponent implements OnDestroy {
|
||||
|
||||
public changeState(state: IDPState): void {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
if (state === IDPState.IDP_STATE_ACTIVE) {
|
||||
if (state === IDPState.IDP_STATE_ACTIVE && this.idp) {
|
||||
(this.service as ManagementService)
|
||||
.reactivateOrgIDP(this.idp.id)
|
||||
.then(() => {
|
||||
this.idp.state = state;
|
||||
this.idp!.state = state;
|
||||
this.toast.showInfo('IDP.TOAST.REACTIVATED', true);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else if (state === IDPState.IDP_STATE_INACTIVE) {
|
||||
} else if (state === IDPState.IDP_STATE_INACTIVE && this.idp) {
|
||||
(this.service as ManagementService)
|
||||
.deactivateOrgIDP(this.idp.id)
|
||||
.then(() => {
|
||||
this.idp.state = state;
|
||||
this.idp!.state = state;
|
||||
this.toast.showInfo('IDP.TOAST.DEACTIVATED', true);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
@ -239,21 +239,21 @@ export class IdpComponent implements OnDestroy {
|
||||
});
|
||||
}
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||
if (state === IDPState.IDP_STATE_ACTIVE) {
|
||||
if (state === IDPState.IDP_STATE_ACTIVE && this.idp) {
|
||||
(this.service as AdminService)
|
||||
.reactivateIDP(this.idp.id)
|
||||
.then(() => {
|
||||
this.idp.state = state;
|
||||
this.idp!.state = state;
|
||||
this.toast.showInfo('IDP.TOAST.REACTIVATED', true);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else if (state === IDPState.IDP_STATE_INACTIVE) {
|
||||
} else if (state === IDPState.IDP_STATE_INACTIVE && this.idp) {
|
||||
(this.service as AdminService)
|
||||
.deactivateIDP(this.idp.id)
|
||||
.then(() => {
|
||||
this.idp.state = state;
|
||||
this.idp!.state = state;
|
||||
this.toast.showInfo('IDP.TOAST.DEACTIVATED', true);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
@ -264,7 +264,7 @@ export class IdpComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
public updateIdp(): void {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT && this.idp) {
|
||||
const req = new UpdateOrgIDPRequest();
|
||||
|
||||
req.setIdpId(this.idp.id);
|
||||
@ -280,7 +280,7 @@ export class IdpComponent implements OnDestroy {
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN && this.idp) {
|
||||
const req = new UpdateIDPRequest();
|
||||
|
||||
req.setIdpId(this.idp.id);
|
||||
@ -300,7 +300,7 @@ export class IdpComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
public updateOidcConfig(): void {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT && this.idp) {
|
||||
const req = new UpdateOrgIDPOIDCConfigRequest();
|
||||
|
||||
req.setIdpId(this.idp.id);
|
||||
@ -319,7 +319,7 @@ export class IdpComponent implements OnDestroy {
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN && this.idp) {
|
||||
const req = new UpdateIDPOIDCConfigRequest();
|
||||
|
||||
req.setIdpId(this.idp.id);
|
||||
@ -342,7 +342,7 @@ export class IdpComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
public updateJwtConfig(): void {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT && this.idp) {
|
||||
const req = new UpdateOrgIDPJWTConfigRequest();
|
||||
|
||||
req.setIdpId(this.idp.id);
|
||||
@ -360,7 +360,7 @@ export class IdpComponent implements OnDestroy {
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN && this.idp) {
|
||||
const req = new UpdateIDPJWTConfigRequest();
|
||||
|
||||
req.setIdpId(this.idp.id);
|
||||
|
@ -257,31 +257,31 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="info-wrapper">
|
||||
<div class="info-wrapper" *ngIf="app">
|
||||
<p class="info-row-title">{{ 'APP.OIDC.INFO.CLIENTID' | translate }}</p>
|
||||
<div class="copy-row" *ngIf="app?.oidcConfig?.clientId">
|
||||
<div class="copy-row" *ngIf="app.oidcConfig?.clientId">
|
||||
<button
|
||||
*ngIf="app.oidcConfig && app.oidcConfig?.clientId"
|
||||
[disabled]="copied === app.oidcConfig?.clientId"
|
||||
[matTooltip]="(copied !== app.oidcConfig?.clientId ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
[disabled]="copied === app.oidcConfig.clientId"
|
||||
[matTooltip]="(copied !== app.oidcConfig.clientId ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="app.oidcConfig.clientId"
|
||||
(copiedValue)="copied = $event"
|
||||
>
|
||||
{{ app.oidcConfig?.clientId }}
|
||||
{{ app.oidcConfig.clientId }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="copy-row" *ngIf="app?.apiConfig?.clientId">
|
||||
<div class="copy-row" *ngIf="app.apiConfig?.clientId">
|
||||
<button
|
||||
*ngIf="app && app.apiConfig && app.apiConfig.clientId"
|
||||
[disabled]="copied === app.apiConfig?.clientId"
|
||||
[matTooltip]="(copied !== app.apiConfig?.clientId ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
[disabled]="copied === app.apiConfig.clientId"
|
||||
[matTooltip]="(copied !== app.apiConfig.clientId ? 'ACTIONS.COPY' : 'ACTIONS.COPIED') | translate"
|
||||
cnslCopyToClipboard
|
||||
[valueToCopy]="app.apiConfig.clientId"
|
||||
(copiedValue)="copied = $event"
|
||||
>
|
||||
{{ app.apiConfig?.clientId }}
|
||||
{{ app.apiConfig.clientId }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -22,12 +22,12 @@ import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
|
||||
styleUrls: ['./machine-keys.component.scss'],
|
||||
})
|
||||
export class MachineKeysComponent implements OnInit {
|
||||
@Input() userId!: string;
|
||||
@Input() userId?: string;
|
||||
|
||||
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
|
||||
public dataSource: MatTableDataSource<Key.AsObject> = new MatTableDataSource<Key.AsObject>();
|
||||
public selection: SelectionModel<Key.AsObject> = new SelectionModel<Key.AsObject>(true, []);
|
||||
public keyResult!: ListMachineKeysResponse.AsObject;
|
||||
public keyResult?: ListMachineKeysResponse.AsObject;
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
@Input() public displayedColumns: string[] = ['id', 'type', 'creationDate', 'expirationDate', 'actions'];
|
||||
@ -64,29 +64,32 @@ export class MachineKeysComponent implements OnInit {
|
||||
}
|
||||
|
||||
public deleteKey(key: Key.AsObject): void {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.DELETE',
|
||||
cancelKey: 'ACTIONS.CANCEL',
|
||||
titleKey: 'USER.MACHINE.DIALOG.DELETE_KEY.TITLE',
|
||||
descriptionKey: 'USER.MACHINE.DIALOG.DELETE_KEY.DESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
dialogRef.afterClosed().subscribe((resp) => {
|
||||
if (resp) {
|
||||
this.mgmtService
|
||||
.removeMachineKey(key.id, this.userId)
|
||||
.then(() => {
|
||||
this.selection.clear();
|
||||
this.toast.showInfo('USER.TOAST.SELECTEDKEYSDELETED', true);
|
||||
this.changePage();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
if (this.userId) {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.DELETE',
|
||||
cancelKey: 'ACTIONS.CANCEL',
|
||||
titleKey: 'USER.MACHINE.DIALOG.DELETE_KEY.TITLE',
|
||||
descriptionKey: 'USER.MACHINE.DIALOG.DELETE_KEY.DESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((resp) => {
|
||||
if (resp && this.userId) {
|
||||
this.mgmtService
|
||||
.removeMachineKey(key.id, this.userId)
|
||||
.then(() => {
|
||||
this.selection.clear();
|
||||
this.toast.showInfo('USER.TOAST.SELECTEDKEYSDELETED', true);
|
||||
this.changePage();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public openAddKey(): void {
|
||||
@ -111,7 +114,7 @@ export class MachineKeysComponent implements OnInit {
|
||||
date = ts;
|
||||
}
|
||||
|
||||
if (type) {
|
||||
if (type && this.userId) {
|
||||
this.mgmtService
|
||||
.addMachineKey(this.userId, type, date)
|
||||
.then((response) => {
|
||||
|
@ -1,7 +1,12 @@
|
||||
<cnsl-refresh-table *ngIf="dataSource" (refreshed)="changePage()" [dataSize]="dataSource.totalResult"
|
||||
[timestamp]="dataSource.viewTimestamp" [hideRefresh]="true" [selection]="selection"
|
||||
[loading]="dataSource?.loading$ | async">
|
||||
|
||||
<cnsl-refresh-table
|
||||
*ngIf="dataSource"
|
||||
(refreshed)="changePage()"
|
||||
[dataSize]="dataSource.totalResult"
|
||||
[timestamp]="dataSource.viewTimestamp"
|
||||
[hideRefresh]="true"
|
||||
[selection]="selection"
|
||||
[loading]="dataSource.loading$ | async"
|
||||
>
|
||||
<ng-container actions *ngIf="selection.hasValue()">
|
||||
<ng-content select="[selectactions]"></ng-content>
|
||||
</ng-container>
|
||||
@ -14,54 +19,73 @@
|
||||
<table mat-table class="table" aria-label="Elements" [dataSource]="dataSource">
|
||||
<ng-container matColumnDef="select">
|
||||
<th class="selection" mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox [disabled]="false" color="primary" (change)="$event ? masterToggle() : null"
|
||||
<mat-checkbox
|
||||
[disabled]="false"
|
||||
color="primary"
|
||||
(change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()">
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td class="selection" mat-cell *matCellDef="let row">
|
||||
<mat-checkbox [disabled]="false" color="primary" (click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null" [checked]="selection.isSelected(row)">
|
||||
|
||||
<mat-checkbox
|
||||
[disabled]="false"
|
||||
color="primary"
|
||||
(click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="displayName">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MEMBERSHIPS.DISPLAYNAME' | translate }} </th>
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'USER.MEMBERSHIPS.DISPLAYNAME' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let membership">
|
||||
{{membership.displayName}} </td>
|
||||
{{ membership.displayName }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="type">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MEMBERSHIPS.TYPE' | translate }} </th>
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'USER.MEMBERSHIPS.TYPE' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let membership">
|
||||
<span class="state">{{getType(membership)}}</span>
|
||||
<span class="state">{{ getType(membership) }}</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="orgId">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MEMBERSHIPS.ORGID' | translate }} </th>
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'USER.MEMBERSHIPS.ORGID' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let membership">
|
||||
{{membership.orgId}} </td>
|
||||
{{ membership.orgId }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="rolesList">
|
||||
<th mat-header-cell *matHeaderCellDef class="role-row"> {{ 'ROLESLABEL' | translate }} </th>
|
||||
<th mat-header-cell *matHeaderCellDef class="role-row">{{ 'ROLESLABEL' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let membership">
|
||||
<div class="membership-line">
|
||||
<mat-chip-list class="cnsl-chip-list" aria-label="role selection">
|
||||
<mat-chip class="cnsl-chip" *ngFor="let role of membership.rolesList" [removable]="!!userId"
|
||||
[selectable]="false" (removed)="removeRole(membership, role)">
|
||||
<mat-chip
|
||||
class="cnsl-chip"
|
||||
*ngFor="let role of membership.rolesList"
|
||||
[removable]="!!userId"
|
||||
[selectable]="false"
|
||||
(removed)="removeRole(membership, role)"
|
||||
>
|
||||
<div class="cnsl-chip-dot" [style.background]="getColor(role)"></div>
|
||||
<span>{{role | roletransform}}</span>
|
||||
<span>{{ role | roletransform }}</span>
|
||||
<button *ngIf="!!userId" matChipRemove>
|
||||
<mat-icon>cancel</mat-icon>
|
||||
</button>
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
<button matTooltip="{{'ACTIONS.EDIT' | translate}}" (click)="goto(membership)" mat-icon-button
|
||||
class="goto-btn">
|
||||
<button
|
||||
matTooltip="{{ 'ACTIONS.EDIT' | translate }}"
|
||||
(click)="goto(membership)"
|
||||
mat-icon-button
|
||||
class="goto-btn"
|
||||
>
|
||||
<i class="las la-angle-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
@ -69,12 +93,18 @@
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;">
|
||||
</tr>
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
<cnsl-paginator *ngIf="dataSource" class="paginator" #paginator [timestamp]="dataSource?.viewTimestamp"
|
||||
[pageSize]="INITIALPAGESIZE" [length]="dataSource.totalResult" [pageSizeOptions]="[25, 50, 100, 250]"
|
||||
(page)="changePage($event)">
|
||||
<cnsl-paginator
|
||||
*ngIf="dataSource"
|
||||
class="paginator"
|
||||
#paginator
|
||||
[timestamp]="dataSource.viewTimestamp"
|
||||
[pageSize]="INITIALPAGESIZE"
|
||||
[length]="dataSource.totalResult"
|
||||
[pageSizeOptions]="[25, 50, 100, 250]"
|
||||
(page)="changePage($event)"
|
||||
>
|
||||
</cnsl-paginator>
|
||||
</cnsl-refresh-table>
|
||||
</cnsl-refresh-table>
|
||||
|
@ -28,8 +28,8 @@ export class MembershipsTableComponent implements OnInit, OnDestroy {
|
||||
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
|
||||
@ViewChild(MatTable) public table!: MatTable<Membership.AsObject>;
|
||||
@Input() public userId: string = '';
|
||||
public dataSource!: MembershipsDataSource;
|
||||
public selection: SelectionModel<any> = new SelectionModel<any>(true, []);
|
||||
public dataSource: MembershipsDataSource = new MembershipsDataSource(this.authService, this.mgmtService);
|
||||
public selection: SelectionModel<Membership.AsObject> = new SelectionModel<Membership.AsObject>(true, []);
|
||||
|
||||
@Output() public changedSelection: EventEmitter<any[]> = new EventEmitter();
|
||||
@Output() public deleteMembership: EventEmitter<Membership.AsObject> = new EventEmitter();
|
||||
@ -51,8 +51,6 @@ export class MembershipsTableComponent implements OnInit, OnDestroy {
|
||||
private workflowService: OverlayWorkflowService,
|
||||
private storageService: StorageService,
|
||||
) {
|
||||
this.dataSource = new MembershipsDataSource(this.authService, this.mgmtService);
|
||||
|
||||
this.selection.changed.pipe(takeUntil(this.destroyed)).subscribe((_) => {
|
||||
this.changedSelection.emit(this.selection.selected);
|
||||
});
|
||||
|
@ -1,12 +1,19 @@
|
||||
<div class="validation-col" *ngIf="this.policy">
|
||||
<div class="val" *ngIf="this.policy.minLength">
|
||||
<div class="validation-col" *ngIf="policy">
|
||||
<div class="val" *ngIf="policy.minLength">
|
||||
<i *ngIf="password?.value?.length === 0; else showSpinner" class="las la-times red"></i>
|
||||
|
||||
<ng-template #showSpinner>
|
||||
<div *ngIf="(password?.errors?.minlength || password?.value?.length === 0) as currentError; else trueminlength"
|
||||
class="complexity-sp-wrapper">
|
||||
<mat-progress-spinner class="complexity-spinner" diameter="20" [color]="currentError ? 'warn': 'valid'"
|
||||
mode="determinate" [value]="(password?.value?.length / policy.minLength) * 100">
|
||||
<div
|
||||
*ngIf="password?.errors?.minlength || password?.value?.length === 0 as currentError; else trueminlength"
|
||||
class="complexity-sp-wrapper"
|
||||
>
|
||||
<mat-progress-spinner
|
||||
class="complexity-spinner"
|
||||
diameter="20"
|
||||
[color]="currentError ? 'warn' : 'valid'"
|
||||
mode="determinate"
|
||||
[value]="(password?.value?.length / policy.minLength) * 100"
|
||||
>
|
||||
</mat-progress-spinner>
|
||||
</div>
|
||||
</ng-template>
|
||||
@ -14,8 +21,10 @@
|
||||
<i class="las la-check green"></i>
|
||||
</ng-template>
|
||||
|
||||
<span class="cnsl-secondary-text">{{ 'USER.PASSWORD.MINLENGTHERROR' | translate: {value: policy?.minLength} }}
|
||||
({{password?.value?.length}}/{{ policy.minLength}})
|
||||
<span class="cnsl-secondary-text"
|
||||
>{{ 'USER.PASSWORD.MINLENGTHERROR' | translate: { value: policy.minLength } }} ({{ password?.value?.length }}/{{
|
||||
policy.minLength
|
||||
}})
|
||||
</span>
|
||||
</div>
|
||||
<div class="val" *ngIf="this.policy.hasSymbol">
|
||||
@ -38,4 +47,4 @@
|
||||
<i *ngIf="!password?.errors?.lowerCaseValidator" class="las la-check green"></i>
|
||||
<span class="cnsl-secondary-text">{{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -57,7 +57,7 @@
|
||||
(typeRemoved)="removeFactor($event)"
|
||||
(typeAdded)="addFactor($event)"
|
||||
[disabled]="
|
||||
loginData?.passwordlessType === PasswordlessType.PASSWORDLESS_TYPE_NOT_ALLOWED ||
|
||||
loginData.passwordlessType === PasswordlessType.PASSWORDLESS_TYPE_NOT_ALLOWED ||
|
||||
([
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.policy.write'
|
||||
|
@ -4,13 +4,13 @@ import { MatDialog } from '@angular/material/dialog';
|
||||
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
||||
import { take } from 'rxjs';
|
||||
import {
|
||||
GetLoginPolicyResponse as AdminGetLoginPolicyResponse,
|
||||
UpdateLoginPolicyRequest,
|
||||
UpdateLoginPolicyResponse,
|
||||
GetLoginPolicyResponse as AdminGetLoginPolicyResponse,
|
||||
UpdateLoginPolicyRequest,
|
||||
UpdateLoginPolicyResponse,
|
||||
} from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import {
|
||||
AddCustomLoginPolicyRequest,
|
||||
GetLoginPolicyResponse as MgmtGetLoginPolicyResponse,
|
||||
AddCustomLoginPolicyRequest,
|
||||
GetLoginPolicyResponse as MgmtGetLoginPolicyResponse,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { LoginPolicy, PasswordlessType } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
@ -34,7 +34,7 @@ export class LoginPolicyComponent implements OnInit {
|
||||
PasswordlessType.PASSWORDLESS_TYPE_NOT_ALLOWED,
|
||||
PasswordlessType.PASSWORDLESS_TYPE_ALLOWED,
|
||||
];
|
||||
public loginData!: LoginPolicy.AsObject;
|
||||
public loginData?: LoginPolicy.AsObject;
|
||||
|
||||
public service!: ManagementService | AdminService;
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
@ -43,22 +43,20 @@ export class LoginPolicyComponent implements OnInit {
|
||||
public loading: boolean = false;
|
||||
public InfoSectionType: any = InfoSectionType;
|
||||
public PasswordlessType: any = PasswordlessType;
|
||||
public lifetimeForm!: UntypedFormGroup;
|
||||
public lifetimeForm: UntypedFormGroup = this.fb.group({
|
||||
passwordCheckLifetime: [{ disabled: true, value: 240 }, [Validators.required]],
|
||||
externalLoginCheckLifetime: [{ disabled: true, value: 12 }, [Validators.required]],
|
||||
mfaInitSkipLifetime: [{ disabled: true, value: 720 }, [Validators.required]],
|
||||
secondFactorCheckLifetime: [{ disabled: true, value: 12 }, [Validators.required]],
|
||||
multiFactorCheckLifetime: [{ disabled: true, value: 12 }, [Validators.required]],
|
||||
});
|
||||
constructor(
|
||||
private toast: ToastService,
|
||||
private injector: Injector,
|
||||
private fb: UntypedFormBuilder,
|
||||
private authService: GrpcAuthService,
|
||||
private dialog: MatDialog,
|
||||
) {
|
||||
this.lifetimeForm = this.fb.group({
|
||||
passwordCheckLifetime: [{ disabled: true, value: 240 }, [Validators.required]],
|
||||
externalLoginCheckLifetime: [{ disabled: true, value: 12 }, [Validators.required]],
|
||||
mfaInitSkipLifetime: [{ disabled: true, value: 720 }, [Validators.required]],
|
||||
secondFactorCheckLifetime: [{ disabled: true, value: 12 }, [Validators.required]],
|
||||
multiFactorCheckLifetime: [{ disabled: true, value: 12 }, [Validators.required]],
|
||||
});
|
||||
}
|
||||
) {}
|
||||
|
||||
public fetchData(): void {
|
||||
this.getData()
|
||||
@ -143,68 +141,72 @@ export class LoginPolicyComponent implements OnInit {
|
||||
}
|
||||
|
||||
private async updateData(): Promise<UpdateLoginPolicyResponse.AsObject> {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
const mgmtreq = new AddCustomLoginPolicyRequest();
|
||||
mgmtreq.setAllowExternalIdp(this.loginData.allowExternalIdp);
|
||||
mgmtreq.setAllowRegister(this.loginData.allowRegister);
|
||||
mgmtreq.setAllowUsernamePassword(this.loginData.allowUsernamePassword);
|
||||
mgmtreq.setForceMfa(this.loginData.forceMfa);
|
||||
mgmtreq.setPasswordlessType(this.loginData.passwordlessType);
|
||||
mgmtreq.setHidePasswordReset(this.loginData.hidePasswordReset);
|
||||
mgmtreq.setMultiFactorsList(this.loginData.multiFactorsList);
|
||||
mgmtreq.setSecondFactorsList(this.loginData.secondFactorsList);
|
||||
if (this.loginData) {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
const mgmtreq = new AddCustomLoginPolicyRequest();
|
||||
mgmtreq.setAllowExternalIdp(this.loginData.allowExternalIdp);
|
||||
mgmtreq.setAllowRegister(this.loginData.allowRegister);
|
||||
mgmtreq.setAllowUsernamePassword(this.loginData.allowUsernamePassword);
|
||||
mgmtreq.setForceMfa(this.loginData.forceMfa);
|
||||
mgmtreq.setPasswordlessType(this.loginData.passwordlessType);
|
||||
mgmtreq.setHidePasswordReset(this.loginData.hidePasswordReset);
|
||||
mgmtreq.setMultiFactorsList(this.loginData.multiFactorsList);
|
||||
mgmtreq.setSecondFactorsList(this.loginData.secondFactorsList);
|
||||
|
||||
const pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 240) * 60 * 60);
|
||||
mgmtreq.setPasswordCheckLifetime(pcl);
|
||||
const pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 240) * 60 * 60);
|
||||
mgmtreq.setPasswordCheckLifetime(pcl);
|
||||
|
||||
const elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setExternalLoginCheckLifetime(elcl);
|
||||
const elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setExternalLoginCheckLifetime(elcl);
|
||||
|
||||
const misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 720) * 60 * 60);
|
||||
mgmtreq.setMfaInitSkipLifetime(misl);
|
||||
const misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 720) * 60 * 60);
|
||||
mgmtreq.setMfaInitSkipLifetime(misl);
|
||||
|
||||
const sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setSecondFactorCheckLifetime(sfcl);
|
||||
const sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setSecondFactorCheckLifetime(sfcl);
|
||||
|
||||
const mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setMultiFactorCheckLifetime(mficl);
|
||||
const mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
mgmtreq.setMultiFactorCheckLifetime(mficl);
|
||||
|
||||
mgmtreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
mgmtreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
mgmtreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
mgmtreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
|
||||
if (this.isDefault) {
|
||||
return (this.service as ManagementService).addCustomLoginPolicy(mgmtreq);
|
||||
} else {
|
||||
return (this.service as ManagementService).updateCustomLoginPolicy(mgmtreq);
|
||||
}
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
const adminreq = new UpdateLoginPolicyRequest();
|
||||
adminreq.setAllowExternalIdp(this.loginData.allowExternalIdp);
|
||||
adminreq.setAllowRegister(this.loginData.allowRegister);
|
||||
adminreq.setAllowUsernamePassword(this.loginData.allowUsernamePassword);
|
||||
adminreq.setForceMfa(this.loginData.forceMfa);
|
||||
adminreq.setPasswordlessType(this.loginData.passwordlessType);
|
||||
adminreq.setHidePasswordReset(this.loginData.hidePasswordReset);
|
||||
if (this.isDefault) {
|
||||
return (this.service as ManagementService).addCustomLoginPolicy(mgmtreq);
|
||||
} else {
|
||||
return (this.service as ManagementService).updateCustomLoginPolicy(mgmtreq);
|
||||
}
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
const adminreq = new UpdateLoginPolicyRequest();
|
||||
adminreq.setAllowExternalIdp(this.loginData.allowExternalIdp);
|
||||
adminreq.setAllowRegister(this.loginData.allowRegister);
|
||||
adminreq.setAllowUsernamePassword(this.loginData.allowUsernamePassword);
|
||||
adminreq.setForceMfa(this.loginData.forceMfa);
|
||||
adminreq.setPasswordlessType(this.loginData.passwordlessType);
|
||||
adminreq.setHidePasswordReset(this.loginData.hidePasswordReset);
|
||||
|
||||
const admin_pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 240) * 60 * 60);
|
||||
adminreq.setPasswordCheckLifetime(admin_pcl);
|
||||
const admin_pcl = new Duration().setSeconds((this.passwordCheckLifetime?.value ?? 240) * 60 * 60);
|
||||
adminreq.setPasswordCheckLifetime(admin_pcl);
|
||||
|
||||
const admin_elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
adminreq.setExternalLoginCheckLifetime(admin_elcl);
|
||||
const admin_elcl = new Duration().setSeconds((this.externalLoginCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
adminreq.setExternalLoginCheckLifetime(admin_elcl);
|
||||
|
||||
const admin_misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 720) * 60 * 60);
|
||||
adminreq.setMfaInitSkipLifetime(admin_misl);
|
||||
const admin_misl = new Duration().setSeconds((this.mfaInitSkipLifetime?.value ?? 720) * 60 * 60);
|
||||
adminreq.setMfaInitSkipLifetime(admin_misl);
|
||||
|
||||
const admin_sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
adminreq.setSecondFactorCheckLifetime(admin_sfcl);
|
||||
const admin_sfcl = new Duration().setSeconds((this.secondFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
adminreq.setSecondFactorCheckLifetime(admin_sfcl);
|
||||
|
||||
const admin_mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
adminreq.setMultiFactorCheckLifetime(admin_mficl);
|
||||
adminreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
adminreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
const admin_mficl = new Duration().setSeconds((this.multiFactorCheckLifetime?.value ?? 12) * 60 * 60);
|
||||
adminreq.setMultiFactorCheckLifetime(admin_mficl);
|
||||
adminreq.setIgnoreUnknownUsernames(this.loginData.ignoreUnknownUsernames);
|
||||
adminreq.setDefaultRedirectUri(this.loginData.defaultRedirectUri);
|
||||
|
||||
return (this.service as AdminService).updateLoginPolicy(adminreq);
|
||||
return (this.service as AdminService).updateLoginPolicy(adminreq);
|
||||
}
|
||||
} else {
|
||||
return Promise.reject();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,10 +72,10 @@
|
||||
*ngIf="twilio"
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: twilio?.state === SMSProviderConfigState.SMS_PROVIDER_CONFIG_ACTIVE,
|
||||
inactive: twilio?.state === SMSProviderConfigState.SMS_PROVIDER_CONFIG_INACTIVE
|
||||
active: twilio.state === SMSProviderConfigState.SMS_PROVIDER_CONFIG_ACTIVE,
|
||||
inactive: twilio.state === SMSProviderConfigState.SMS_PROVIDER_CONFIG_INACTIVE
|
||||
}"
|
||||
>{{ 'SETTING.SMS.SMSPROVIDERSTATE.' + twilio?.state | translate }}</span
|
||||
>{{ 'SETTING.SMS.SMSPROVIDERSTATE.' + twilio.state | translate }}</span
|
||||
>
|
||||
|
||||
<span class="fill-space"></span>
|
||||
|
@ -28,7 +28,7 @@
|
||||
<button mat-icon-button (click)="decrementLength()" [disabled]="(['policy.write'] | hasRole | async) === false">
|
||||
<mat-icon>remove</mat-icon>
|
||||
</button>
|
||||
<span>{{ complexityData?.minLength }}</span>
|
||||
<span>{{ complexityData.minLength }}</span>
|
||||
<button mat-icon-button (click)="incrementLength()" [disabled]="(['policy.write'] | hasRole | async) === false">
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
|
@ -1,11 +1,7 @@
|
||||
import { Component, Injector, Input, OnInit, Type } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import {
|
||||
GetPasswordComplexityPolicyResponse as AdminGetPasswordComplexityPolicyResponse,
|
||||
} from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import {
|
||||
GetPasswordComplexityPolicyResponse as MgmtGetPasswordComplexityPolicyResponse,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { GetPasswordComplexityPolicyResponse as AdminGetPasswordComplexityPolicyResponse } from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import { GetPasswordComplexityPolicyResponse as MgmtGetPasswordComplexityPolicyResponse } from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { PasswordComplexityPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
@ -24,7 +20,7 @@ export class PasswordComplexityPolicyComponent implements OnInit {
|
||||
@Input() public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
||||
public service!: ManagementService | AdminService;
|
||||
|
||||
public complexityData!: PasswordComplexityPolicy.AsObject;
|
||||
public complexityData?: PasswordComplexityPolicy.AsObject;
|
||||
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
|
||||
@ -110,11 +106,44 @@ export class PasswordComplexityPolicyComponent implements OnInit {
|
||||
}
|
||||
|
||||
public savePolicy(): void {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
if ((this.complexityData as PasswordComplexityPolicy.AsObject).isDefault) {
|
||||
(this.service as ManagementService)
|
||||
.addCustomPasswordComplexityPolicy(
|
||||
if (this.complexityData) {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
if ((this.complexityData as PasswordComplexityPolicy.AsObject).isDefault) {
|
||||
(this.service as ManagementService)
|
||||
.addCustomPasswordComplexityPolicy(
|
||||
this.complexityData.hasLowercase,
|
||||
this.complexityData.hasUppercase,
|
||||
this.complexityData.hasNumber,
|
||||
this.complexityData.hasSymbol,
|
||||
this.complexityData.minLength,
|
||||
)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else {
|
||||
(this.service as ManagementService)
|
||||
.updateCustomPasswordComplexityPolicy(
|
||||
this.complexityData.hasLowercase,
|
||||
this.complexityData.hasUppercase,
|
||||
this.complexityData.hasNumber,
|
||||
this.complexityData.hasSymbol,
|
||||
this.complexityData.minLength,
|
||||
)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
(this.service as AdminService)
|
||||
.updatePasswordComplexityPolicy(
|
||||
this.complexityData.hasLowercase,
|
||||
this.complexityData.hasUppercase,
|
||||
this.complexityData.hasNumber,
|
||||
@ -127,39 +156,8 @@ export class PasswordComplexityPolicyComponent implements OnInit {
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else {
|
||||
(this.service as ManagementService)
|
||||
.updateCustomPasswordComplexityPolicy(
|
||||
this.complexityData.hasLowercase,
|
||||
this.complexityData.hasUppercase,
|
||||
this.complexityData.hasNumber,
|
||||
this.complexityData.hasSymbol,
|
||||
this.complexityData.minLength,
|
||||
)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
(this.service as AdminService)
|
||||
.updatePasswordComplexityPolicy(
|
||||
this.complexityData.hasLowercase,
|
||||
this.complexityData.hasUppercase,
|
||||
this.complexityData.hasNumber,
|
||||
this.complexityData.hasSymbol,
|
||||
this.complexityData.minLength,
|
||||
)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,8 +13,6 @@
|
||||
</button>
|
||||
</ng-template>
|
||||
|
||||
<!-- <cnsl-info-section class="default" *ngIf="isDefault"> {{ 'POLICY.DEFAULTLABEL' | translate }}</cnsl-info-section> -->
|
||||
|
||||
<cnsl-card *ngIf="lockoutData">
|
||||
<div class="lockout-content">
|
||||
<div class="row">
|
||||
@ -22,7 +20,7 @@
|
||||
<button [disabled]="(['policy.write'] | hasRole | async) === false" mat-icon-button (click)="decrementMaxAttempts()">
|
||||
<mat-icon>remove</mat-icon>
|
||||
</button>
|
||||
<span>{{ lockoutData?.maxPasswordAttempts }}</span>
|
||||
<span>{{ lockoutData.maxPasswordAttempts }}</span>
|
||||
<button [disabled]="(['policy.write'] | hasRole | async) === false" mat-icon-button (click)="incrementMaxAttempts()">
|
||||
<mat-icon>add</mat-icon>
|
||||
</button>
|
||||
|
@ -2,9 +2,7 @@ import { Component, Injector, Input, OnInit, Type } from '@angular/core';
|
||||
import { UntypedFormGroup } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { GetLockoutPolicyResponse as AdminGetPasswordLockoutPolicyResponse } from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import {
|
||||
GetLockoutPolicyResponse as MgmtGetPasswordLockoutPolicyResponse,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { GetLockoutPolicyResponse as MgmtGetPasswordLockoutPolicyResponse } from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { LockoutPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
@ -24,7 +22,7 @@ export class PasswordLockoutPolicyComponent implements OnInit {
|
||||
@Input() public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
|
||||
|
||||
public lockoutForm!: UntypedFormGroup;
|
||||
public lockoutData!: LockoutPolicy.AsObject;
|
||||
public lockoutData?: LockoutPolicy.AsObject;
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
public InfoSectionType: any = InfoSectionType;
|
||||
|
||||
@ -103,20 +101,10 @@ export class PasswordLockoutPolicyComponent implements OnInit {
|
||||
|
||||
public savePolicy(): void {
|
||||
let promise: Promise<any>;
|
||||
if (this.service instanceof AdminService) {
|
||||
promise = this.service
|
||||
.updateLockoutPolicy(this.lockoutData.maxPasswordAttempts)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
this.fetchData();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else {
|
||||
if ((this.lockoutData as LockoutPolicy.AsObject).isDefault) {
|
||||
if (this.lockoutData) {
|
||||
if (this.service instanceof AdminService) {
|
||||
promise = this.service
|
||||
.addCustomLockoutPolicy(this.lockoutData.maxPasswordAttempts)
|
||||
.updateLockoutPolicy(this.lockoutData.maxPasswordAttempts)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
this.fetchData();
|
||||
@ -125,15 +113,27 @@ export class PasswordLockoutPolicyComponent implements OnInit {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else {
|
||||
promise = this.service
|
||||
.updateCustomLockoutPolicy(this.lockoutData.maxPasswordAttempts)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
this.fetchData();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
if ((this.lockoutData as LockoutPolicy.AsObject).isDefault) {
|
||||
promise = (this.service as ManagementService)
|
||||
.addCustomLockoutPolicy(this.lockoutData.maxPasswordAttempts)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
this.fetchData();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else {
|
||||
promise = (this.service as ManagementService)
|
||||
.updateCustomLockoutPolicy(this.lockoutData.maxPasswordAttempts)
|
||||
.then(() => {
|
||||
this.toast.showInfo('POLICY.TOAST.SET', true);
|
||||
this.fetchData();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,11 @@
|
||||
[showSelectionActionButton]="showSelectionActionButton"
|
||||
*ngIf="projectId"
|
||||
(refreshed)="refreshPage()"
|
||||
[dataSize]="dataSource?.totalResult ?? 0"
|
||||
[dataSize]="dataSource.totalResult"
|
||||
[emitRefreshOnPreviousRoutes]="['/projects/' + projectId + '/roles/create']"
|
||||
[selection]="selection"
|
||||
[loading]="dataSource?.loading$ | async"
|
||||
[timestamp]="dataSource?.viewTimestamp"
|
||||
[loading]="dataSource.loading$ | async"
|
||||
[timestamp]="dataSource.viewTimestamp"
|
||||
>
|
||||
<ng-template cnslHasRole [hasRole]="['project.role.write:' + projectId, 'project.role.write']" actions>
|
||||
<a
|
||||
@ -126,7 +126,7 @@
|
||||
|
||||
<cnsl-paginator
|
||||
#paginator
|
||||
[timestamp]="dataSource?.viewTimestamp"
|
||||
[timestamp]="dataSource.viewTimestamp"
|
||||
[length]="dataSource.totalResult"
|
||||
[pageSize]="50"
|
||||
(page)="changePage()"
|
||||
|
@ -1,15 +1,19 @@
|
||||
<div class="refresh-table-header-row" [ngClass]="{'border-bottom': showBorder}">
|
||||
<div class="refresh-table-header-row" [ngClass]="{ 'border-bottom': showBorder }">
|
||||
<div class="refresh-table-row" *ngIf="selection.hasValue(); else leftActions">
|
||||
<div>
|
||||
<span class="count">{{selection?.selected?.length}}</span>
|
||||
<span class="count-desc">{{'ORG_DETAIL.TABLE.SELECTION' | translate}}</span>
|
||||
<span class="count">{{ selection.selected.length }}</span>
|
||||
<span class="count-desc">{{ 'ORG_DETAIL.TABLE.SELECTION' | translate }}</span>
|
||||
</div>
|
||||
|
||||
<span class="count-slash">|</span>
|
||||
<a mat-stroked-button [ngClass]="{'cnsl-action-button': showSelectionActionButton}" (click)="selection.clear()">
|
||||
<span>{{'ORG_DETAIL.TABLE.CLEAR' | translate}}</span>
|
||||
<cnsl-action-keys *ngIf="showSelectionActionButton" [doNotUseContrast]="true" [type]="ActionKeysType.CLEAR"
|
||||
(actionTriggered)="selection.clear()">
|
||||
<a mat-stroked-button [ngClass]="{ 'cnsl-action-button': showSelectionActionButton }" (click)="selection.clear()">
|
||||
<span>{{ 'ORG_DETAIL.TABLE.CLEAR' | translate }}</span>
|
||||
<cnsl-action-keys
|
||||
*ngIf="showSelectionActionButton"
|
||||
[doNotUseContrast]="true"
|
||||
[type]="ActionKeysType.CLEAR"
|
||||
(actionTriggered)="selection.clear()"
|
||||
>
|
||||
</cnsl-action-keys>
|
||||
</a>
|
||||
</div>
|
||||
@ -19,8 +23,13 @@
|
||||
<span class="fill-space"></span>
|
||||
<mat-spinner class="refresh-table-spinner" *ngIf="loading" diameter="20"></mat-spinner>
|
||||
|
||||
<button *ngIf="!hideRefresh" mat-icon-button (click)="emitRefresh()" class="refresh-table-icon-button"
|
||||
matTooltip="{{'ACTIONS.REFRESH' | translate}}">
|
||||
<button
|
||||
*ngIf="!hideRefresh"
|
||||
mat-icon-button
|
||||
(click)="emitRefresh()"
|
||||
class="refresh-table-icon-button"
|
||||
matTooltip="{{ 'ACTIONS.REFRESH' | translate }}"
|
||||
>
|
||||
<mat-icon class="icon">refresh</mat-icon>
|
||||
</button>
|
||||
|
||||
@ -28,4 +37,4 @@
|
||||
</div>
|
||||
<div class="table-wrapper">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -12,7 +12,7 @@
|
||||
"
|
||||
class="avatar"
|
||||
[name]="user.human.profile.displayName"
|
||||
[avatarUrl]="user.human.profile?.avatarUrl || ''"
|
||||
[avatarUrl]="user.human.profile.avatarUrl || ''"
|
||||
[forColor]="user.preferredLoginName"
|
||||
[size]="32"
|
||||
>
|
||||
@ -23,7 +23,7 @@
|
||||
</div>
|
||||
|
||||
<div class="user-name-column" *ngIf="user.human">
|
||||
<span>{{ user.human?.profile?.displayName }}</span>
|
||||
<span>{{ user.human.profile?.displayName }}</span>
|
||||
<span class="smaller cnsl-secondary-text">{{ user.preferredLoginName }}</span>
|
||||
</div>
|
||||
<div class="user-name-column" *ngIf="user.machine">
|
||||
@ -85,7 +85,7 @@
|
||||
"
|
||||
class="avatar"
|
||||
[name]="user.human.profile.displayName"
|
||||
[avatarUrl]="user.human.profile?.avatarUrl || ''"
|
||||
[avatarUrl]="user.human.profile.avatarUrl || ''"
|
||||
[forColor]="user.preferredLoginName"
|
||||
[size]="32"
|
||||
>
|
||||
|
@ -1,21 +1,12 @@
|
||||
<cnsl-refresh-table
|
||||
[loading]="dataSource?.loading$ | async"
|
||||
[loading]="dataSource.loading$ | async"
|
||||
(refreshed)="changePage()"
|
||||
[hideRefresh]="true"
|
||||
[emitRefreshOnPreviousRoutes]="refreshOnPreviousRoutes"
|
||||
[timestamp]="dataSource?.viewTimestamp"
|
||||
[dataSize]="dataSource?.totalResult ?? 0"
|
||||
[timestamp]="dataSource.viewTimestamp"
|
||||
[dataSize]="dataSource.totalResult"
|
||||
[selection]="selection"
|
||||
>
|
||||
<!-- <div leftActions class="user-grants-table-left-actions">
|
||||
<button class="user-grant-type-button" [ngClass]="{'active': type === undefined}"
|
||||
(click)="setType(undefined)">{{'PROJECT.GRANT.ALL' | translate}}</button>
|
||||
<button class="user-grant-type-button" [ngClass]="{'active': type === Type.TYPE_HUMAN}"
|
||||
(click)="setType(Type.TYPE_HUMAN)">{{'USER.TABLE.TYPES.HUMAN' | translate}}</button>
|
||||
<button class="user-grant-type-button" [ngClass]="{'active': type === Type.TYPE_MACHINE}"
|
||||
(click)="setType(Type.TYPE_MACHINE)">{{'USER.TABLE.TYPES.MACHINE' | translate}}</button>
|
||||
</div> -->
|
||||
|
||||
<button
|
||||
color="warn"
|
||||
matTooltip="{{ 'GRANTS.DELETE' | translate }}"
|
||||
@ -193,7 +184,7 @@
|
||||
<cnsl-paginator
|
||||
class="paginator"
|
||||
#paginator
|
||||
[timestamp]="dataSource?.viewTimestamp"
|
||||
[timestamp]="dataSource.viewTimestamp"
|
||||
[length]="dataSource.totalResult"
|
||||
[pageSize]="INITIAL_PAGE_SIZE"
|
||||
[length]="dataSource.totalResult"
|
||||
|
@ -38,10 +38,10 @@ export class UserGrantsComponent implements OnInit, AfterViewInit {
|
||||
@Input() context: UserGrantContext = UserGrantContext.NONE;
|
||||
@Input() refreshOnPreviousRoutes: string[] = [];
|
||||
|
||||
public dataSource!: UserGrantsDataSource;
|
||||
public dataSource: UserGrantsDataSource = new UserGrantsDataSource(this.userService);
|
||||
public selection: SelectionModel<UserGrant.AsObject> = new SelectionModel<UserGrant.AsObject>(true, []);
|
||||
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
|
||||
@ViewChild(MatTable) public table!: MatTable<UserGrant.AsObject>;
|
||||
@ViewChild(PaginatorComponent) public paginator?: PaginatorComponent;
|
||||
@ViewChild(MatTable) public table?: MatTable<UserGrant.AsObject>;
|
||||
|
||||
@Input() disableWrite: boolean = false;
|
||||
@Input() disableDelete: boolean = false;
|
||||
@ -85,8 +85,6 @@ export class UserGrantsComponent implements OnInit, AfterViewInit {
|
||||
];
|
||||
|
||||
ngOnInit(): void {
|
||||
this.dataSource = new UserGrantsDataSource(this.userService);
|
||||
|
||||
switch (this.context) {
|
||||
case UserGrantContext.OWNED_PROJECT:
|
||||
if (this.projectId) {
|
||||
@ -113,7 +111,7 @@ export class UserGrantsComponent implements OnInit, AfterViewInit {
|
||||
}
|
||||
|
||||
public ngAfterViewInit(): void {
|
||||
this.paginator.page.pipe(tap(() => this.loadGrantsPage(this.type))).subscribe();
|
||||
this.paginator?.page.pipe(tap(() => this.loadGrantsPage(this.type))).subscribe();
|
||||
}
|
||||
|
||||
public setType(type: Type | undefined): void {
|
||||
@ -271,8 +269,8 @@ export class UserGrantsComponent implements OnInit, AfterViewInit {
|
||||
public changePage(event?: PageEvent): void {
|
||||
this.dataSource.loadGrants(
|
||||
this.context,
|
||||
event?.pageIndex ?? this.paginator.pageIndex,
|
||||
event?.pageSize ?? this.paginator.pageSize,
|
||||
event?.pageIndex ?? this.paginator?.pageIndex ?? 0,
|
||||
event?.pageSize ?? this.paginator?.pageSize ?? this.INITIAL_PAGE_SIZE,
|
||||
{
|
||||
projectId: this.projectId,
|
||||
grantId: this.grantId,
|
||||
|
@ -2,7 +2,7 @@
|
||||
[hideRefresh]="true"
|
||||
[loading]="loading$ | async"
|
||||
(refreshed)="refreshPage()"
|
||||
[dataSize]="dataSource?.data?.length ?? 0"
|
||||
[dataSize]="dataSource.data.length"
|
||||
[timestamp]="actionsResult?.details?.viewTimestamp"
|
||||
[selection]="selection"
|
||||
>
|
||||
|
@ -10,9 +10,9 @@ import { PaginatorComponent } from 'src/app/modules/paginator/paginator.componen
|
||||
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
|
||||
import { Action, ActionState } from 'src/app/proto/generated/zitadel/action_pb';
|
||||
import {
|
||||
CreateActionRequest,
|
||||
ListActionsResponse,
|
||||
UpdateActionRequest,
|
||||
CreateActionRequest,
|
||||
ListActionsResponse,
|
||||
UpdateActionRequest,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
@ -28,7 +28,7 @@ export class ActionTableComponent implements OnInit {
|
||||
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
|
||||
public dataSource: MatTableDataSource<Action.AsObject> = new MatTableDataSource<Action.AsObject>();
|
||||
public selection: SelectionModel<Action.AsObject> = new SelectionModel<Action.AsObject>(true, []);
|
||||
public actionsResult!: ListActionsResponse.AsObject;
|
||||
public actionsResult?: ListActionsResponse.AsObject;
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
@Input() public displayedColumns: string[] = ['select', 'name', 'state', 'timeout', 'allowedToFail', 'actions'];
|
||||
@ -50,7 +50,7 @@ export class ActionTableComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getData(10, 0);
|
||||
this.getData(20, 0);
|
||||
}
|
||||
|
||||
public isAllSelected(): boolean {
|
||||
@ -84,7 +84,7 @@ export class ActionTableComponent implements OnInit {
|
||||
.deleteAction(action.id)
|
||||
.then(() => {
|
||||
this.toast.showInfo('FLOWS.DIALOG.DELETEACTION.DELETE_SUCCESS', true);
|
||||
this.getData(10, 0);
|
||||
this.getData(20, 0);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
|
@ -1,4 +1,4 @@
|
||||
<span class="title" mat-dialog-title>{{ 'ORG.PAGES.ORGDOMAIN.TITLE' | translate }} {{ domain.domainName }}</span>
|
||||
<span class="title" mat-dialog-title>{{ 'ORG.PAGES.ORGDOMAIN.TITLE' | translate }} {{ domain?.domainName }}</span>
|
||||
<div mat-dialog-content>
|
||||
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION' | translate }}</p>
|
||||
|
||||
@ -7,17 +7,17 @@
|
||||
}}</cnsl-info-section>
|
||||
|
||||
<p
|
||||
*ngIf="domain.validationType !== DomainValidationType.DOMAIN_VALIDATION_TYPE_UNSPECIFIED && !(dns || http)"
|
||||
*ngIf="domain?.validationType !== DomainValidationType.DOMAIN_VALIDATION_TYPE_UNSPECIFIED && !(dns || http)"
|
||||
class="desc"
|
||||
>
|
||||
{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_VALIDATION_ONGOING' | translate: domain }}
|
||||
{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_VALIDATION_ONGOING_TYPE' | translate }}
|
||||
{{ 'ORG.PAGES.ORGDOMAIN.TYPES.' + domain.validationType | translate }}
|
||||
{{ 'ORG.PAGES.ORGDOMAIN.TYPES.' + domain?.validationType | translate }}
|
||||
</p>
|
||||
|
||||
<div class="btn-container">
|
||||
<button
|
||||
[disabled]="domain.validationType === DomainValidationType.DOMAIN_VALIDATION_TYPE_UNSPECIFIED"
|
||||
[disabled]="domain?.validationType === DomainValidationType.DOMAIN_VALIDATION_TYPE_UNSPECIFIED"
|
||||
color="primary"
|
||||
type="submit"
|
||||
mat-raised-button
|
||||
@ -44,7 +44,7 @@
|
||||
|
||||
<div *ngIf="http">
|
||||
<p>HTTP TOKEN</p>
|
||||
<p class="entry">{{ http?.url }}.txt</p>
|
||||
<p class="entry">{{ http.url }}.txt</p>
|
||||
|
||||
<div class="btn-container">
|
||||
<button mat-stroked-button (click)="saveFile()" color="primary">{{ 'ORG.PAGES.DOWNLOAD_FILE' | translate }}</button>
|
||||
@ -57,8 +57,8 @@
|
||||
|
||||
<div *ngIf="dns">
|
||||
<p>DNS TOKEN</p>
|
||||
<div class="domain-line" *ngIf="dns?.token">
|
||||
<p class="entry">{{ dns?.token }}</p>
|
||||
<div class="domain-line" *ngIf="dns.token">
|
||||
<p class="entry">{{ dns.token }}</p>
|
||||
<button
|
||||
color="primary"
|
||||
[disabled]="copied === data.clientSecret"
|
||||
@ -76,7 +76,7 @@
|
||||
</button>
|
||||
<mat-spinner class="spinner" *ngIf="validating" diameter="20" mode="indeterminate"></mat-spinner>
|
||||
</div>
|
||||
<p class="entry">{{ dns?.url }}</p>
|
||||
<p class="entry">{{ dns.url }}</p>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
@ -13,12 +13,12 @@ import { ToastService } from 'src/app/services/toast.service';
|
||||
styleUrls: ['./domain-verification.component.scss'],
|
||||
})
|
||||
export class DomainVerificationComponent {
|
||||
public domain!: Domain.AsObject;
|
||||
public domain?: Domain.AsObject;
|
||||
|
||||
public DomainValidationType: any = DomainValidationType;
|
||||
|
||||
public http!: GenerateOrgDomainValidationResponse.AsObject;
|
||||
public dns!: GenerateOrgDomainValidationResponse.AsObject;
|
||||
public http?: GenerateOrgDomainValidationResponse.AsObject;
|
||||
public dns?: GenerateOrgDomainValidationResponse.AsObject;
|
||||
|
||||
public copied: string = '';
|
||||
|
||||
@ -34,25 +34,30 @@ export class DomainVerificationComponent {
|
||||
private mgmtService: ManagementService,
|
||||
) {
|
||||
this.domain = data.domain;
|
||||
if (this.domain.validationType === DomainValidationType.DOMAIN_VALIDATION_TYPE_UNSPECIFIED) {
|
||||
|
||||
if (this.domain?.validationType === DomainValidationType.DOMAIN_VALIDATION_TYPE_UNSPECIFIED) {
|
||||
this.showNew = true;
|
||||
}
|
||||
}
|
||||
|
||||
async loadHttpToken(): Promise<void> {
|
||||
this.mgmtService
|
||||
.generateOrgDomainValidation(this.domain.domainName, DomainValidationType.DOMAIN_VALIDATION_TYPE_HTTP)
|
||||
.then((http) => {
|
||||
this.http = http;
|
||||
});
|
||||
if (this.domain) {
|
||||
this.mgmtService
|
||||
.generateOrgDomainValidation(this.domain.domainName, DomainValidationType.DOMAIN_VALIDATION_TYPE_HTTP)
|
||||
.then((http) => {
|
||||
this.http = http;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async loadDnsToken(): Promise<void> {
|
||||
this.mgmtService
|
||||
.generateOrgDomainValidation(this.domain.domainName, DomainValidationType.DOMAIN_VALIDATION_TYPE_DNS)
|
||||
.then((dns) => {
|
||||
this.dns = dns;
|
||||
});
|
||||
if (this.domain) {
|
||||
this.mgmtService
|
||||
.generateOrgDomainValidation(this.domain.domainName, DomainValidationType.DOMAIN_VALIDATION_TYPE_DNS)
|
||||
.then((dns) => {
|
||||
this.dns = dns;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
@ -61,21 +66,25 @@ export class DomainVerificationComponent {
|
||||
|
||||
public validate(): void {
|
||||
this.validating = true;
|
||||
this.mgmtService
|
||||
.validateOrgDomain(this.domain.domainName)
|
||||
.then(() => {
|
||||
this.dialogRef.close(true);
|
||||
this.toast.showInfo('ORG.PAGES.ORGDOMAIN.VERIFICATION_SUCCESSFUL', true);
|
||||
this.validating = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
this.validating = false;
|
||||
});
|
||||
if (this.domain) {
|
||||
this.mgmtService
|
||||
.validateOrgDomain(this.domain.domainName)
|
||||
.then(() => {
|
||||
this.dialogRef.close(true);
|
||||
this.toast.showInfo('ORG.PAGES.ORGDOMAIN.VERIFICATION_SUCCESSFUL', true);
|
||||
this.validating = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
this.validating = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public saveFile(): void {
|
||||
const blob = new Blob([this.http.token], { type: 'text/plain;charset=utf-8' });
|
||||
saveAs(blob, this.http.token + '.txt');
|
||||
if (this.http) {
|
||||
const blob = new Blob([this.http.token], { type: 'text/plain;charset=utf-8' });
|
||||
saveAs(blob, this.http.token + '.txt');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import { ToastService } from 'src/app/services/toast.service';
|
||||
styleUrls: ['./instance.component.scss'],
|
||||
})
|
||||
export class InstanceComponent {
|
||||
public instance!: InstanceDetail.AsObject;
|
||||
public instance?: InstanceDetail.AsObject;
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
|
@ -51,7 +51,7 @@
|
||||
<h1>{{ 'ORG.PAGES.ORGDETAILUSER_TITLE' | translate }}</h1>
|
||||
|
||||
<div class="user">
|
||||
<form [formGroup]="userForm" class="form">
|
||||
<form [formGroup]="userForm" *ngIf="userForm" class="form">
|
||||
<div class="content">
|
||||
<p class="section cnsl-secondary-text">{{ 'USER.CREATE.NAMEANDEMAILSECTION' | translate }}</p>
|
||||
<cnsl-form-field class="formfield">
|
||||
@ -136,7 +136,12 @@
|
||||
<ng-container *ngIf="usePassword && pwdForm">
|
||||
<p class="section cnsl-secondary-text">{{ 'USER.CREATE.PASSWORDSECTION' | translate }}</p>
|
||||
|
||||
<cnsl-password-complexity-view class="complexity-view" [policy]="this.policy" [password]="password">
|
||||
<cnsl-password-complexity-view
|
||||
*ngIf="policy"
|
||||
class="complexity-view"
|
||||
[policy]="policy"
|
||||
[password]="password"
|
||||
>
|
||||
</cnsl-password-complexity-view>
|
||||
|
||||
<form [formGroup]="pwdForm" class="pwd-form">
|
||||
@ -177,7 +182,7 @@
|
||||
color="primary"
|
||||
class="big-button"
|
||||
(click)="finish()"
|
||||
[disabled]="orgForm.invalid || userForm.invalid || (usePassword && pwdForm ? pwdForm?.invalid : false)"
|
||||
[disabled]="orgForm.invalid || userForm.invalid || (usePassword && pwdForm ? pwdForm.invalid : false)"
|
||||
mat-raised-button
|
||||
>
|
||||
{{ 'ACTIONS.FINISH' | translate }}
|
||||
|
@ -50,14 +50,18 @@ function passwordConfirmValidator(c: AbstractControl): any {
|
||||
],
|
||||
})
|
||||
export class OrgCreateComponent {
|
||||
public orgForm!: UntypedFormGroup;
|
||||
public userForm!: UntypedFormGroup;
|
||||
public pwdForm!: UntypedFormGroup;
|
||||
public orgForm: UntypedFormGroup = this.fb.group({
|
||||
name: ['', [Validators.required]],
|
||||
domain: [''],
|
||||
});
|
||||
|
||||
public userForm?: UntypedFormGroup;
|
||||
public pwdForm?: UntypedFormGroup;
|
||||
|
||||
public genders: Gender[] = [Gender.GENDER_FEMALE, Gender.GENDER_MALE, Gender.GENDER_UNSPECIFIED];
|
||||
public languages: string[] = ['de', 'en'];
|
||||
public languages: string[] = ['de', 'en', 'it', 'fr'];
|
||||
|
||||
public policy!: PasswordComplexityPolicy.AsObject;
|
||||
public policy?: PasswordComplexityPolicy.AsObject;
|
||||
public usePassword: boolean = false;
|
||||
|
||||
public forSelf: boolean = true;
|
||||
@ -70,7 +74,7 @@ export class OrgCreateComponent {
|
||||
private fb: UntypedFormBuilder,
|
||||
private mgmtService: ManagementService,
|
||||
private authService: GrpcAuthService,
|
||||
private breadcrumbService: BreadcrumbService,
|
||||
breadcrumbService: BreadcrumbService,
|
||||
) {
|
||||
const instanceBread = new Breadcrumb({
|
||||
type: BreadcrumbType.INSTANCE,
|
||||
@ -89,12 +93,11 @@ export class OrgCreateComponent {
|
||||
}
|
||||
});
|
||||
|
||||
this.orgForm = this.fb.group({
|
||||
name: ['', [Validators.required]],
|
||||
domain: [''],
|
||||
});
|
||||
|
||||
this.initForm();
|
||||
|
||||
this.adminService.getSupportedLanguages().then((supportedResp) => {
|
||||
this.languages = supportedResp.languagesList;
|
||||
});
|
||||
}
|
||||
|
||||
public createSteps: number = 2;
|
||||
@ -125,16 +128,8 @@ export class OrgCreateComponent {
|
||||
|
||||
this.adminService
|
||||
.SetUpOrg(createOrgRequest, humanRequest)
|
||||
.then((resp) => {
|
||||
.then(() => {
|
||||
this.router.navigate(['/orgs']);
|
||||
|
||||
// const orgResp = org.getOrg();
|
||||
// if (orgResp) {
|
||||
// this.authService.setActiveOrg(orgResp.toObject());
|
||||
// this.router.navigate(['/org']);
|
||||
// } else {
|
||||
// this.router.navigate(['/org', 'overview']);
|
||||
// }
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
@ -241,43 +236,43 @@ export class OrgCreateComponent {
|
||||
}
|
||||
|
||||
public get userName(): AbstractControl | null {
|
||||
return this.userForm.get('userName');
|
||||
return this.userForm?.get('userName') ?? null;
|
||||
}
|
||||
|
||||
public get firstName(): AbstractControl | null {
|
||||
return this.userForm.get('firstName');
|
||||
return this.userForm?.get('firstName') ?? null;
|
||||
}
|
||||
|
||||
public get lastName(): AbstractControl | null {
|
||||
return this.userForm.get('lastName');
|
||||
return this.userForm?.get('lastName') ?? null;
|
||||
}
|
||||
|
||||
public get email(): AbstractControl | null {
|
||||
return this.userForm.get('email');
|
||||
return this.userForm?.get('email') ?? null;
|
||||
}
|
||||
|
||||
public get isVerified(): AbstractControl | null {
|
||||
return this.userForm.get('isVerified');
|
||||
return this.userForm?.get('isVerified') ?? null;
|
||||
}
|
||||
|
||||
public get nickName(): AbstractControl | null {
|
||||
return this.userForm.get('nickName');
|
||||
return this.userForm?.get('nickName') ?? null;
|
||||
}
|
||||
|
||||
public get preferredLanguage(): AbstractControl | null {
|
||||
return this.userForm.get('preferredLanguage');
|
||||
return this.userForm?.get('preferredLanguage') ?? null;
|
||||
}
|
||||
|
||||
public get gender(): AbstractControl | null {
|
||||
return this.userForm.get('gender');
|
||||
return this.userForm?.get('gender') ?? null;
|
||||
}
|
||||
|
||||
public get password(): AbstractControl | null {
|
||||
return this.pwdForm.get('password');
|
||||
return this.pwdForm?.get('password') ?? null;
|
||||
}
|
||||
|
||||
public get confirmPassword(): AbstractControl | null {
|
||||
return this.pwdForm.get('confirmPassword');
|
||||
return this.pwdForm?.get('confirmPassword') ?? null;
|
||||
}
|
||||
|
||||
public close(): void {
|
||||
|
@ -21,7 +21,7 @@ import { ToastService } from 'src/app/services/toast.service';
|
||||
styleUrls: ['./org-detail.component.scss'],
|
||||
})
|
||||
export class OrgDetailComponent implements OnInit, OnDestroy {
|
||||
public org!: Org.AsObject;
|
||||
public org?: Org.AsObject;
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
|
||||
public OrgState: any = OrgState;
|
||||
@ -80,7 +80,7 @@ export class OrgDetailComponent implements OnInit, OnDestroy {
|
||||
.reactivateOrg()
|
||||
.then(() => {
|
||||
this.toast.showInfo('ORG.TOAST.REACTIVATED', true);
|
||||
this.org.state = OrgState.ORG_STATE_ACTIVE;
|
||||
this.org!.state = OrgState.ORG_STATE_ACTIVE;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
@ -103,7 +103,7 @@ export class OrgDetailComponent implements OnInit, OnDestroy {
|
||||
.deactivateOrg()
|
||||
.then(() => {
|
||||
this.toast.showInfo('ORG.TOAST.DEACTIVATED', true);
|
||||
this.org.state = OrgState.ORG_STATE_INACTIVE;
|
||||
this.org!.state = OrgState.ORG_STATE_INACTIVE;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
|
@ -19,7 +19,7 @@ import { OrgMembersDataSource } from './org-members-datasource';
|
||||
})
|
||||
export class OrgMembersComponent {
|
||||
public INITIALPAGESIZE: number = 25;
|
||||
public org!: Org.AsObject;
|
||||
public org?: Org.AsObject;
|
||||
public disableWrite: boolean = false;
|
||||
public dataSource!: OrgMembersDataSource;
|
||||
|
||||
|
@ -186,7 +186,7 @@
|
||||
</span>
|
||||
<span class="right">
|
||||
<span>
|
||||
{{ 'APP.OIDC.AUTHMETHOD.' + oidcAppRequest?.authMethodType | translate }}
|
||||
{{ 'APP.OIDC.AUTHMETHOD.' + oidcAppRequest.authMethodType | translate }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
@ -226,7 +226,7 @@
|
||||
</span>
|
||||
<span class="right">
|
||||
<span>
|
||||
{{ 'APP.API.AUTHMETHOD.' + apiAppRequest?.authMethodType | translate }}
|
||||
{{ 'APP.API.AUTHMETHOD.' + apiAppRequest.authMethodType | translate }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -9,17 +9,17 @@ import { Subject, Subscription } from 'rxjs';
|
||||
import { debounceTime, takeUntil } from 'rxjs/operators';
|
||||
import { RadioItemAuthType } from 'src/app/modules/app-radio/app-auth-method-radio/app-auth-method-radio.component';
|
||||
import {
|
||||
APIAuthMethodType,
|
||||
OIDCAppType,
|
||||
OIDCAuthMethodType,
|
||||
OIDCGrantType,
|
||||
OIDCResponseType,
|
||||
APIAuthMethodType,
|
||||
OIDCAppType,
|
||||
OIDCAuthMethodType,
|
||||
OIDCGrantType,
|
||||
OIDCResponseType,
|
||||
} from 'src/app/proto/generated/zitadel/app_pb';
|
||||
import {
|
||||
AddAPIAppRequest,
|
||||
AddAPIAppResponse,
|
||||
AddOIDCAppRequest,
|
||||
AddOIDCAppResponse,
|
||||
AddAPIAppRequest,
|
||||
AddAPIAppResponse,
|
||||
AddOIDCAppRequest,
|
||||
AddOIDCAppResponse,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
@ -27,13 +27,13 @@ import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { AppSecretDialogComponent } from '../app-secret-dialog/app-secret-dialog.component';
|
||||
import {
|
||||
BASIC_AUTH_METHOD,
|
||||
CODE_METHOD,
|
||||
getPartialConfigFromAuthMethod,
|
||||
IMPLICIT_METHOD,
|
||||
PK_JWT_METHOD,
|
||||
PKCE_METHOD,
|
||||
POST_METHOD,
|
||||
BASIC_AUTH_METHOD,
|
||||
CODE_METHOD,
|
||||
getPartialConfigFromAuthMethod,
|
||||
IMPLICIT_METHOD,
|
||||
PK_JWT_METHOD,
|
||||
PKCE_METHOD,
|
||||
POST_METHOD,
|
||||
} from '../authmethods';
|
||||
import { API_TYPE, AppCreateType, NATIVE_TYPE, RadioItemAppType, USER_AGENT_TYPE, WEB_TYPE } from '../authtypes';
|
||||
|
||||
@ -43,7 +43,7 @@ import { API_TYPE, AppCreateType, NATIVE_TYPE, RadioItemAppType, USER_AGENT_TYPE
|
||||
styleUrls: ['./app-create.component.scss'],
|
||||
})
|
||||
export class AppCreateComponent implements OnInit, OnDestroy {
|
||||
private subscription?: Subscription;
|
||||
private subscription: Subscription = new Subscription();
|
||||
private destroyed$: Subject<void> = new Subject();
|
||||
public devmode: boolean = false;
|
||||
public projectId: string = '';
|
||||
|
@ -57,7 +57,10 @@
|
||||
</cnsl-top-view>
|
||||
|
||||
<div class="max-width-container">
|
||||
<div class="compliance" *ngIf="app?.oidcConfig?.complianceProblemsList && app.oidcConfig?.complianceProblemsList?.length">
|
||||
<div
|
||||
class="compliance"
|
||||
*ngIf="app && app.oidcConfig && app.oidcConfig.complianceProblemsList && app.oidcConfig.complianceProblemsList?.length"
|
||||
>
|
||||
<h2 class="compliance-title">{{ 'APP.COMPLIANCE' | translate }}</h2>
|
||||
<cnsl-info-section class="problem" [type]="InfoSectionType.ALERT">
|
||||
<ul style="margin: 0">
|
||||
@ -355,7 +358,7 @@
|
||||
|
||||
<ng-container *ngIf="currentSetting === 'configuration'">
|
||||
<cnsl-card
|
||||
*ngIf="initialAuthMethod === 'PK_JWT' && projectId && app?.id"
|
||||
*ngIf="initialAuthMethod === 'PK_JWT' && projectId && app && app.id"
|
||||
title="{{ 'USER.MACHINE.KEYSTITLE' | translate }}"
|
||||
description="{{ 'USER.MACHINE.KEYSDESC' | translate }}"
|
||||
>
|
||||
|
@ -17,21 +17,21 @@ import { NameDialogComponent } from 'src/app/modules/name-dialog/name-dialog.com
|
||||
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
|
||||
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
|
||||
import {
|
||||
APIAuthMethodType,
|
||||
APIConfig,
|
||||
App,
|
||||
AppState,
|
||||
OIDCAppType,
|
||||
OIDCAuthMethodType,
|
||||
OIDCConfig,
|
||||
OIDCGrantType,
|
||||
OIDCResponseType,
|
||||
OIDCTokenType,
|
||||
APIAuthMethodType,
|
||||
APIConfig,
|
||||
App,
|
||||
AppState,
|
||||
OIDCAppType,
|
||||
OIDCAuthMethodType,
|
||||
OIDCConfig,
|
||||
OIDCGrantType,
|
||||
OIDCResponseType,
|
||||
OIDCTokenType,
|
||||
} from 'src/app/proto/generated/zitadel/app_pb';
|
||||
import {
|
||||
GetOIDCInformationResponse,
|
||||
UpdateAPIAppConfigRequest,
|
||||
UpdateOIDCAppConfigRequest,
|
||||
GetOIDCInformationResponse,
|
||||
UpdateAPIAppConfigRequest,
|
||||
UpdateOIDCAppConfigRequest,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
|
||||
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
|
||||
@ -40,15 +40,15 @@ import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { AppSecretDialogComponent } from '../app-secret-dialog/app-secret-dialog.component';
|
||||
import {
|
||||
BASIC_AUTH_METHOD,
|
||||
CODE_METHOD,
|
||||
CUSTOM_METHOD,
|
||||
getAuthMethodFromPartialConfig,
|
||||
getPartialConfigFromAuthMethod,
|
||||
IMPLICIT_METHOD,
|
||||
PK_JWT_METHOD,
|
||||
PKCE_METHOD,
|
||||
POST_METHOD,
|
||||
BASIC_AUTH_METHOD,
|
||||
CODE_METHOD,
|
||||
CUSTOM_METHOD,
|
||||
getAuthMethodFromPartialConfig,
|
||||
getPartialConfigFromAuthMethod,
|
||||
IMPLICIT_METHOD,
|
||||
PK_JWT_METHOD,
|
||||
PKCE_METHOD,
|
||||
POST_METHOD,
|
||||
} from '../authmethods';
|
||||
import { AuthMethodDialogComponent } from './auth-method-dialog/auth-method-dialog.component';
|
||||
|
||||
@ -71,7 +71,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
public authMethods: RadioItemAuthType[] = [];
|
||||
private subscription?: Subscription;
|
||||
public projectId: string = '';
|
||||
public app!: App.AsObject;
|
||||
public app?: App.AsObject;
|
||||
|
||||
public environmentMap: { [key: string]: string } = {};
|
||||
|
||||
@ -183,7 +183,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
public openNameDialog(): void {
|
||||
const dialogRef = this.dialog.open(NameDialogComponent, {
|
||||
data: {
|
||||
name: this.app.name,
|
||||
name: this.app?.name,
|
||||
titleKey: 'APP.NAMEDIALOG.TITLE',
|
||||
descKey: 'APP.NAMEDIALOG.DESCRIPTION',
|
||||
labelKey: 'APP.NAMEDIALOG.NAME',
|
||||
@ -193,7 +193,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
dialogRef.afterClosed().subscribe((name) => {
|
||||
if (name) {
|
||||
this.app.name = name;
|
||||
this.app!.name = name;
|
||||
this.saveApp();
|
||||
}
|
||||
});
|
||||
@ -344,7 +344,6 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
this.toast.showError(error);
|
||||
this.errorMessage = error.message;
|
||||
});
|
||||
@ -354,7 +353,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
private getAuthMethodOptions(type: string): void {
|
||||
if (type === 'OIDC') {
|
||||
switch (this.app.oidcConfig?.appType) {
|
||||
switch (this.app?.oidcConfig?.appType) {
|
||||
case OIDCAppType.OIDC_APP_TYPE_NATIVE:
|
||||
this.authMethods = [PKCE_METHOD, CUSTOM_METHOD];
|
||||
break;
|
||||
@ -378,17 +377,17 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
|
||||
public setPartialConfigFromAuthMethod(authMethod: string): void {
|
||||
const partialConfig = getPartialConfigFromAuthMethod(authMethod);
|
||||
if (partialConfig && partialConfig.oidc && this.app.oidcConfig) {
|
||||
this.app.oidcConfig.responseTypesList = (partialConfig.oidc as Partial<OIDCConfig.AsObject>).responseTypesList ?? [];
|
||||
if (partialConfig && partialConfig.oidc && this.app?.oidcConfig) {
|
||||
this.app!.oidcConfig.responseTypesList = (partialConfig.oidc as Partial<OIDCConfig.AsObject>).responseTypesList ?? [];
|
||||
|
||||
this.app.oidcConfig.grantTypesList = (partialConfig.oidc as Partial<OIDCConfig.AsObject>).grantTypesList ?? [];
|
||||
this.app!.oidcConfig.grantTypesList = (partialConfig.oidc as Partial<OIDCConfig.AsObject>).grantTypesList ?? [];
|
||||
|
||||
this.app.oidcConfig.authMethodType =
|
||||
this.app!.oidcConfig.authMethodType =
|
||||
(partialConfig.oidc as Partial<OIDCConfig.AsObject>).authMethodType ?? OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE;
|
||||
|
||||
this.oidcForm.patchValue(this.app.oidcConfig);
|
||||
this.oidcTokenForm.patchValue(this.app.oidcConfig);
|
||||
} else if (partialConfig && partialConfig.api && this.app.apiConfig) {
|
||||
} else if (partialConfig && partialConfig.api && this.app?.apiConfig) {
|
||||
this.app.apiConfig.authMethodType =
|
||||
(partialConfig.api as Partial<APIConfig.AsObject>).authMethodType ?? APIAuthMethodType.API_AUTH_METHOD_TYPE_BASIC;
|
||||
|
||||
@ -408,7 +407,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((resp) => {
|
||||
if (resp && this.projectId && this.app.id) {
|
||||
if (resp && this.projectId && this.app?.id) {
|
||||
this.mgmtService
|
||||
.removeApp(this.projectId, this.app.id)
|
||||
.then(() => {
|
||||
@ -424,21 +423,21 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public changeState(state: AppState): void {
|
||||
if (state === AppState.APP_STATE_ACTIVE) {
|
||||
if (state === AppState.APP_STATE_ACTIVE && this.app) {
|
||||
this.mgmtService
|
||||
.reactivateApp(this.projectId, this.app.id)
|
||||
.then(() => {
|
||||
this.app.state = state;
|
||||
this.app!.state = state;
|
||||
this.toast.showInfo('APP.TOAST.REACTIVATED', true);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else if (state === AppState.APP_STATE_INACTIVE) {
|
||||
} else if (state === AppState.APP_STATE_INACTIVE && this.app) {
|
||||
this.mgmtService
|
||||
.deactivateApp(this.projectId, this.app.id)
|
||||
.then(() => {
|
||||
this.app.state = state;
|
||||
this.app!.state = state;
|
||||
this.toast.showInfo('APP.TOAST.DEACTIVATED', true);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
@ -448,15 +447,17 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public saveApp(): void {
|
||||
this.mgmtService
|
||||
.updateApp(this.projectId, this.app.id, this.app.name)
|
||||
.then(() => {
|
||||
this.toast.showInfo('APP.TOAST.UPDATED', true);
|
||||
this.editState = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
if (this.app) {
|
||||
this.mgmtService
|
||||
.updateApp(this.projectId, this.app.id, this.app.name)
|
||||
.then(() => {
|
||||
this.toast.showInfo('APP.TOAST.UPDATED', true);
|
||||
this.editState = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public toggleRefreshToken(event: MatCheckboxChange): void {
|
||||
@ -481,7 +482,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
public saveOIDCApp(): void {
|
||||
this.requestRedirectValuesSubject$.next();
|
||||
if (this.oidcForm.valid) {
|
||||
if (this.app.oidcConfig) {
|
||||
if (this.app?.oidcConfig) {
|
||||
// configuration
|
||||
this.app.oidcConfig.responseTypesList = this.responseTypesList?.value;
|
||||
this.app.oidcConfig.grantTypesList = this.grantTypesList?.value;
|
||||
@ -532,7 +533,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
this.mgmtService
|
||||
.updateOIDCAppConfig(req)
|
||||
.then(() => {
|
||||
if (this.app.oidcConfig) {
|
||||
if (this.app?.oidcConfig) {
|
||||
const config = { oidc: this.app.oidcConfig };
|
||||
this.currentAuthMethod = this.authMethodFromPartialConfig(config);
|
||||
}
|
||||
@ -546,7 +547,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public saveAPIApp(): void {
|
||||
if (this.apiForm.valid && this.app.apiConfig) {
|
||||
if (this.apiForm.valid && this.app?.apiConfig) {
|
||||
this.app.apiConfig.authMethodType = this.apiAuthMethodType?.value;
|
||||
|
||||
const req = new UpdateAPIAppConfigRequest();
|
||||
@ -557,7 +558,7 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
this.mgmtService
|
||||
.updateAPIAppConfig(req)
|
||||
.then(() => {
|
||||
if (this.app.apiConfig) {
|
||||
if (this.app?.apiConfig) {
|
||||
const config = { api: this.app.apiConfig };
|
||||
this.currentAuthMethod = this.authMethodFromPartialConfig(config);
|
||||
|
||||
@ -581,21 +582,23 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public regenerateOIDCClientSecret(): void {
|
||||
this.mgmtService
|
||||
.regenerateOIDCClientSecret(this.app.id, this.projectId)
|
||||
.then((resp) => {
|
||||
this.toast.showInfo('APP.TOAST.CLIENTSECRETREGENERATED', true);
|
||||
this.dialog.open(AppSecretDialogComponent, {
|
||||
data: {
|
||||
// clientId: data.toObject() as ClientSecret.AsObject.clientId,
|
||||
clientSecret: resp.clientSecret,
|
||||
},
|
||||
width: '400px',
|
||||
if (this.app) {
|
||||
this.mgmtService
|
||||
.regenerateOIDCClientSecret(this.app.id, this.projectId)
|
||||
.then((resp) => {
|
||||
this.toast.showInfo('APP.TOAST.CLIENTSECRETREGENERATED', true);
|
||||
this.dialog.open(AppSecretDialogComponent, {
|
||||
data: {
|
||||
// clientId: data.toObject() as ClientSecret.AsObject.clientId,
|
||||
clientSecret: resp.clientSecret,
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public changeAuthMethod(): void {
|
||||
@ -617,20 +620,22 @@ export class AppDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public regenerateAPIClientSecret(): void {
|
||||
this.mgmtService
|
||||
.regenerateAPIClientSecret(this.app.id, this.projectId)
|
||||
.then((resp) => {
|
||||
this.toast.showInfo('APP.TOAST.CLIENTSECRETREGENERATED', true);
|
||||
this.dialog.open(AppSecretDialogComponent, {
|
||||
data: {
|
||||
clientSecret: resp.clientSecret,
|
||||
},
|
||||
width: '400px',
|
||||
if (this.app) {
|
||||
this.mgmtService
|
||||
.regenerateAPIClientSecret(this.app.id, this.projectId)
|
||||
.then((resp) => {
|
||||
this.toast.showInfo('APP.TOAST.CLIENTSECRETREGENERATED', true);
|
||||
this.dialog.open(AppSecretDialogComponent, {
|
||||
data: {
|
||||
clientSecret: resp.clientSecret,
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public get currentRadioItemAuthType(): RadioItemAuthType | undefined {
|
||||
|
@ -54,7 +54,12 @@
|
||||
</ng-template>
|
||||
|
||||
<div metainfo>
|
||||
<cnsl-changes *ngIf="project" [changeType]="ChangeType.PROJECT_GRANT" [id]="project.projectId" [secId]="project.grantId"></cnsl-changes>
|
||||
<cnsl-changes
|
||||
*ngIf="project"
|
||||
[changeType]="ChangeType.PROJECT_GRANT"
|
||||
[id]="project.projectId"
|
||||
[secId]="project.grantId"
|
||||
></cnsl-changes>
|
||||
</div>
|
||||
</cnsl-meta-layout>
|
||||
</div>
|
||||
|
@ -23,16 +23,12 @@ import { ToastService } from 'src/app/services/toast.service';
|
||||
export class GrantedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
public projectId: string = '';
|
||||
public grantId: string = '';
|
||||
public project!: GrantedProject.AsObject;
|
||||
|
||||
public project?: GrantedProject.AsObject;
|
||||
public ProjectGrantState: any = ProjectGrantState;
|
||||
public ChangeType: any = ChangeType;
|
||||
|
||||
private subscription?: Subscription;
|
||||
|
||||
public isZitadel: boolean = false;
|
||||
|
||||
UserGrantContext: any = UserGrantContext;
|
||||
public UserGrantContext: any = UserGrantContext;
|
||||
private subscription: Subscription = new Subscription();
|
||||
|
||||
// members
|
||||
public totalMemberResult: number = 0;
|
||||
@ -56,7 +52,7 @@ export class GrantedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public ngOnDestroy(): void {
|
||||
this.subscription?.unsubscribe();
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
|
||||
private async getData({ id, grantId }: Params): Promise<void> {
|
||||
@ -155,6 +151,8 @@ export class GrantedProjectDetailComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public showDetail(): void {
|
||||
this.router.navigate(['granted-projects', this.project.projectId, 'grant', this.grantId, 'members']);
|
||||
if (this.project) {
|
||||
this.router.navigate(['granted-projects', this.project.projectId, 'grant', this.grantId, 'members']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
<cnsl-refresh-table [loading]="dataSource.loading$ | async" [selection]="selection" (refreshed)="refreshPage()"
|
||||
[dataSize]="dataSource.totalResult" [timestamp]="dataSource?.viewTimestamp">
|
||||
<cnsl-refresh-table
|
||||
[loading]="dataSource.loading$ | async"
|
||||
[selection]="selection"
|
||||
(refreshed)="refreshPage()"
|
||||
[dataSize]="dataSource.totalResult"
|
||||
[timestamp]="dataSource.viewTimestamp"
|
||||
>
|
||||
<ng-template cnslHasRole [hasRole]="['project.app.write']" actions>
|
||||
<a [disabled]="disabled" [routerLink]="[ '/projects', projectId, 'apps', 'create']" color="primary"
|
||||
mat-raised-button>
|
||||
<a [disabled]="disabled" [routerLink]="['/projects', projectId, 'apps', 'create']" color="primary" mat-raised-button>
|
||||
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
|
||||
</a>
|
||||
</ng-template>
|
||||
@ -11,66 +15,87 @@
|
||||
<table [dataSource]="dataSource" mat-table class="table" aria-label="Elements">
|
||||
<ng-container matColumnDef="select">
|
||||
<th class="selection" mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox color="primary" (change)="$event ? masterToggle() : null"
|
||||
<mat-checkbox
|
||||
color="primary"
|
||||
(change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()">
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td class="selection" mat-cell *matCellDef="let row">
|
||||
<mat-checkbox color="primary" (click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null" [checked]="selection.isSelected(row)">
|
||||
<mat-checkbox
|
||||
color="primary"
|
||||
(click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'APP.NAME' | translate }} </th>
|
||||
<td class="pointer" [routerLink]="['/projects', projectId, 'apps', app.id ]" mat-cell *matCellDef="let app">
|
||||
{{app.name}} </td>
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'APP.NAME' | translate }}</th>
|
||||
<td class="pointer" [routerLink]="['/projects', projectId, 'apps', app.id]" mat-cell *matCellDef="let app">
|
||||
{{ app.name }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="type">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'APP.TYPE' | translate }} </th>
|
||||
<td class="pointer" [routerLink]="['/projects', projectId, 'apps', app.id ]" mat-cell *matCellDef="let app">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'APP.TYPE' | translate }}</th>
|
||||
<td class="pointer" [routerLink]="['/projects', projectId, 'apps', app.id]" mat-cell *matCellDef="let app">
|
||||
<span *ngIf="app?.oidcConfig?.appType !== undefined && app?.oidcConfig?.appType !== null">
|
||||
{{'APP.OIDC.APPTYPE.'+app?.oidcConfig?.appType | translate}}
|
||||
{{ 'APP.OIDC.APPTYPE.' + app?.oidcConfig?.appType | translate }}
|
||||
</span>
|
||||
<span *ngIf="app.apiConfig">API</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="state">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.DATA.STATE' | translate }} </th>
|
||||
<td class="pointer" mat-cell *matCellDef="let app" [routerLink]="['/projects', projectId, 'apps', app.id ]">
|
||||
<span class="state"
|
||||
[ngClass]="{'active': app.state === AppState.APP_STATE_ACTIVE, 'inactive': app.state === AppState.APP_STATE_INACTIVE}">
|
||||
{{('APP.PAGES.DETAIL.STATE.'+app?.state) | translate}}
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'USER.DATA.STATE' | translate }}</th>
|
||||
<td class="pointer" mat-cell *matCellDef="let app" [routerLink]="['/projects', projectId, 'apps', app.id]">
|
||||
<span
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: app.state === AppState.APP_STATE_ACTIVE,
|
||||
inactive: app.state === AppState.APP_STATE_INACTIVE
|
||||
}"
|
||||
>
|
||||
{{ 'APP.PAGES.DETAIL.STATE.' + app?.state | translate }}
|
||||
</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="creationDate">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.ROLE.CREATIONDATE' | translate }} </th>
|
||||
<td class="pointer" [routerLink]="['/projects', projectId, 'apps', app.id ]" mat-cell *matCellDef="let app">
|
||||
<span *ngIf="app?.details?.creationDate">{{app.details.creationDate | timestampToDate |
|
||||
localizedDate: 'dd. MMM, HH:mm' }}</span>
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'PROJECT.ROLE.CREATIONDATE' | translate }}</th>
|
||||
<td class="pointer" [routerLink]="['/projects', projectId, 'apps', app.id]" mat-cell *matCellDef="let app">
|
||||
<span *ngIf="app?.details?.creationDate">{{
|
||||
app.details.creationDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm'
|
||||
}}</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="changeDate">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.ROLE.CHANGEDATE' | translate }} </th>
|
||||
<td class="pointer" [routerLink]="['/projects', projectId, 'apps', app.id ]" mat-cell *matCellDef="let app">
|
||||
<span *ngIf="app?.details?.changeDate">{{app.details.changeDate | timestampToDate |
|
||||
localizedDate: 'dd. MMM, HH:mm' }}</span>
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'PROJECT.ROLE.CHANGEDATE' | translate }}</th>
|
||||
<td class="pointer" [routerLink]="['/projects', projectId, 'apps', app.id]" mat-cell *matCellDef="let app">
|
||||
<span *ngIf="app?.details?.changeDate">{{
|
||||
app.details.changeDate | timestampToDate | localizedDate: 'dd. MMM, HH:mm'
|
||||
}}</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<cnsl-paginator class="paginator" #paginator [timestamp]="dataSource?.viewTimestamp" [length]="dataSource.totalResult"
|
||||
[pageSize]="25" [pageSizeOptions]="[25, 50, 100, 250]">
|
||||
<cnsl-paginator
|
||||
class="paginator"
|
||||
#paginator
|
||||
[timestamp]="dataSource.viewTimestamp"
|
||||
[length]="dataSource.totalResult"
|
||||
[pageSize]="25"
|
||||
[pageSizeOptions]="[25, 50, 100, 250]"
|
||||
>
|
||||
</cnsl-paginator>
|
||||
</cnsl-refresh-table>
|
||||
</cnsl-refresh-table>
|
||||
|
@ -19,7 +19,7 @@ export class ApplicationsComponent implements AfterViewInit, OnInit {
|
||||
@Input() public disabled: boolean = false;
|
||||
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
|
||||
@ViewChild(MatTable) public table!: MatTable<App.AsObject>;
|
||||
public dataSource!: ProjectApplicationsDataSource;
|
||||
public dataSource: ProjectApplicationsDataSource = new ProjectApplicationsDataSource(this.mgmtService);
|
||||
public selection: SelectionModel<App.AsObject> = new SelectionModel<App.AsObject>(true, []);
|
||||
|
||||
public displayedColumns: string[] = ['name', 'type', 'state', 'creationDate', 'changeDate'];
|
||||
@ -27,7 +27,6 @@ export class ApplicationsComponent implements AfterViewInit, OnInit {
|
||||
constructor(private mgmtService: ManagementService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.dataSource = new ProjectApplicationsDataSource(this.mgmtService);
|
||||
this.dataSource.loadApps(this.projectId, 0, 25);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
<button
|
||||
mat-menu-item
|
||||
[disabled]="isZitadel || (['project.write$', 'project.write:' + project.id] | hasRole | async) === false"
|
||||
[disabled]="isZitadel || (['project.write$', 'project.write:' + project?.id] | hasRole | async) === false"
|
||||
*ngIf="project?.state === ProjectState.PROJECT_STATE_ACTIVE"
|
||||
(click)="changeState(ProjectState.PROJECT_STATE_INACTIVE)"
|
||||
>
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
<button
|
||||
mat-menu-item
|
||||
[disabled]="isZitadel || (['project.write$', 'project.write:' + project.id] | hasRole | async) === false"
|
||||
[disabled]="isZitadel || (['project.write$', 'project.write:' + project?.id] | hasRole | async) === false"
|
||||
*ngIf="project?.state === ProjectState.PROJECT_STATE_INACTIVE"
|
||||
(click)="changeState(ProjectState.PROJECT_STATE_ACTIVE)"
|
||||
>
|
||||
|
@ -8,9 +8,7 @@ import { BehaviorSubject, from, Observable, of } from 'rxjs';
|
||||
import { catchError, finalize, map, take } from 'rxjs/operators';
|
||||
import { CreationType, MemberCreateDialogComponent } from 'src/app/modules/add-member-dialog/member-create-dialog.component';
|
||||
import { ChangeType } from 'src/app/modules/changes/changes.component';
|
||||
import {
|
||||
ProjectPrivateLabelingDialogComponent,
|
||||
} from 'src/app/modules/project-private-labeling-dialog/project-private-labeling-dialog.component';
|
||||
import { ProjectPrivateLabelingDialogComponent } from 'src/app/modules/project-private-labeling-dialog/project-private-labeling-dialog.component';
|
||||
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
|
||||
import { UserGrantContext } from 'src/app/modules/user-grants/user-grants-datasource';
|
||||
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
|
||||
@ -39,7 +37,7 @@ const GRANTS: SidenavSetting = { id: 'grants', i18nKey: 'MENU.GRANTS' };
|
||||
})
|
||||
export class OwnedProjectDetailComponent implements OnInit {
|
||||
public projectId: string = '';
|
||||
public project!: Project.AsObject;
|
||||
public project?: Project.AsObject;
|
||||
|
||||
public pageSizeApps: number = 10;
|
||||
public appsDataSource: MatTableDataSource<App.AsObject> = new MatTableDataSource<App.AsObject>();
|
||||
@ -95,7 +93,7 @@ export class OwnedProjectDetailComponent implements OnInit {
|
||||
public openNameDialog(): void {
|
||||
const dialogRef = this.dialog.open(NameDialogComponent, {
|
||||
data: {
|
||||
name: this.project.name,
|
||||
name: this.project?.name,
|
||||
titleKey: 'PROJECT.NAMEDIALOG.TITLE',
|
||||
descKey: 'PROJECT.NAMEDIALOG.DESCRIPTION',
|
||||
labelKey: 'PROJECT.NAMEDIALOG.NAME',
|
||||
@ -105,7 +103,7 @@ export class OwnedProjectDetailComponent implements OnInit {
|
||||
|
||||
dialogRef.afterClosed().subscribe((name) => {
|
||||
if (name) {
|
||||
this.project.name = name;
|
||||
this.project!.name = name;
|
||||
this.updateName();
|
||||
}
|
||||
});
|
||||
@ -114,14 +112,14 @@ export class OwnedProjectDetailComponent implements OnInit {
|
||||
public openPrivateLabelingDialog(): void {
|
||||
const dialogRef = this.dialog.open(ProjectPrivateLabelingDialogComponent, {
|
||||
data: {
|
||||
setting: this.project.privateLabelingSetting,
|
||||
setting: this.project?.privateLabelingSetting,
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((resp: PrivateLabelingSetting) => {
|
||||
if (resp !== undefined) {
|
||||
this.project.privateLabelingSetting = resp;
|
||||
this.project!.privateLabelingSetting = resp;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -143,7 +141,7 @@ export class OwnedProjectDetailComponent implements OnInit {
|
||||
}),
|
||||
new Breadcrumb({
|
||||
type: BreadcrumbType.PROJECT,
|
||||
name: this.project.name,
|
||||
name: this.project?.name,
|
||||
param: { key: ROUTEPARAM, value: projectId },
|
||||
routerLink: ['/projects', projectId],
|
||||
isZitadel: this.isZitadel,
|
||||
@ -198,7 +196,7 @@ export class OwnedProjectDetailComponent implements OnInit {
|
||||
.reactivateProject(this.projectId)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.REACTIVATED', true);
|
||||
this.project.state = ProjectState.PROJECT_STATE_ACTIVE;
|
||||
this.project!.state = ProjectState.PROJECT_STATE_ACTIVE;
|
||||
this.refreshChanges$.emit();
|
||||
})
|
||||
.catch((error) => {
|
||||
@ -222,7 +220,7 @@ export class OwnedProjectDetailComponent implements OnInit {
|
||||
.deactivateProject(this.projectId)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.DEACTIVATED', true);
|
||||
this.project.state = ProjectState.PROJECT_STATE_INACTIVE;
|
||||
this.project!.state = ProjectState.PROJECT_STATE_INACTIVE;
|
||||
this.refreshChanges$.emit();
|
||||
})
|
||||
.catch((error) => {
|
||||
@ -262,23 +260,25 @@ export class OwnedProjectDetailComponent implements OnInit {
|
||||
}
|
||||
|
||||
public saveProject(): void {
|
||||
const req = new UpdateProjectRequest();
|
||||
req.setId(this.project.id);
|
||||
req.setName(this.project.name);
|
||||
req.setProjectRoleAssertion(this.project.projectRoleAssertion);
|
||||
req.setProjectRoleCheck(this.project.projectRoleCheck);
|
||||
req.setHasProjectCheck(this.project.hasProjectCheck);
|
||||
req.setPrivateLabelingSetting(this.project.privateLabelingSetting);
|
||||
if (this.project) {
|
||||
const req = new UpdateProjectRequest();
|
||||
req.setId(this.project.id);
|
||||
req.setName(this.project.name);
|
||||
req.setProjectRoleAssertion(this.project.projectRoleAssertion);
|
||||
req.setProjectRoleCheck(this.project.projectRoleCheck);
|
||||
req.setHasProjectCheck(this.project.hasProjectCheck);
|
||||
req.setPrivateLabelingSetting(this.project.privateLabelingSetting);
|
||||
|
||||
this.mgmtService
|
||||
.updateProject(req)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.UPDATED', true);
|
||||
this.refreshChanges$.emit();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
this.mgmtService
|
||||
.updateProject(req)
|
||||
.then(() => {
|
||||
this.toast.showInfo('PROJECT.TOAST.UPDATED', true);
|
||||
this.refreshChanges$.emit();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public navigateBack(): void {
|
||||
@ -293,7 +293,7 @@ export class OwnedProjectDetailComponent implements OnInit {
|
||||
const dialogRef = this.dialog.open(MemberCreateDialogComponent, {
|
||||
data: {
|
||||
creationType: CreationType.PROJECT_OWNED,
|
||||
projectId: this.project.id,
|
||||
projectId: this.project?.id,
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
@ -323,6 +323,8 @@ export class OwnedProjectDetailComponent implements OnInit {
|
||||
}
|
||||
|
||||
public showDetail(): void {
|
||||
this.router.navigate(['projects', this.project.id, 'members']);
|
||||
if (this.project) {
|
||||
this.router.navigate(['projects', this.project.id, 'members']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<span *ngIf="org"> {{ 'PROJECT.GRANT.CREATE.FOR_ORG' | translate }} {{ org?.name }} </span>
|
||||
<span *ngIf="org"> {{ 'PROJECT.GRANT.CREATE.FOR_ORG' | translate }} {{ org.name }} </span>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="currentCreateStep === 2">
|
||||
|
@ -16,7 +16,7 @@ const ROUTEPARAM = 'projectid';
|
||||
styleUrls: ['./project-grant-create.component.scss'],
|
||||
})
|
||||
export class ProjectGrantCreateComponent implements OnInit, OnDestroy {
|
||||
public org!: Org.AsObject;
|
||||
public org?: Org.AsObject;
|
||||
public projectId: string = '';
|
||||
public grantId: string = '';
|
||||
public rolesKeyList: string[] = [];
|
||||
@ -77,14 +77,16 @@ export class ProjectGrantCreateComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public addGrant(): void {
|
||||
this.mgmtService
|
||||
.addProjectGrant(this.org.id, this.projectId, this.rolesKeyList)
|
||||
.then(() => {
|
||||
this.close();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
if (this.org) {
|
||||
this.mgmtService
|
||||
.addProjectGrant(this.org.id, this.projectId, this.rolesKeyList)
|
||||
.then(() => {
|
||||
this.close();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public selectRoles(roles: Role.AsObject[]): void {
|
||||
|
@ -2,12 +2,12 @@
|
||||
<div class="project-grants-wrapper">
|
||||
<div class="project-grants">
|
||||
<cnsl-refresh-table
|
||||
[loading]="dataSource?.loading$ | async"
|
||||
[loading]="dataSource.loading$ | async"
|
||||
*ngIf="projectId"
|
||||
(refreshed)="loadGrantsPage()"
|
||||
[dataSize]="dataSource.totalResult"
|
||||
[selection]="selection"
|
||||
[timestamp]="dataSource?.viewTimestamp"
|
||||
[timestamp]="dataSource.viewTimestamp"
|
||||
(refreshed)="getRoleOptions(projectId)"
|
||||
>
|
||||
<div actions>
|
||||
@ -149,7 +149,7 @@
|
||||
class="paginator"
|
||||
#paginator
|
||||
[pageSize]="50"
|
||||
[timestamp]="dataSource?.viewTimestamp"
|
||||
[timestamp]="dataSource.viewTimestamp"
|
||||
[pageSizeOptions]="[25, 50, 100, 250]"
|
||||
[length]="dataSource.totalResult"
|
||||
(page)="loadGrantsPage($event.pageIndex, $event.pageSize)"
|
||||
|
@ -32,12 +32,12 @@ export class ProjectGrantsComponent implements OnInit, AfterViewInit {
|
||||
@Input() public projectId: string = '';
|
||||
@ViewChild(PaginatorComponent) public paginator!: PaginatorComponent;
|
||||
@ViewChild(MatTable) public table!: MatTable<GrantedProject.AsObject>;
|
||||
public dataSource!: ProjectGrantsDataSource;
|
||||
public dataSource: ProjectGrantsDataSource = new ProjectGrantsDataSource(this.mgmtService, this.toast);
|
||||
public selection: SelectionModel<GrantedProject.AsObject> = new SelectionModel<GrantedProject.AsObject>(true, []);
|
||||
public memberRoleOptions: Role.AsObject[] = [];
|
||||
public displayedColumns: string[] = ['grantedOrgName', 'state', 'creationDate', 'changeDate', 'roleNamesList', 'actions'];
|
||||
|
||||
ProjectGrantState: any = ProjectGrantState;
|
||||
public ProjectGrantState: any = ProjectGrantState;
|
||||
|
||||
constructor(
|
||||
private mgmtService: ManagementService,
|
||||
@ -51,7 +51,6 @@ export class ProjectGrantsComponent implements OnInit, AfterViewInit {
|
||||
}
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.dataSource = new ProjectGrantsDataSource(this.mgmtService, this.toast);
|
||||
this.dataSource.loadGrants(this.projectId, 0, 25, 'asc');
|
||||
this.getRoleOptions(this.projectId);
|
||||
}
|
||||
|
@ -40,7 +40,9 @@
|
||||
<cnsl-project-roles-table
|
||||
[displayedColumns]="['select', 'key', 'displayname', 'group', 'creationDate', 'changeDate']"
|
||||
(changedSelection)="selectRoles($event)"
|
||||
[projectId]="project?.id ? project.id : grantedProject?.projectId ? grantedProject.projectId : ''"
|
||||
[projectId]="
|
||||
project && project.id ? project.id : grantedProject && grantedProject.projectId ? grantedProject.projectId : ''
|
||||
"
|
||||
[grantId]="$any(grantedProject)?.grantId ? $any(grantedProject)?.grantId : ''"
|
||||
>
|
||||
</cnsl-project-roles-table>
|
||||
|
@ -21,11 +21,11 @@ import { ToastService } from 'src/app/services/toast.service';
|
||||
export class UserGrantCreateComponent implements OnDestroy {
|
||||
public context!: UserGrantContext;
|
||||
|
||||
public org!: Org.AsObject;
|
||||
public org?: Org.AsObject;
|
||||
public userIds: string[] = [];
|
||||
|
||||
public project!: Project.AsObject;
|
||||
public grantedProject!: GrantedProject.AsObject;
|
||||
public project?: Project.AsObject;
|
||||
public grantedProject?: GrantedProject.AsObject;
|
||||
|
||||
public rolesList: string[] = [];
|
||||
|
||||
@ -34,7 +34,7 @@ export class UserGrantCreateComponent implements OnDestroy {
|
||||
|
||||
public UserGrantContext: any = UserGrantContext;
|
||||
|
||||
public user!: User.AsObject;
|
||||
public user?: User.AsObject;
|
||||
public UserTarget: any = UserTarget;
|
||||
|
||||
public editState: boolean = false;
|
||||
@ -114,7 +114,7 @@ export class UserGrantCreateComponent implements OnDestroy {
|
||||
public addGrant(): void {
|
||||
switch (this.context) {
|
||||
case UserGrantContext.OWNED_PROJECT:
|
||||
const prom = this.userIds.map((id) => this.userService.addUserGrant(id, this.rolesList, this.project.id));
|
||||
const prom = this.userIds.map((id) => this.userService.addUserGrant(id, this.rolesList, this.project?.id));
|
||||
Promise.all(prom)
|
||||
.then(() => {
|
||||
this.toast.showInfo('GRANTS.TOAST.UPDATED', true);
|
||||
@ -127,7 +127,7 @@ export class UserGrantCreateComponent implements OnDestroy {
|
||||
break;
|
||||
case UserGrantContext.GRANTED_PROJECT:
|
||||
const promp = this.userIds.map((id) =>
|
||||
this.userService.addUserGrant(id, this.rolesList, this.grantedProject.projectId, this.grantedProject.grantId),
|
||||
this.userService.addUserGrant(id, this.rolesList, this.grantedProject?.projectId, this.grantedProject?.grantId),
|
||||
);
|
||||
Promise.all(promp)
|
||||
.then(() => {
|
||||
|
@ -1,31 +1,55 @@
|
||||
<cnsl-card title="{{'USER.PASSWORDLESS.TITLE' | translate}}"
|
||||
description="{{'USER.PASSWORDLESS.DESCRIPTION' | translate}}">
|
||||
<button card-actions mat-icon-button (click)="getPasswordless()" class="icon-button"
|
||||
matTooltip="{{'ACTIONS.REFRESH' | translate}}">
|
||||
<cnsl-card
|
||||
title="{{ 'USER.PASSWORDLESS.TITLE' | translate }}"
|
||||
description="{{ 'USER.PASSWORDLESS.DESCRIPTION' | translate }}"
|
||||
>
|
||||
<button
|
||||
card-actions
|
||||
mat-icon-button
|
||||
(click)="getPasswordless()"
|
||||
class="icon-button"
|
||||
matTooltip="{{ 'ACTIONS.REFRESH' | translate }}"
|
||||
>
|
||||
<mat-icon class="icon">refresh</mat-icon>
|
||||
</button>
|
||||
<cnsl-refresh-table [hideRefresh]="true" [loading]="loading$ | async" (refreshed)="getPasswordless()"
|
||||
[dataSize]="dataSource?.data?.length ?? 0">
|
||||
<button actions class="cnsl-action-button button" (click)="addPasswordless()" mat-raised-button color="primary"
|
||||
matTooltip="{{'ACTIONS.NEW' | translate}}">
|
||||
<cnsl-refresh-table
|
||||
[hideRefresh]="true"
|
||||
[loading]="loading$ | async"
|
||||
(refreshed)="getPasswordless()"
|
||||
[dataSize]="dataSource.data.length"
|
||||
>
|
||||
<button
|
||||
actions
|
||||
class="cnsl-action-button button"
|
||||
(click)="addPasswordless()"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
matTooltip="{{ 'ACTIONS.NEW' | translate }}"
|
||||
>
|
||||
<i class="icon las la-fingerprint"></i>
|
||||
{{'USER.PASSWORDLESS.U2F' | translate}}
|
||||
{{ 'USER.PASSWORDLESS.U2F' | translate }}
|
||||
</button>
|
||||
<table class="table" mat-table [dataSource]="dataSource">
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.PASSWORDLESS.NAME' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let mfa"><span *ngIf="mfa?.name" class="centered">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'USER.PASSWORDLESS.NAME' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let mfa">
|
||||
<span *ngIf="mfa?.name" class="centered">
|
||||
{{ mfa?.name }}
|
||||
</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="state">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.PASSWORDLESS.TABLESTATE' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let mfa"><span class="centered">
|
||||
<span class="state"
|
||||
[ngClass]="{'active': mfa.state === AuthFactorState.AUTH_FACTOR_STATE_READY, 'inactive': mfa.state === AuthFactorState.AUTH_FACTOR_STATE_NOT_READY }">{{'USER.PASSWORDLESS.STATE.'+
|
||||
mfa.state | translate}}</span>
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'USER.PASSWORDLESS.TABLESTATE' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let mfa">
|
||||
<span class="centered">
|
||||
<span
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: mfa.state === AuthFactorState.AUTH_FACTOR_STATE_READY,
|
||||
inactive: mfa.state === AuthFactorState.AUTH_FACTOR_STATE_NOT_READY
|
||||
}"
|
||||
>{{ 'USER.PASSWORDLESS.STATE.' + mfa.state | translate }}</span
|
||||
>
|
||||
</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
@ -34,8 +58,13 @@
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let mfa">
|
||||
<cnsl-table-actions>
|
||||
<button actions matTooltip="{{'ACTIONS.REMOVE' | translate}}" color="warn" mat-icon-button
|
||||
(click)="deletePasswordless(mfa.id)">
|
||||
<button
|
||||
actions
|
||||
matTooltip="{{ 'ACTIONS.REMOVE' | translate }}"
|
||||
color="warn"
|
||||
mat-icon-button
|
||||
(click)="deletePasswordless(mfa.id)"
|
||||
>
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
</cnsl-table-actions>
|
||||
@ -43,11 +72,11 @@
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
<div *ngIf="(loading$ | async) === false && !dataSource?.data?.length" class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{'USER.PASSWORDLESS.EMPTY' | translate}}</span>
|
||||
<span>{{ 'USER.PASSWORDLESS.EMPTY' | translate }}</span>
|
||||
</div>
|
||||
</cnsl-refresh-table>
|
||||
<div class="table-wrapper">
|
||||
@ -55,4 +84,4 @@
|
||||
<mat-spinner diameter="50"></mat-spinner>
|
||||
</div>
|
||||
</div>
|
||||
</cnsl-card>
|
||||
</cnsl-card>
|
||||
|
@ -34,7 +34,7 @@ export class AuthPasswordlessComponent implements OnInit, OnDestroy {
|
||||
|
||||
@ViewChild(MatTable) public table!: MatTable<WebAuthNToken.AsObject>;
|
||||
@ViewChild(MatSort) public sort!: MatSort;
|
||||
public dataSource!: MatTableDataSource<WebAuthNToken.AsObject>;
|
||||
public dataSource: MatTableDataSource<WebAuthNToken.AsObject> = new MatTableDataSource<WebAuthNToken.AsObject>([]);
|
||||
|
||||
public AuthFactorState: any = AuthFactorState;
|
||||
public error: string = '';
|
||||
|
@ -1,5 +1,5 @@
|
||||
<cnsl-top-view
|
||||
title="{{ user?.human ? user.human?.profile?.displayName : user?.machine?.name }}"
|
||||
title="{{ user && user.human ? user.human.profile?.displayName : user?.machine?.name }}"
|
||||
sub="{{ user?.preferredLoginName }}"
|
||||
[isActive]="user?.state === UserState.USER_STATE_ACTIVE"
|
||||
[isInactive]="user?.state === UserState.USER_STATE_INACTIVE"
|
||||
@ -95,7 +95,7 @@
|
||||
|
||||
<ng-container *ngIf="currentSetting === 'grants'">
|
||||
<cnsl-card
|
||||
*ngIf="user?.id"
|
||||
*ngIf="user && user.id"
|
||||
title="{{ 'GRANTS.USER.TITLE' | translate }}"
|
||||
description="{{ 'GRANTS.USER.DESCRIPTION' | translate }}"
|
||||
>
|
||||
@ -130,7 +130,7 @@
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="currentSetting === 'metadata'">
|
||||
<cnsl-metadata *ngIf="user?.id" [userId]="user.id"></cnsl-metadata>
|
||||
<cnsl-metadata *ngIf="user && user.id" [userId]="user.id"></cnsl-metadata>
|
||||
</ng-container>
|
||||
</cnsl-sidenav>
|
||||
|
||||
|
@ -23,7 +23,7 @@ import { EditDialogComponent, EditDialogType } from './edit-dialog/edit-dialog.c
|
||||
styleUrls: ['./auth-user-detail.component.scss'],
|
||||
})
|
||||
export class AuthUserDetailComponent implements OnDestroy {
|
||||
public user!: User.AsObject;
|
||||
public user?: User.AsObject;
|
||||
public genders: Gender[] = [Gender.GENDER_MALE, Gender.GENDER_FEMALE, Gender.GENDER_DIVERSE];
|
||||
public languages: string[] = ['de', 'en', 'it'];
|
||||
|
||||
@ -132,13 +132,13 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
labelKey: 'ACTIONS.NEWVALUE',
|
||||
titleKey: 'USER.PROFILE.CHANGEUSERNAME_TITLE',
|
||||
descriptionKey: 'USER.PROFILE.CHANGEUSERNAME_DESC',
|
||||
value: this.user.userName,
|
||||
value: this.user?.userName,
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((resp: { value: string }) => {
|
||||
if (resp && resp.value && resp.value !== this.user.userName) {
|
||||
if (resp && resp.value && resp.value !== this.user?.userName) {
|
||||
this.userService
|
||||
.updateMyUserName(resp.value)
|
||||
.then(() => {
|
||||
@ -153,7 +153,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
public saveProfile(profileData: Profile.AsObject): void {
|
||||
if (this.user.human) {
|
||||
if (this.user?.human) {
|
||||
this.user.human.profile = profileData;
|
||||
|
||||
this.userService
|
||||
@ -180,7 +180,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
.setMyEmail(email)
|
||||
.then(() => {
|
||||
this.toast.showInfo('USER.TOAST.EMAILSAVED', true);
|
||||
if (this.user.human) {
|
||||
if (this.user?.human) {
|
||||
const mailToSet = new Email();
|
||||
mailToSet.setEmail(email);
|
||||
this.user.human.email = mailToSet.toObject();
|
||||
@ -237,7 +237,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
.removeMyPhone()
|
||||
.then(() => {
|
||||
this.toast.showInfo('USER.TOAST.PHONEREMOVED', true);
|
||||
if (this.user.human?.phone) {
|
||||
if (this.user?.human?.phone) {
|
||||
const phone = new Phone();
|
||||
this.user.human.phone = phone.toObject();
|
||||
this.refreshUser();
|
||||
@ -249,12 +249,12 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
public savePhone(phone: string): void {
|
||||
if (this.user.human) {
|
||||
if (this.user?.human) {
|
||||
this.userService
|
||||
.setMyPhone(phone)
|
||||
.then(() => {
|
||||
this.toast.showInfo('USER.TOAST.PHONESAVED', true);
|
||||
if (this.user.human) {
|
||||
if (this.user?.human) {
|
||||
const phoneToSet = new Phone();
|
||||
phoneToSet.setPhone(phone);
|
||||
this.user.human.phone = phoneToSet.toObject();
|
||||
@ -277,7 +277,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
labelKey: 'USER.LOGINMETHODS.PHONE.EDITVALUE',
|
||||
titleKey: 'USER.LOGINMETHODS.PHONE.EDITTITLE',
|
||||
descriptionKey: 'USER.LOGINMETHODS.PHONE.EDITDESC',
|
||||
value: this.user.human?.phone?.phone,
|
||||
value: this.user?.human?.phone?.phone,
|
||||
type: type,
|
||||
},
|
||||
width: '400px',
|
||||
@ -297,7 +297,7 @@ export class AuthUserDetailComponent implements OnDestroy {
|
||||
labelKey: 'ACTIONS.NEWVALUE',
|
||||
titleKey: 'USER.LOGINMETHODS.EMAIL.EDITTITLE',
|
||||
descriptionKey: 'USER.LOGINMETHODS.EMAIL.EDITDESC',
|
||||
value: this.user.human?.email?.email,
|
||||
value: this.user?.human?.email?.email,
|
||||
type: type,
|
||||
},
|
||||
width: '400px',
|
||||
|
@ -1,20 +1,35 @@
|
||||
<cnsl-card title="{{'USER.MFA.TITLE' | translate}}" description="{{'USER.MFA.DESCRIPTION' | translate}}">
|
||||
<button card-actions mat-icon-button (click)="getMFAs()" class="icon-button"
|
||||
matTooltip="{{'ACTIONS.REFRESH' | translate}}">
|
||||
<cnsl-card title="{{ 'USER.MFA.TITLE' | translate }}" description="{{ 'USER.MFA.DESCRIPTION' | translate }}">
|
||||
<button
|
||||
card-actions
|
||||
mat-icon-button
|
||||
(click)="getMFAs()"
|
||||
class="icon-button"
|
||||
matTooltip="{{ 'ACTIONS.REFRESH' | translate }}"
|
||||
>
|
||||
<mat-icon class="icon">refresh</mat-icon>
|
||||
</button>
|
||||
|
||||
<cnsl-refresh-table [hideRefresh]="true" [loading]="loading$ | async" (refreshed)="getMFAs()"
|
||||
[dataSize]="dataSource?.data?.length ?? 0">
|
||||
<button actions class="button cnsl-action-button" (click)="addAuthFactor()" mat-raised-button color="primary"
|
||||
matTooltip="{{'ACTIONS.NEW' | translate}}">
|
||||
<cnsl-refresh-table
|
||||
[hideRefresh]="true"
|
||||
[loading]="loading$ | async"
|
||||
(refreshed)="getMFAs()"
|
||||
[dataSize]="dataSource.data.length"
|
||||
>
|
||||
<button
|
||||
actions
|
||||
class="button cnsl-action-button"
|
||||
(click)="addAuthFactor()"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
matTooltip="{{ 'ACTIONS.NEW' | translate }}"
|
||||
>
|
||||
<mat-icon class="icon">add</mat-icon>
|
||||
<span>{{'USER.MFA.ADD' | translate}}</span>
|
||||
<span>{{ 'USER.MFA.ADD' | translate }}</span>
|
||||
</button>
|
||||
|
||||
<table class="table" mat-table [dataSource]="dataSource">
|
||||
<ng-container matColumnDef="type">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MFA.TABLETYPE' | translate }} </th>
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'USER.MFA.TABLETYPE' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let mfa">
|
||||
<span *ngIf="mfa.otp !== undefined">OTP (One-Time Password)</span>
|
||||
<span *ngIf="mfa.u2f !== undefined">U2F (Universal 2nd Factor)</span>
|
||||
@ -22,7 +37,7 @@
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MFA.NAME' | translate }} </th>
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'USER.MFA.NAME' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let mfa">
|
||||
<span *ngIf="mfa?.u2f?.name" class="centered">
|
||||
{{ mfa.u2f.name }}
|
||||
@ -31,11 +46,17 @@
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="state">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MFA.TABLESTATE' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let mfa"><span class="centered">
|
||||
<span class="state"
|
||||
[ngClass]="{'active': mfa.state === AuthFactorState.AUTH_FACTOR_STATE_READY, 'inactive': mfa.state === AuthFactorState.AUTH_FACTOR_STATE_NOT_READY}">{{'USER.MFA.STATE.'+
|
||||
mfa.state | translate}}</span>
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'USER.MFA.TABLESTATE' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let mfa">
|
||||
<span class="centered">
|
||||
<span
|
||||
class="state"
|
||||
[ngClass]="{
|
||||
active: mfa.state === AuthFactorState.AUTH_FACTOR_STATE_READY,
|
||||
inactive: mfa.state === AuthFactorState.AUTH_FACTOR_STATE_NOT_READY
|
||||
}"
|
||||
>{{ 'USER.MFA.STATE.' + mfa.state | translate }}</span
|
||||
>
|
||||
</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
@ -44,8 +65,13 @@
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let mfa">
|
||||
<cnsl-table-actions>
|
||||
<button actions matTooltip="{{'ACTIONS.REMOVE' | translate}}" color="warn" mat-icon-button
|
||||
(click)="deleteMFA(mfa)">
|
||||
<button
|
||||
actions
|
||||
matTooltip="{{ 'ACTIONS.REMOVE' | translate }}"
|
||||
color="warn"
|
||||
mat-icon-button
|
||||
(click)="deleteMFA(mfa)"
|
||||
>
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
</cnsl-table-actions>
|
||||
@ -53,12 +79,12 @@
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
|
||||
<div *ngIf="(loading$ | async) === false && !dataSource?.data?.length" class="no-content-row">
|
||||
<i class="las la-exclamation"></i>
|
||||
<span>{{'USER.MFA.EMPTY' | translate}}</span>
|
||||
<span>{{ 'USER.MFA.EMPTY' | translate }}</span>
|
||||
</div>
|
||||
</cnsl-refresh-table>
|
||||
<div class="table-wrapper">
|
||||
@ -66,4 +92,4 @@
|
||||
<mat-spinner diameter="50"></mat-spinner>
|
||||
</div>
|
||||
</div>
|
||||
</cnsl-card>
|
||||
</cnsl-card>
|
||||
|
@ -32,7 +32,7 @@ export class AuthUserMfaComponent implements OnInit, OnDestroy {
|
||||
|
||||
@ViewChild(MatTable) public table!: MatTable<AuthFactor.AsObject>;
|
||||
@ViewChild(MatSort) public sort!: MatSort;
|
||||
public dataSource!: MatTableDataSource<AuthFactor.AsObject>;
|
||||
public dataSource: MatTableDataSource<AuthFactor.AsObject> = new MatTableDataSource<AuthFactor.AsObject>([]);
|
||||
|
||||
public AuthFactorState: any = AuthFactorState;
|
||||
|
||||
|
@ -1,79 +1,105 @@
|
||||
<div class="contact-method-col">
|
||||
<div class="contact-method-row">
|
||||
<div class="left">
|
||||
<span class="label cnsl-secondary-text">{{ 'USER.PROFILE.PASSWORD' | translate }}</span>
|
||||
<span class="name">*********</span>
|
||||
<div class="contact-method-col" *ngIf="human">
|
||||
<div class="contact-method-row">
|
||||
<div class="left">
|
||||
<span class="label cnsl-secondary-text">{{ 'USER.PROFILE.PASSWORD' | translate }}</span>
|
||||
<span class="name">*********</span>
|
||||
|
||||
<ng-content select="[pwdAction]"></ng-content>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<a matTooltip="{{'USER.PASSWORD.SET' | translate}}" [disabled]="!canWrite" [routerLink]="['password']"
|
||||
mat-icon-button>
|
||||
<i class="las la-pen"></i>
|
||||
</a>
|
||||
</div>
|
||||
<ng-content select="[pwdAction]"></ng-content>
|
||||
</div>
|
||||
|
||||
<div class="contact-method-row">
|
||||
<div class="left">
|
||||
<span class="label cnsl-secondary-text">{{ 'USER.EMAIL' | translate }}</span>
|
||||
<span class="name">{{human?.email?.email}}</span>
|
||||
<span *ngIf="human?.email?.isEmailVerified" class="contact-state verified">{{'USER.EMAILVERIFIED' |
|
||||
translate}}</span>
|
||||
<div *ngIf="!human?.email?.isEmailVerified" class="block">
|
||||
<span class="contact-state notverified">{{'USER.NOTVERIFIED' | translate}}</span>
|
||||
<div class="right">
|
||||
<a
|
||||
matTooltip="{{ 'USER.PASSWORD.SET' | translate }}"
|
||||
[disabled]="!canWrite"
|
||||
[routerLink]="['password']"
|
||||
mat-icon-button
|
||||
>
|
||||
<i class="las la-pen"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="human?.email">
|
||||
<a *ngIf="canWrite" class="verify cnsl-secondary-text"
|
||||
matTooltip="{{'USER.LOGINMETHODS.EMAIL.RESEND' | translate}}"
|
||||
(click)="emitEmailVerification()">{{'USER.LOGINMETHODS.RESENDCODE' | translate}}</a>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div class="contact-method-row">
|
||||
<div class="left">
|
||||
<span class="label cnsl-secondary-text">{{ 'USER.EMAIL' | translate }}</span>
|
||||
<span class="name">{{ human.email?.email }}</span>
|
||||
<span *ngIf="human.email?.isEmailVerified" class="contact-state verified">{{ 'USER.EMAILVERIFIED' | translate }}</span>
|
||||
<div *ngIf="!human.email?.isEmailVerified" class="block">
|
||||
<span class="contact-state notverified">{{ 'USER.NOTVERIFIED' | translate }}</span>
|
||||
|
||||
<ng-content select="[emailAction]"></ng-content>
|
||||
</div>
|
||||
<ng-container *ngIf="human.email">
|
||||
<a
|
||||
*ngIf="canWrite"
|
||||
class="verify cnsl-secondary-text"
|
||||
matTooltip="{{ 'USER.LOGINMETHODS.EMAIL.RESEND' | translate }}"
|
||||
(click)="emitEmailVerification()"
|
||||
>{{ 'USER.LOGINMETHODS.RESENDCODE' | translate }}</a
|
||||
>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<button matTooltip="{{'ACTIONS.EDIT' | translate}}"
|
||||
[disabled]="!canWrite || state === UserState.USER_STATE_INITIAL"
|
||||
(click)="openEditDialog(EditDialogType.EMAIL)" mat-icon-button>
|
||||
<i class="las la-pen"></i>
|
||||
</button>
|
||||
</div>
|
||||
<ng-content select="[emailAction]"></ng-content>
|
||||
</div>
|
||||
|
||||
<div class="contact-method-row">
|
||||
<div class="left">
|
||||
<span class="label cnsl-secondary-text">{{ 'USER.PHONE' | translate }}</span>
|
||||
<span class="name">{{human?.phone?.phone ? human.phone?.phone : ('USER.PHONEEMPTY' | translate)}}</span>
|
||||
<span *ngIf="human?.phone?.isPhoneVerified" class="contact-state verified">{{'USER.PHONEVERIFIED' |
|
||||
translate}}</span>
|
||||
<div *ngIf="human.phone?.phone && !human?.phone?.isPhoneVerified" class="block">
|
||||
<span class="contact-state notverified">{{'USER.NOTVERIFIED' | translate}}</span>
|
||||
|
||||
<ng-container *ngIf="human?.phone?.phone">
|
||||
<a *ngIf="!disablePhoneCode && canWrite" class="verify cnsl-secondary-text"
|
||||
matTooltip="{{'USER.LOGINMETHODS.ENTERCODE_DESC' | translate}}"
|
||||
(click)="enterCode()">{{'USER.LOGINMETHODS.ENTERCODE' | translate}}</a>
|
||||
<a *ngIf="canWrite" class="verify cnsl-secondary-text"
|
||||
matTooltip="{{'USER.LOGINMETHODS.PHONE.RESEND' | translate}}"
|
||||
(click)="emitPhoneVerification()">{{'USER.LOGINMETHODS.RESENDCODE' | translate}}</a>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<ng-content select="[phoneAction]"></ng-content>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<button matTooltip="{{'ACTIONS.DELETE' | translate}}" *ngIf="human && human.phone?.phone" color="warn"
|
||||
(click)="emitDeletePhone()" mat-icon-button>
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
<button matTooltip="{{'ACTIONS.EDIT' | translate}}" [disabled]="!canWrite"
|
||||
(click)="openEditDialog(EditDialogType.PHONE)" mat-icon-button>
|
||||
<i class="las la-pen"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button
|
||||
matTooltip="{{ 'ACTIONS.EDIT' | translate }}"
|
||||
[disabled]="!canWrite || state === UserState.USER_STATE_INITIAL"
|
||||
(click)="openEditDialog(EditDialogType.EMAIL)"
|
||||
mat-icon-button
|
||||
>
|
||||
<i class="las la-pen"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="contact-method-row">
|
||||
<div class="left">
|
||||
<span class="label cnsl-secondary-text">{{ 'USER.PHONE' | translate }}</span>
|
||||
<span class="name">{{ human.phone?.phone ? human.phone?.phone : ('USER.PHONEEMPTY' | translate) }}</span>
|
||||
<span *ngIf="human.phone?.isPhoneVerified" class="contact-state verified">{{ 'USER.PHONEVERIFIED' | translate }}</span>
|
||||
<div *ngIf="human.phone?.phone && !human.phone?.isPhoneVerified" class="block">
|
||||
<span class="contact-state notverified">{{ 'USER.NOTVERIFIED' | translate }}</span>
|
||||
|
||||
<ng-container *ngIf="human.phone?.phone">
|
||||
<a
|
||||
*ngIf="!disablePhoneCode && canWrite"
|
||||
class="verify cnsl-secondary-text"
|
||||
matTooltip="{{ 'USER.LOGINMETHODS.ENTERCODE_DESC' | translate }}"
|
||||
(click)="enterCode()"
|
||||
>{{ 'USER.LOGINMETHODS.ENTERCODE' | translate }}</a
|
||||
>
|
||||
<a
|
||||
*ngIf="canWrite"
|
||||
class="verify cnsl-secondary-text"
|
||||
matTooltip="{{ 'USER.LOGINMETHODS.PHONE.RESEND' | translate }}"
|
||||
(click)="emitPhoneVerification()"
|
||||
>{{ 'USER.LOGINMETHODS.RESENDCODE' | translate }}</a
|
||||
>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<ng-content select="[phoneAction]"></ng-content>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<button
|
||||
matTooltip="{{ 'ACTIONS.DELETE' | translate }}"
|
||||
*ngIf="human && human.phone?.phone"
|
||||
color="warn"
|
||||
(click)="emitDeletePhone()"
|
||||
mat-icon-button
|
||||
>
|
||||
<i class="las la-trash"></i>
|
||||
</button>
|
||||
<button
|
||||
matTooltip="{{ 'ACTIONS.EDIT' | translate }}"
|
||||
[disabled]="!canWrite"
|
||||
(click)="openEditDialog(EditDialogType.PHONE)"
|
||||
mat-icon-button
|
||||
>
|
||||
<i class="las la-pen"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -14,7 +14,7 @@ import { EditDialogType } from '../auth-user-detail/edit-dialog/edit-dialog.comp
|
||||
export class ContactComponent {
|
||||
@Input() disablePhoneCode: boolean = false;
|
||||
@Input() canWrite: boolean | null = false;
|
||||
@Input() human!: Human.AsObject;
|
||||
@Input() human?: Human.AsObject;
|
||||
@Input() state!: UserState;
|
||||
@Output() editType: EventEmitter<EditDialogType> = new EventEmitter<EditDialogType>();
|
||||
@Output() resendEmailVerification: EventEmitter<void> = new EventEmitter<void>();
|
||||
|
@ -14,7 +14,7 @@
|
||||
*ngIf="user && user.profile?.displayName && user.profile?.firstName && user.profile?.lastName"
|
||||
class="avatar"
|
||||
[name]="user.profile?.displayName ?? ''"
|
||||
[avatarUrl]="user?.profile?.avatarUrl || ''"
|
||||
[avatarUrl]="user.profile?.avatarUrl || ''"
|
||||
[forColor]="preferredLoginName"
|
||||
[size]="80"
|
||||
>
|
||||
|
Loading…
x
Reference in New Issue
Block a user