mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-11 16:45:13 +00:00
feat(console): Google, Generic OIDC, Generic JWT - Identity provider templates (#5265)
implement Google, Generic OIDC, Generic JWT provider templates in console
This commit is contained in:
@@ -7,100 +7,8 @@
|
||||
[selection]="selection"
|
||||
[hideRefresh]="true"
|
||||
>
|
||||
<div actions>
|
||||
<button
|
||||
(click)="deactivateSelectedIdps()"
|
||||
matTooltip="{{ 'IDP.DEACTIVATE' | translate }}"
|
||||
class="idp-margin-right bg-state inactive"
|
||||
mat-stroked-button
|
||||
*ngIf="selection.hasValue()"
|
||||
[disabled]="
|
||||
([
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.idp.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'org.idp.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
"
|
||||
>
|
||||
{{ 'IDP.DEACTIVATE' | translate }}
|
||||
</button>
|
||||
<button
|
||||
(click)="reactivateSelectedIdps()"
|
||||
matTooltip="{{ 'IDP.ACTIVATE' | translate }}"
|
||||
class="bg-state active"
|
||||
mat-stroked-button
|
||||
*ngIf="selection.hasValue()"
|
||||
[disabled]="
|
||||
([
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.idp.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'org.idp.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
"
|
||||
>
|
||||
{{ 'IDP.ACTIVATE' | translate }}
|
||||
</button>
|
||||
|
||||
<a
|
||||
[routerLink]="createRouterLink"
|
||||
class="cnsl-action-button"
|
||||
color="primary"
|
||||
mat-raised-button
|
||||
[disabled]="
|
||||
([
|
||||
serviceType === PolicyComponentServiceType.ADMIN
|
||||
? 'iam.idp.write'
|
||||
: serviceType === PolicyComponentServiceType.MGMT
|
||||
? 'org.idp.write'
|
||||
: ''
|
||||
]
|
||||
| hasRole
|
||||
| async) === false
|
||||
"
|
||||
>
|
||||
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="table-wrapper">
|
||||
<table class="table" mat-table [dataSource]="dataSource">
|
||||
<ng-container matColumnDef="select">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox
|
||||
color="primary"
|
||||
(change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()"
|
||||
[disabled]="serviceType === PolicyComponentServiceType.MGMT"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let idp">
|
||||
<mat-checkbox
|
||||
color="primary"
|
||||
(click)="$event.stopPropagation()"
|
||||
class="chbox"
|
||||
[disabled]="serviceType === PolicyComponentServiceType.MGMT && idp?.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM"
|
||||
(change)="$event ? selection.toggle(idp) : null"
|
||||
[checked]="selection.isSelected(idp)"
|
||||
>
|
||||
<img
|
||||
src="../../../assets/images/google.png"
|
||||
*ngIf="idp.stylingType === IDPStylingType.IDPSTYLINGTYPE_GOOGLE"
|
||||
alt="google"
|
||||
/>
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="availability">
|
||||
<th class="availability" mat-header-cell *matHeaderCellDef>
|
||||
<span>{{ 'IDP.AVAILABILITY' | translate }}</span>
|
||||
@@ -129,8 +37,21 @@
|
||||
<ng-container matColumnDef="type">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'IDP.TYPE' | translate }}</th>
|
||||
<td class="pointer" [routerLink]="routerLinkForRow(idp)" mat-cell *matCellDef="let idp">
|
||||
<span class="state" *ngIf="idp?.oidcConfig">{{ 'IDP.TYPES.1' | translate }}</span>
|
||||
<span class="state" *ngIf="idp?.jwtConfig">{{ 'IDP.TYPES.3' | translate }}</span>
|
||||
<div [ngSwitch]="idp.type">
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_GOOGLE">
|
||||
<img class="idp-logo" src="../../../assets/images/idp/google.png" alt="google" />
|
||||
Google
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_OIDC">
|
||||
<mat-icon class="idp-icon" svgIcon="mdi_openid" alt="oidc" />
|
||||
Generic OIDC
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchCase="ProviderType.PROVIDER_TYPE_JWT">
|
||||
<mat-icon class="idp-icon" svgIcon="mdi_jwt" alt="jwt" />
|
||||
Generic JWT
|
||||
</div>
|
||||
<div class="idp-table-provider-type" *ngSwitchDefault>coming soon</div>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
@@ -150,21 +71,21 @@
|
||||
|
||||
<ng-container matColumnDef="creationDate">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'IDP.CREATIONDATE' | translate }}</th>
|
||||
<td [routerLink]="routerLinkForRow(idp)" class="pointer" mat-cell *matCellDef="let idp">
|
||||
<td class="pointer" [routerLink]="routerLinkForRow(idp)" mat-cell *matCellDef="let idp">
|
||||
<span>{{ idp.details.creationDate | timestampToDate | localizedDate : 'dd. MMM, HH:mm' }}</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="changeDate">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'IDP.CHANGEDATE' | translate }}</th>
|
||||
<td [routerLink]="routerLinkForRow(idp)" class="pointer" mat-cell *matCellDef="let idp">
|
||||
<td class="pointer" [routerLink]="routerLinkForRow(idp)" mat-cell *matCellDef="let idp">
|
||||
<span>{{ idp.details.changeDate | timestampToDate | localizedDate : 'dd. MMM, HH:mm' }}</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="owner">
|
||||
<th mat-header-cell *matHeaderCellDef>{{ 'IDP.OWNER' | translate }}</th>
|
||||
<td [routerLink]="routerLinkForRow(idp)" class="pointer" mat-cell *matCellDef="let idp">
|
||||
<td class="pointer" [routerLink]="routerLinkForRow(idp)" mat-cell *matCellDef="let idp">
|
||||
{{ 'IDP.OWNERTYPES.' + idp.owner | translate }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
@@ -1,3 +1,44 @@
|
||||
@mixin idp-table-theme($theme) {
|
||||
$primary: map-get($theme, primary);
|
||||
$warn: map-get($theme, warn);
|
||||
$background: map-get($theme, background);
|
||||
$accent: map-get($theme, accent);
|
||||
$primary-color: mat.get-color-from-palette($primary, 500);
|
||||
|
||||
$warn-color: mat.get-color-from-palette($warn, 500);
|
||||
$accent-color: mat.get-color-from-palette($accent, 500);
|
||||
$foreground: map-get($theme, foreground);
|
||||
$is-dark-theme: map-get($theme, is-dark);
|
||||
$back: map-get($background, background);
|
||||
|
||||
.idp-table-provider-type {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.idp-logo {
|
||||
margin-right: 1rem;
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
flex-shrink: 0;
|
||||
|
||||
&.dark {
|
||||
display: if($is-dark-theme, block, none);
|
||||
}
|
||||
|
||||
&.light {
|
||||
display: if($is-dark-theme, none, block);
|
||||
}
|
||||
}
|
||||
|
||||
.idp-icon {
|
||||
font-size: 1.75rem;
|
||||
height: 1.75rem;
|
||||
width: 1.75rem;
|
||||
margin-right: 1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.idp-margin-right {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
@@ -6,13 +6,26 @@ import { RouterLink } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Duration } from 'google-protobuf/google/protobuf/duration_pb';
|
||||
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 {
|
||||
ListProvidersRequest as AdminListProvidersRequest,
|
||||
ListProvidersResponse as AdminListProvidersResponse,
|
||||
} from 'src/app/proto/generated/zitadel/admin_pb';
|
||||
import {
|
||||
IDP,
|
||||
IDPLoginPolicyLink,
|
||||
IDPOwnerType,
|
||||
IDPState,
|
||||
IDPStylingType,
|
||||
Provider,
|
||||
ProviderType,
|
||||
} from 'src/app/proto/generated/zitadel/idp_pb';
|
||||
import {
|
||||
AddCustomLoginPolicyRequest,
|
||||
AddCustomLoginPolicyResponse,
|
||||
ListOrgIDPsResponse,
|
||||
ListProvidersRequest as MgmtListProvidersRequest,
|
||||
ListProvidersResponse as MgmtListProvidersResponse,
|
||||
} from 'src/app/proto/generated/zitadel/management_pb';
|
||||
import { ListQuery } from 'src/app/proto/generated/zitadel/object_pb';
|
||||
import { LoginPolicy } from 'src/app/proto/generated/zitadel/policy_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
@@ -31,16 +44,17 @@ export class IdpTableComponent implements OnInit {
|
||||
@Input() public serviceType!: PolicyComponentServiceType;
|
||||
@Input() service!: AdminService | ManagementService;
|
||||
@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 dataSource: MatTableDataSource<Provider.AsObject> = new MatTableDataSource<Provider.AsObject>();
|
||||
public selection: SelectionModel<Provider.AsObject> = new SelectionModel<Provider.AsObject>(true, []);
|
||||
public idpResult?: MgmtListProvidersResponse.AsObject | AdminListProvidersResponse.AsObject;
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
public IDPOwnerType: any = IDPOwnerType;
|
||||
public IDPState: any = IDPState;
|
||||
public displayedColumns: string[] = ['availability', 'name', 'type', 'creationDate', 'changeDate', 'state', 'actions'];
|
||||
@Output() public changedSelection: EventEmitter<Array<IDP.AsObject>> = new EventEmitter();
|
||||
public ProviderType: any = ProviderType;
|
||||
public displayedColumns: string[] = ['availability', 'name', 'type', 'creationDate', 'changeDate', 'actions'];
|
||||
@Output() public changedSelection: EventEmitter<Array<Provider.AsObject>> = new EventEmitter();
|
||||
|
||||
public idps: IDPLoginPolicyLink.AsObject[] = [];
|
||||
public IDPStylingType: any = IDPStylingType;
|
||||
@@ -59,7 +73,7 @@ export class IdpTableComponent implements OnInit {
|
||||
});
|
||||
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
this.displayedColumns = ['availability', 'name', 'type', 'owner', 'creationDate', 'changeDate', 'state', 'actions'];
|
||||
this.displayedColumns = ['availability', 'name', 'type', 'owner', 'creationDate', 'changeDate', 'actions'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,8 +175,13 @@ export class IdpTableComponent implements OnInit {
|
||||
this.loadingSubject.next(true);
|
||||
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
const req = new MgmtListProvidersRequest();
|
||||
const lq = new ListQuery();
|
||||
lq.setOffset(offset);
|
||||
lq.setLimit(limit);
|
||||
req.setQuery(lq);
|
||||
(this.service as ManagementService)
|
||||
.listOrgIDPs(limit, offset)
|
||||
.listProviders(req)
|
||||
.then((resp) => {
|
||||
this.idpResult = resp;
|
||||
this.dataSource.data = resp.resultList;
|
||||
@@ -173,8 +192,13 @@ export class IdpTableComponent implements OnInit {
|
||||
this.loadingSubject.next(false);
|
||||
});
|
||||
} else {
|
||||
const req = new AdminListProvidersRequest();
|
||||
const lq = new ListQuery();
|
||||
lq.setOffset(offset);
|
||||
lq.setLimit(limit);
|
||||
req.setQuery(lq);
|
||||
(this.service as AdminService)
|
||||
.listIDPs(limit, offset)
|
||||
.listProviders(req)
|
||||
.then((resp) => {
|
||||
this.idpResult = resp;
|
||||
this.dataSource.data = resp.resultList;
|
||||
@@ -199,19 +223,15 @@ export class IdpTableComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
public routerLinkForRow(row: IDP.AsObject): any {
|
||||
public routerLinkForRow(row: Provider.AsObject): any {
|
||||
if (row.id) {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
switch (row.owner) {
|
||||
case IDPOwnerType.IDP_OWNER_TYPE_SYSTEM:
|
||||
return ['/instance', 'idp', row.id];
|
||||
case IDPOwnerType.IDP_OWNER_TYPE_ORG:
|
||||
return ['/org', 'idp', row.id];
|
||||
}
|
||||
break;
|
||||
case PolicyComponentServiceType.ADMIN:
|
||||
return ['/instance', 'idp', row.id];
|
||||
switch (row.type) {
|
||||
case ProviderType.PROVIDER_TYPE_OIDC:
|
||||
return [row.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM ? '/instance' : '/org', 'provider', 'oidc', row.id];
|
||||
case ProviderType.PROVIDER_TYPE_JWT:
|
||||
return [row.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM ? '/instance' : '/org', 'provider', 'jwt', row.id];
|
||||
case ProviderType.PROVIDER_TYPE_GOOGLE:
|
||||
return [row.owner === IDPOwnerType.IDP_OWNER_TYPE_SYSTEM ? '/instance' : '/org', 'provider', 'google', row.id];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,7 +298,7 @@ export class IdpTableComponent implements OnInit {
|
||||
return (this.service as ManagementService).addCustomLoginPolicy(mgmtreq);
|
||||
}
|
||||
|
||||
public addIdp(idp: IDP.AsObject | IDP.AsObject): Promise<any> {
|
||||
public addIdp(idp: Provider.AsObject): Promise<any> {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
if (this.isDefault) {
|
||||
@@ -307,13 +327,15 @@ export class IdpTableComponent implements OnInit {
|
||||
.addIDPToLoginPolicy(idp.id, idp.owner)
|
||||
.then(() => {
|
||||
this.toast.showInfo('IDP.TOAST.ADDED', true);
|
||||
this.getIdps()
|
||||
.then((resp) => {
|
||||
this.idps = resp;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.getIdps()
|
||||
.then((resp) => {
|
||||
this.idps = resp;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}, 2000);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
@@ -324,9 +346,15 @@ export class IdpTableComponent implements OnInit {
|
||||
.addIDPToLoginPolicy(idp.id)
|
||||
.then(() => {
|
||||
this.toast.showInfo('IDP.TOAST.ADDED', true);
|
||||
this.getIdps().then((resp) => {
|
||||
this.idps = resp;
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.getIdps()
|
||||
.then((resp) => {
|
||||
this.idps = resp;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}, 2000);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
@@ -334,7 +362,7 @@ export class IdpTableComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
public removeIdp(idp: IDP.AsObject): Promise<any> {
|
||||
public removeIdp(idp: Provider.AsObject): Promise<any> {
|
||||
switch (this.serviceType) {
|
||||
case PolicyComponentServiceType.MGMT:
|
||||
if (this.isDefault) {
|
||||
@@ -367,9 +395,15 @@ export class IdpTableComponent implements OnInit {
|
||||
.removeIDPFromLoginPolicy(idp.id)
|
||||
.then(() => {
|
||||
this.toast.showInfo('IDP.TOAST.REMOVED', true);
|
||||
this.getIdps().then((resp) => {
|
||||
this.idps = resp;
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.getIdps()
|
||||
.then((resp) => {
|
||||
this.idps = resp;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}, 2000);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
@@ -380,9 +414,15 @@ export class IdpTableComponent implements OnInit {
|
||||
.removeIDPFromLoginPolicy(idp.id)
|
||||
.then(() => {
|
||||
this.toast.showInfo('IDP.TOAST.REMOVED', true);
|
||||
this.getIdps().then((resp) => {
|
||||
this.idps = resp;
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.getIdps()
|
||||
.then((resp) => {
|
||||
this.idps = resp;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}, 2000);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toast.showError(error);
|
||||
@@ -390,7 +430,7 @@ export class IdpTableComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
public isEnabled(idp: IDP.AsObject): boolean {
|
||||
public isEnabled(idp: Provider.AsObject): boolean {
|
||||
return this.idps.findIndex((i) => i.idpId === idp.id) > -1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user