mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-07 22:55:12 +00:00
feat(console): u2f (#1080)
* fix user table count * grpc ge * move grpc * u2f * add u2f funcs * rm local grpc, u2f dialog * dialog u2f * 2fa button * mfa u2f credentialoptions * decode base64 to bytearray, id, challenge * u2f verify * spinner, remove, attribute col * delete mfa * add forcemfa to policy * add id to remove * fix: add missing remove u2f in management * user mgmt u2f delete, login policy * rm log * show attr in mgmt user mfa * add missing id of mfa * mfa table * multifaktor for admin, org * add secondfactor to gen component * remove circular dependency * lint * revert identity prov * add divider * login policy lint * Update console/src/app/modules/policies/login-policy/login-policy.component.html * Update console/src/app/modules/policies/login-policy/login-policy.component.html Co-authored-by: Maximilian Peintner <[email protected]> Co-authored-by: Livio Amstutz <[email protected]>
This commit is contained in:
co-authored by
Maximilian Peintner
Livio Amstutz
parent
cd44213e99
commit
c6fed8ae86
@@ -0,0 +1,19 @@
|
||||
<h1 mat-dialog-title class="title"><span>{{data.title | translate}}</span></h1>
|
||||
<div mat-dialog-content>
|
||||
<p class="desc">{{data.desc | translate}}</p>
|
||||
|
||||
<cnsl-form-field class="form-field" label="Access Code" required="true">
|
||||
<cnsl-label>{{'MFA.TYPE' | translate}}</cnsl-label>
|
||||
<mat-select [(ngModel)]="newMfaType">
|
||||
<mat-option *ngFor="let mfa of availableMfaTypes" [value]="mfa">
|
||||
{{(data.componentType == LoginMethodComponentType.SecondFactor ? 'MFA.SECONDFACTORTYPES.': LoginMethodComponentType.MultiFactor ? 'MFA.MULTIFACTORTYPES.': '')+mfa | translate}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</div>
|
||||
<div mat-dialog-actions class="action">
|
||||
<button mat-button (click)="closeDialog()"><span translate>ACTIONS.CLOSE</span></button>
|
||||
<button mat-raised-button class="ok-button" color="primary" (click)="closeDialogWithCode()"><span
|
||||
translate>ACTIONS.OK</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -0,0 +1,22 @@
|
||||
.title {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 14px;
|
||||
color: var(--grey);
|
||||
}
|
||||
|
||||
.form-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.action {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
button {
|
||||
margin-left: .5rem;
|
||||
border-radius: .5rem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
|
||||
import { MultiFactorType as AdminMultiFactorType } from 'src/app/proto/generated/admin_pb';
|
||||
import { MultiFactorType as MgmtMultiFactorType } from 'src/app/proto/generated/management_pb';
|
||||
|
||||
enum LoginMethodComponentType {
|
||||
MultiFactor = 1,
|
||||
SecondFactor = 2,
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-dialog-add-type',
|
||||
templateUrl: './dialog-add-type.component.html',
|
||||
styleUrls: ['./dialog-add-type.component.scss'],
|
||||
})
|
||||
export class DialogAddTypeComponent {
|
||||
public LoginMethodComponentType: any = LoginMethodComponentType;
|
||||
public newMfaType!: AdminMultiFactorType | MgmtMultiFactorType;
|
||||
public availableMfaTypes: Array<AdminMultiFactorType | MgmtMultiFactorType> = [];
|
||||
constructor(public dialogRef: MatDialogRef<DialogAddTypeComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any) {
|
||||
this.availableMfaTypes = data.types;
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
public closeDialogWithCode(): void {
|
||||
this.dialogRef.close(this.newMfaType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<div class="sp_wrapper">
|
||||
<mat-spinner diameter="30" *ngIf="loading$ | async"></mat-spinner>
|
||||
</div>
|
||||
<div class="mfa-list">
|
||||
<div class="mfa" *ngFor="let mfa of mfas">
|
||||
<button [disabled]="disabled" mat-icon-button (click)="removeMfa(mfa)" class="rm">
|
||||
<mat-icon matTooltip="{{'ACTIONS.REMOVE' | translate}}">
|
||||
remove_circle</mat-icon>
|
||||
</button>
|
||||
{{(componentType == LoginMethodComponentType.SecondFactor ? 'MFA.SECONDFACTORTYPES.': LoginMethodComponentType.MultiFactor ? 'MFA.MULTIFACTORTYPES.': '')+mfa | translate}}
|
||||
</div>
|
||||
<div class="mfa" (click)="addMfa()">
|
||||
<mat-icon>add</mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
.t .sp_wrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mfa-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 -.5rem;
|
||||
|
||||
.mfa {
|
||||
border: 1px solid var(--grey);
|
||||
border-radius: .5rem;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: .5rem;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
min-height: 70px;
|
||||
min-width: 150px;
|
||||
|
||||
.rm {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
cursor: pointer;
|
||||
|
||||
&[disabled] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.disabled) {
|
||||
&:hover {
|
||||
background-color: #ffffff10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { MfaTableComponent } from './mfa-table.component';
|
||||
|
||||
describe('MfaTableComponent', () => {
|
||||
let component: MfaTableComponent;
|
||||
let fixture: ComponentFixture<MfaTableComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [MfaTableComponent],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MfaTableComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,220 @@
|
||||
import { Component, Input, OnInit, ViewChild } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatPaginator } from '@angular/material/paginator';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import {
|
||||
MultiFactor as AdminMultiFactor, MultiFactorType as AdminMultiFactorType,
|
||||
SecondFactor as AdminSecondFactor, SecondFactorType as AdminSecondFactorType,
|
||||
} from 'src/app/proto/generated/admin_pb';
|
||||
import {
|
||||
MultiFactor as MgmtMultiFactor, MultiFactorType as MgmtMultiFactorType,
|
||||
SecondFactor as MgmtSecondFactor, SecondFactorType as MgmtSecondFactorType,
|
||||
} from 'src/app/proto/generated/management_pb';
|
||||
import { AdminService } from 'src/app/services/admin.service';
|
||||
import { ManagementService } from 'src/app/services/mgmt.service';
|
||||
import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { PolicyComponentServiceType } from '../policies/policy-component-types.enum';
|
||||
import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
|
||||
import { DialogAddTypeComponent } from './dialog-add-type/dialog-add-type.component';
|
||||
|
||||
export enum LoginMethodComponentType {
|
||||
MultiFactor = 1,
|
||||
SecondFactor = 2,
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-mfa-table',
|
||||
templateUrl: './mfa-table.component.html',
|
||||
styleUrls: ['./mfa-table.component.scss'],
|
||||
})
|
||||
export class MfaTableComponent implements OnInit {
|
||||
public LoginMethodComponentType: any = LoginMethodComponentType;
|
||||
@Input() componentType!: LoginMethodComponentType;
|
||||
@Input() public serviceType!: PolicyComponentServiceType;
|
||||
@Input() service!: AdminService | ManagementService;
|
||||
@Input() disabled: boolean = false;
|
||||
@ViewChild(MatPaginator) public paginator!: MatPaginator;
|
||||
public mfas: Array<AdminMultiFactorType | MgmtMultiFactorType | MgmtSecondFactorType | AdminSecondFactorType> = [];
|
||||
|
||||
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
|
||||
|
||||
public PolicyComponentServiceType: any = PolicyComponentServiceType;
|
||||
|
||||
constructor(public translate: TranslateService, private toast: ToastService, private dialog: MatDialog) { }
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.getData();
|
||||
}
|
||||
|
||||
public removeMfa(type: MgmtMultiFactorType | AdminMultiFactorType | MgmtSecondFactorType | AdminSecondFactorType): void {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.DELETE',
|
||||
cancelKey: 'ACTIONS.CANCEL',
|
||||
titleKey: 'MFA.DELETE.TITLE',
|
||||
descriptionKey: 'MFA.DELETE.DESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(resp => {
|
||||
if (resp) {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
if (this.componentType === LoginMethodComponentType.MultiFactor) {
|
||||
const req = new MgmtMultiFactor();
|
||||
req.setMultiFactor(type as MgmtMultiFactorType);
|
||||
(this.service as ManagementService).RemoveMultiFactorFromLoginPolicy(req).then(() => {
|
||||
this.toast.showInfo('MFA.TOAST.DELETED', true);
|
||||
this.refreshPageAfterTimout(2000);
|
||||
});
|
||||
} else if (this.componentType === LoginMethodComponentType.SecondFactor) {
|
||||
const req = new MgmtSecondFactor();
|
||||
req.setSecondFactor(type as MgmtSecondFactorType);
|
||||
(this.service as ManagementService).RemoveSecondFactorFromLoginPolicy(req).then(() => {
|
||||
this.toast.showInfo('MFA.TOAST.DELETED', true);
|
||||
this.refreshPageAfterTimout(2000);
|
||||
});
|
||||
}
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||
if (this.componentType === LoginMethodComponentType.MultiFactor) {
|
||||
const req = new AdminMultiFactor();
|
||||
req.setMultiFactor(type as AdminMultiFactorType);
|
||||
(this.service as AdminService).RemoveMultiFactorFromDefaultLoginPolicy(req).then(() => {
|
||||
this.toast.showInfo('MFA.TOAST.DELETED', true);
|
||||
this.refreshPageAfterTimout(2000);
|
||||
});
|
||||
} else if (this.componentType === LoginMethodComponentType.SecondFactor) {
|
||||
const req = new AdminSecondFactor();
|
||||
req.setSecondFactor(type as AdminSecondFactorType);
|
||||
(this.service as AdminService).RemoveSecondFactorFromDefaultLoginPolicy(req).then(() => {
|
||||
this.toast.showInfo('MFA.TOAST.DELETED', true);
|
||||
this.refreshPageAfterTimout(2000);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public addMfa(): void {
|
||||
|
||||
let selection: any[] = [];
|
||||
|
||||
if (this.componentType === LoginMethodComponentType.MultiFactor) {
|
||||
selection = this.serviceType === PolicyComponentServiceType.MGMT ?
|
||||
[MgmtMultiFactorType.MULTIFACTORTYPE_U2F_WITH_PIN] :
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN ?
|
||||
[AdminMultiFactorType.MULTIFACTORTYPE_U2F_WITH_PIN] :
|
||||
[];
|
||||
} else if (this.componentType === LoginMethodComponentType.SecondFactor) {
|
||||
selection = this.serviceType === PolicyComponentServiceType.MGMT ?
|
||||
[MgmtSecondFactorType.SECONDFACTORTYPE_U2F, MgmtSecondFactorType.SECONDFACTORTYPE_U2F] :
|
||||
this.serviceType === PolicyComponentServiceType.ADMIN ?
|
||||
[AdminSecondFactorType.SECONDFACTORTYPE_OTP, AdminSecondFactorType.SECONDFACTORTYPE_U2F] :
|
||||
[];
|
||||
}
|
||||
const dialogRef = this.dialog.open(DialogAddTypeComponent, {
|
||||
data: {
|
||||
title: 'MFA.CREATE.TITLE',
|
||||
desc: 'MFA.CREATE.DESCRIPTION',
|
||||
componentType: this.componentType,
|
||||
types: selection,
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((mfaType: AdminMultiFactorType | MgmtMultiFactorType |
|
||||
AdminSecondFactorType | MgmtSecondFactorType) => {
|
||||
if (mfaType) {
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
if (this.componentType === LoginMethodComponentType.MultiFactor) {
|
||||
const req = new MgmtMultiFactor();
|
||||
req.setMultiFactor(mfaType as MgmtMultiFactorType);
|
||||
(this.service as ManagementService).AddMultiFactorToLoginPolicy(req).then(() => {
|
||||
this.refreshPageAfterTimout(2000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else if (this.componentType === LoginMethodComponentType.SecondFactor) {
|
||||
const req = new MgmtSecondFactor();
|
||||
req.setSecondFactor(mfaType as MgmtSecondFactorType);
|
||||
(this.service as ManagementService).AddSecondFactorToLoginPolicy(req).then(() => {
|
||||
this.refreshPageAfterTimout(2000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||
if (this.componentType === LoginMethodComponentType.MultiFactor) {
|
||||
const req = new AdminMultiFactor();
|
||||
req.setMultiFactor(mfaType as AdminMultiFactorType);
|
||||
(this.service as AdminService).addMultiFactorToDefaultLoginPolicy(req).then(() => {
|
||||
this.refreshPageAfterTimout(2000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
} else if (this.componentType === LoginMethodComponentType.SecondFactor) {
|
||||
const req = new AdminSecondFactor();
|
||||
req.setSecondFactor(mfaType as AdminSecondFactorType);
|
||||
(this.service as AdminService).AddSecondFactorToDefaultLoginPolicy(req).then(() => {
|
||||
this.refreshPageAfterTimout(2000);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async getData(): Promise<void> {
|
||||
this.loadingSubject.next(true);
|
||||
|
||||
if (this.serviceType === PolicyComponentServiceType.MGMT) {
|
||||
if (this.componentType === LoginMethodComponentType.MultiFactor) {
|
||||
(this.service as ManagementService).GetLoginPolicyMultiFactors().then(resp => {
|
||||
this.mfas = resp.toObject().multiFactorsList;
|
||||
this.loadingSubject.next(false);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
this.loadingSubject.next(false);
|
||||
});
|
||||
} else if (this.componentType === LoginMethodComponentType.SecondFactor) {
|
||||
(this.service as ManagementService).GetLoginPolicySecondFactors().then(resp => {
|
||||
this.mfas = resp.toObject().secondFactorsList;
|
||||
this.loadingSubject.next(false);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
this.loadingSubject.next(false);
|
||||
});
|
||||
}
|
||||
} else if (this.serviceType === PolicyComponentServiceType.ADMIN) {
|
||||
if (this.componentType === LoginMethodComponentType.MultiFactor) {
|
||||
(this.service as AdminService).getDefaultLoginPolicyMultiFactors().then(resp => {
|
||||
this.mfas = resp.toObject().multiFactorsList;
|
||||
this.loadingSubject.next(false);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
this.loadingSubject.next(false);
|
||||
});
|
||||
} else if (this.componentType === LoginMethodComponentType.SecondFactor) {
|
||||
(this.service as AdminService).GetDefaultLoginPolicySecondFactors().then(resp => {
|
||||
this.mfas = resp.toObject().secondFactorsList;
|
||||
this.loadingSubject.next(false);
|
||||
}).catch(error => {
|
||||
this.toast.showError(error);
|
||||
this.loadingSubject.next(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public refreshPageAfterTimout(to: number): void {
|
||||
setTimeout(() => {
|
||||
this.getData();
|
||||
}, to);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
|
||||
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
|
||||
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/localized-date-pipe.module';
|
||||
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
|
||||
import { TruncatePipeModule } from 'src/app/pipes/truncate-pipe/truncate-pipe.module';
|
||||
|
||||
import { MfaTableComponent } from './mfa-table.component';
|
||||
import { DialogAddTypeComponent } from './dialog-add-type/dialog-add-type.component';
|
||||
import { InputModule } from '../input/input.module';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
|
||||
@NgModule({
|
||||
declarations: [MfaTableComponent, DialogAddTypeComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
InputModule,
|
||||
MatSelectModule,
|
||||
MatTooltipModule,
|
||||
TranslateModule,
|
||||
TimestampToDatePipeModule,
|
||||
HasRoleModule,
|
||||
MatProgressSpinnerModule,
|
||||
],
|
||||
exports: [
|
||||
MfaTableComponent,
|
||||
],
|
||||
})
|
||||
export class MfaTableModule { }
|
||||
@@ -44,8 +44,34 @@
|
||||
</mat-slide-toggle>
|
||||
<p> {{'POLICY.DATA.ALLOWEXTERNALIDP_DESC' | translate}} </p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<mat-slide-toggle class="toggle" color="primary" [disabled]="disabled" ngDefaultControl
|
||||
[(ngModel)]="loginData.forceMfa">
|
||||
{{'POLICY.DATA.FORCEMFA' | translate}}
|
||||
</mat-slide-toggle>
|
||||
<p> {{'POLICY.DATA.FORCEMFA_DESC' | translate}} </p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button [disabled]="disabled" class="save-button" (click)="savePolicy()" color="primary" type="submit"
|
||||
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<h3 class="subheader">{{ 'MFA.LIST.MULTIFACTORTITLE' | translate }}</h3>
|
||||
<p class="subdesc">{{ 'MFA.LIST.MULTIFACTORDESCRIPTION' | translate }}</p>
|
||||
<app-mfa-table [service]="service" [serviceType]="serviceType"
|
||||
[componentType]="LoginMethodComponentType.MultiFactor"
|
||||
[disabled]="([serviceType == PolicyComponentServiceType.ADMIN ? 'iam.policy.write' : serviceType == PolicyComponentServiceType.MGMT ? 'org.policy.write' : ''] | hasRole | async) == false">
|
||||
</app-mfa-table>
|
||||
|
||||
<h3 class="subheader">{{ 'MFA.LIST.SECONDFACTORTITLE' | translate }}</h3>
|
||||
<p class="subdesc">{{ 'MFA.LIST.SECONDFACTORDESCRIPTION' | translate }}</p>
|
||||
<app-mfa-table [service]="service" [serviceType]="serviceType"
|
||||
[componentType]="LoginMethodComponentType.SecondFactor"
|
||||
[disabled]="([serviceType == PolicyComponentServiceType.ADMIN ? 'iam.policy.write' : serviceType == PolicyComponentServiceType.MGMT ? 'org.policy.write' : ''] | hasRole | async) == false">
|
||||
</app-mfa-table>
|
||||
|
||||
<h3 class="subheader">{{'LOGINPOLICY.IDPS' | translate}}</h3>
|
||||
|
||||
<div class="idps">
|
||||
@@ -63,9 +89,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button [disabled]="disabled" class="save-button" (click)="savePolicy()" color="primary" type="submit"
|
||||
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
|
||||
|
||||
<ng-template appHasRole [appHasRole]="['org.idp.read']">
|
||||
<h2>{{ 'IDP.LIST.TITLE' | translate }}</h2>
|
||||
<p>{{ 'IDP.LIST.DESCRIPTION' | translate }}</p>
|
||||
@@ -73,4 +96,4 @@
|
||||
[disabled]="([serviceType == PolicyComponentServiceType.ADMIN ? 'iam.idp.write' : serviceType == PolicyComponentServiceType.MGMT ? 'org.idp.write' : ''] | hasRole | async) == false">
|
||||
</app-idp-table>
|
||||
</ng-template>
|
||||
</app-detail-layout>
|
||||
</app-detail-layout>
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.subdesc {
|
||||
color: var(--grey);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.idps {
|
||||
display: flex;
|
||||
margin: 0 -.5rem;
|
||||
@@ -93,3 +98,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background-color: var(--grey);
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import { ToastService } from 'src/app/services/toast.service';
|
||||
|
||||
import { PolicyComponentServiceType } from '../policy-component-types.enum';
|
||||
import { AddIdpDialogComponent } from './add-idp-dialog/add-idp-dialog.component';
|
||||
import { LoginMethodComponentType } from 'src/app/modules/mfa-table/mfa-table.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login-policy',
|
||||
@@ -29,6 +30,7 @@ import { AddIdpDialogComponent } from './add-idp-dialog/add-idp-dialog.component
|
||||
styleUrls: ['./login-policy.component.scss'],
|
||||
})
|
||||
export class LoginPolicyComponent implements OnDestroy {
|
||||
public LoginMethodComponentType: any = LoginMethodComponentType;
|
||||
public loginData!: LoginPolicyView.AsObject | DefaultLoginPolicyView.AsObject;
|
||||
|
||||
private sub: Subscription = new Subscription();
|
||||
@@ -112,6 +114,8 @@ export class LoginPolicyComponent implements OnDestroy {
|
||||
mgmtreq.setAllowExternalIdp(this.loginData.allowExternalIdp);
|
||||
mgmtreq.setAllowRegister(this.loginData.allowRegister);
|
||||
mgmtreq.setAllowUsernamePassword(this.loginData.allowUsernamePassword);
|
||||
mgmtreq.setForceMfa(this.loginData.forceMfa);
|
||||
// console.log(mgmtreq.toObject());
|
||||
if ((this.loginData as LoginPolicyView.AsObject).pb_default) {
|
||||
return (this.service as ManagementService).CreateLoginPolicy(mgmtreq);
|
||||
} else {
|
||||
@@ -122,6 +126,9 @@ export class LoginPolicyComponent implements OnDestroy {
|
||||
adminreq.setAllowExternalIdp(this.loginData.allowExternalIdp);
|
||||
adminreq.setAllowRegister(this.loginData.allowRegister);
|
||||
adminreq.setAllowUsernamePassword(this.loginData.allowUsernamePassword);
|
||||
adminreq.setForceMfa(this.loginData.forceMfa);
|
||||
// console.log(adminreq.toObject());
|
||||
|
||||
return (this.service as AdminService).UpdateDefaultLoginPolicy(adminreq);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.mod
|
||||
import { AddIdpDialogModule } from './add-idp-dialog/add-idp-dialog.module';
|
||||
import { LoginPolicyRoutingModule } from './login-policy-routing.module';
|
||||
import { LoginPolicyComponent } from './login-policy.component';
|
||||
import { MfaTableModule } from 'src/app/modules/mfa-table/mfa-table.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [LoginPolicyComponent],
|
||||
@@ -36,6 +37,7 @@ import { LoginPolicyComponent } from './login-policy.component';
|
||||
DetailLayoutModule,
|
||||
AddIdpDialogModule,
|
||||
IdpTableModule,
|
||||
MfaTableModule,
|
||||
MatProgressSpinnerModule,
|
||||
],
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user