feat(console): email label policy, cleanup policy grid module (#890)

* add primitive label policy component, routing

* label policy, i18n

* refactor policy grid

* i18n

* lint

* cleanup i19n policy

* rm failed events styling

* fix detail layout padding, de i18n

* remove unused translations
This commit is contained in:
Max Peintner 2020-10-24 20:28:48 +02:00 committed by GitHub
parent a7ed5fed50
commit e7514998bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 549 additions and 544 deletions

View File

@ -13,7 +13,6 @@
width: 100%;
display: flex;
padding-bottom: 3rem;
padding-top: 3rem;
.detail-left {
width: 100px;

View File

@ -0,0 +1,20 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LabelPolicyComponent } from './label-policy.component';
const routes: Routes = [
{
path: '',
component: LabelPolicyComponent,
data: {
animation: 'DetailPage',
},
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class LabelPolicyRoutingModule { }

View File

@ -0,0 +1,20 @@
<app-detail-layout [backRouterLink]="['/iam']" [title]="'POLICY.LABEL.TITLE' | translate"
[description]="'POLICY.LABEL.DESCRIPTION' | translate">
<div class="content" *ngIf="labelData">
<mat-form-field class="form-field" appearance="outline">
<mat-label>{{'POLICY.LABEL.PRIMARYCOLOR' | translate}}</mat-label>
<input [(ngModel)]="labelData.primaryColor" matInput />
</mat-form-field>
<mat-form-field class="form-field" appearance="outline">
<mat-label>{{'POLICY.LABEL.SECONDARYCOLOR' | translate}}</mat-label>
<input [(ngModel)]="labelData.secondaryColor" matInput />
</mat-form-field>
</div>
<div class="btn-container">
<button (click)="savePolicy()" color="primary" type="submit"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
</div>
</app-detail-layout>

View File

@ -0,0 +1,24 @@
.content {
padding-top: 1rem;
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0 -.5rem;
.form-field {
flex: 1;
margin: 0 .5rem;
}
}
.btn-container {
display: flex;
justify-content: flex-end;
width: 100%;
button {
margin-top: 3rem;
display: block;
padding: .5rem 4rem;
}
}

View File

@ -1,20 +1,20 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { IamPolicyGridComponent } from './iam-policy-grid.component';
import { LabelPolicyComponent } from './label-policy.component';
describe('IamPolicyGridComponent', () => {
let component: IamPolicyGridComponent;
let fixture: ComponentFixture<IamPolicyGridComponent>;
describe('LabelPolicyComponent', () => {
let component: LabelPolicyComponent;
let fixture: ComponentFixture<LabelPolicyComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [IamPolicyGridComponent],
declarations: [LabelPolicyComponent],
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(IamPolicyGridComponent);
fixture = TestBed.createComponent(LabelPolicyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

View File

@ -0,0 +1,54 @@
import { Component, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
import { DefaultLabelPolicyUpdate, DefaultLabelPolicyView } from 'src/app/proto/generated/admin_pb';
import { AdminService } from 'src/app/services/admin.service';
import { ToastService } from 'src/app/services/toast.service';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
@Component({
selector: 'app-label-policy',
templateUrl: './label-policy.component.html',
styleUrls: ['./label-policy.component.scss'],
})
export class LabelPolicyComponent implements OnDestroy {
public labelData!: DefaultLabelPolicyView.AsObject;
private sub: Subscription = new Subscription();
public PolicyComponentServiceType: any = PolicyComponentServiceType;
constructor(
private route: ActivatedRoute,
private toast: ToastService,
private adminService: AdminService,
) {
this.route.params.subscribe(() => {
this.getData().then(data => {
if (data) {
this.labelData = data.toObject();
}
});
});
}
public ngOnDestroy(): void {
this.sub.unsubscribe();
}
private async getData(): Promise<DefaultLabelPolicyView> {
return this.adminService.GetDefaultLabelPolicy();
}
public savePolicy(): void {
const req = new DefaultLabelPolicyUpdate();
req.setPrimaryColor(this.labelData.primaryColor);
req.setSecondaryColor(this.labelData.secondaryColor);
this.adminService.UpdateDefaultLabelPolicy(req).then(() => {
this.toast.showInfo('POLICY.TOAST.SET', true);
}).catch(error => {
this.toast.showError(error);
});
}
}

View File

@ -0,0 +1,34 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.module';
import { LabelPolicyRoutingModule } from './label-policy-routing.module';
import { LabelPolicyComponent } from './label-policy.component';
@NgModule({
declarations: [LabelPolicyComponent],
imports: [
LabelPolicyRoutingModule,
CommonModule,
FormsModule,
MatInputModule,
MatFormFieldModule,
MatButtonModule,
MatSlideToggleModule,
MatIconModule,
HasRoleModule,
MatTooltipModule,
TranslateModule,
DetailLayoutModule,
],
})
export class LabelPolicyModule { }

View File

@ -1,23 +1,23 @@
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam' : '/org']"
[title]="'ORG.POLICY.LOGIN_POLICY.TITLECREATE' | translate"
[description]="(serviceType==PolicyComponentServiceType.MGMT ? 'ORG.POLICY.LOGIN_POLICY.DESCRIPTIONCREATEMGMT' : PolicyComponentServiceType.ADMIN ? 'ORG.POLICY.LOGIN_POLICY.DESCRIPTIONCREATEADMIN' : '') | translate">
<p class="default" *ngIf="isDefault"> {{'ORG.POLICY.DEFAULTLABEL' | translate}}</p>
[title]="'POLICY.LOGIN_POLICY.TITLE' | translate"
[description]="(serviceType==PolicyComponentServiceType.MGMT ? 'POLICY.LOGIN_POLICY.DESCRIPTIONCREATEMGMT' : PolicyComponentServiceType.ADMIN ? 'POLICY.LOGIN_POLICY.DESCRIPTIONCREATEADMIN' : '') | translate">
<p class="default" *ngIf="isDefault"> {{'POLICY.DEFAULTLABEL' | translate}}</p>
<div class="spinner-wr">
<mat-spinner diameter="30" *ngIf="loading" color="primary"></mat-spinner>
</div>
<ng-container *ngIf="serviceType === PolicyComponentServiceType.MGMT">
<ng-template appHasRole [appHasRole]="['policy.delete']">
<button *ngIf="!isDefault" matTooltip="{{'ORG.POLICY.RESET' | translate}}" color="warn"
(click)="removePolicy()" mat-stroked-button>
{{'ORG.POLICY.RESET' | translate}}
<button *ngIf="!isDefault" matTooltip="{{'POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()"
mat-stroked-button>
{{'POLICY.RESET' | translate}}
</button>
</ng-template>
<ng-template appHasRole [appHasRole]="['policy.write']">
<button *ngIf="isDefault" matTooltip="{{'ORG.POLICY.CREATECUSTOM' | translate}}" (click)="savePolicy()"
<button *ngIf="isDefault" matTooltip="{{'POLICY.CREATECUSTOM' | translate}}" (click)="savePolicy()"
mat-raised-button>
{{'ORG.POLICY.CREATECUSTOM' | translate}}
{{'POLICY.CREATECUSTOM' | translate}}
</button>
</ng-template>
</ng-container>
@ -26,23 +26,23 @@
<div class="row">
<mat-slide-toggle class="toggle" color="primary" [disabled]="disabled" ngDefaultControl
[(ngModel)]="loginData.allowUsernamePassword">
{{'ORG.POLICY.DATA.ALLOWUSERNAMEPASSWORD' | translate}}
{{'POLICY.DATA.ALLOWUSERNAMEPASSWORD' | translate}}
</mat-slide-toggle>
<p>{{'ORG.POLICY.DATA.ALLOWUSERNAMEPASSWORD_DESC' | translate}}</p>
<p>{{'POLICY.DATA.ALLOWUSERNAMEPASSWORD_DESC' | translate}}</p>
</div>
<div class="row">
<mat-slide-toggle class="toggle" color="primary" [disabled]="disabled" ngDefaultControl
[(ngModel)]="loginData.allowRegister">
{{'ORG.POLICY.DATA.ALLOWREGISTER' | translate}}
{{'POLICY.DATA.ALLOWREGISTER' | translate}}
</mat-slide-toggle>
<p> {{'ORG.POLICY.DATA.ALLOWREGISTER_DESC' | translate}} </p>
<p> {{'POLICY.DATA.ALLOWREGISTER_DESC' | translate}} </p>
</div>
<div class="row">
<mat-slide-toggle class="toggle" color="primary" [disabled]="disabled" ngDefaultControl
[(ngModel)]="loginData.allowExternalIdp">
{{'ORG.POLICY.DATA.ALLOWEXTERNALIDP' | translate}}
{{'POLICY.DATA.ALLOWEXTERNALIDP' | translate}}
</mat-slide-toggle>
<p> {{'ORG.POLICY.DATA.ALLOWEXTERNALIDP_DESC' | translate}} </p>
<p> {{'POLICY.DATA.ALLOWEXTERNALIDP_DESC' | translate}} </p>
</div>
</div>

View File

@ -128,7 +128,7 @@ export class LoginPolicyComponent implements OnDestroy {
public savePolicy(): void {
this.updateData().then(() => {
this.toast.showInfo('ORG.POLICY.LOGIN_POLICY.SAVED', true);
this.toast.showInfo('POLICY.LOGIN_POLICY.SAVED', true);
this.loading = true;
setTimeout(() => {
this.fetchData();
@ -141,7 +141,7 @@ export class LoginPolicyComponent implements OnDestroy {
public removePolicy(): void {
if (this.serviceType === PolicyComponentServiceType.MGMT) {
(this.service as ManagementService).RemoveLoginPolicy().then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.RESETSUCCESS', true);
this.toast.showInfo('POLICY.TOAST.RESETSUCCESS', true);
this.loading = true;
setTimeout(() => {
this.fetchData();

View File

@ -1,18 +1,17 @@
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam' : '/org']"
[title]="'ORG.POLICY.IAM_POLICY.TITLECREATE' | translate"
[description]="'ORG.POLICY.IAM_POLICY.DESCRIPTION' | translate">
<p class="default" *ngIf="isDefault"> {{'ORG.POLICY.DEFAULTLABEL' | translate}}</p>
[title]="'POLICY.IAM_POLICY.TITLECREATE' | translate" [description]="'POLICY.IAM_POLICY.DESCRIPTION' | translate">
<p class="default" *ngIf="isDefault"> {{'POLICY.DEFAULTLABEL' | translate}}</p>
<ng-template appHasRole [appHasRole]="['iam.policy.delete']">
<button *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
matTooltip="{{'ORG.POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
{{'ORG.POLICY.RESET' | translate}}
matTooltip="{{'POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
{{'POLICY.RESET' | translate}}
</button>
</ng-template>
<div class="content" *ngIf="iamData">
<div class="row">
<span class="left-desc">{{'ORG.POLICY.DATA.USERLOGINMUSTBEDOMAIN' | translate}}</span>
<span class="left-desc">{{'POLICY.DATA.USERLOGINMUSTBEDOMAIN' | translate}}</span>
<span class="fill-space"></span>
<mat-slide-toggle color="primary" name="hasNumber" ngDefaultControl
[(ngModel)]="iamData.userLoginMustBeDomain">

View File

@ -83,7 +83,7 @@ export class OrgIamPolicyComponent implements OnDestroy {
this.org.id,
this.iamData.userLoginMustBeDomain,
).then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
this.toast.showInfo('POLICY.TOAST.SET', true);
}).catch(error => {
this.toast.showError(error);
});
@ -93,7 +93,7 @@ export class OrgIamPolicyComponent implements OnDestroy {
this.org.id,
this.iamData.userLoginMustBeDomain,
).then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
this.toast.showInfo('POLICY.TOAST.SET', true);
}).catch(error => {
this.toast.showError(error);
});
@ -105,7 +105,7 @@ export class OrgIamPolicyComponent implements OnDestroy {
this.org.id,
this.iamData.userLoginMustBeDomain,
).then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
this.toast.showInfo('POLICY.TOAST.SET', true);
}).catch(error => {
this.toast.showError(error);
});
@ -116,7 +116,7 @@ export class OrgIamPolicyComponent implements OnDestroy {
public removePolicy(): void {
if (this.serviceType === PolicyComponentServiceType.MGMT) {
this.adminService.RemoveOrgIamPolicy(this.org.id).then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.RESETSUCCESS', true);
this.toast.showInfo('POLICY.TOAST.RESETSUCCESS', true);
setTimeout(() => {
this.fetchData();
}, 1000);

View File

@ -1,15 +1,15 @@
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam' : '/org']"
[title]="'ORG.POLICY.PWD_AGE.TITLE' | translate" [description]="'ORG.POLICY.PWD_AGE.DESCRIPTION' | translate">
[title]="'POLICY.PWD_AGE.TITLE' | translate" [description]="'POLICY.PWD_AGE.DESCRIPTION' | translate">
<ng-template appHasRole [appHasRole]="['policy.delete']">
<button *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
matTooltip="{{'ORG.POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
{{'ORG.POLICY.RESET' | translate}}
matTooltip="{{'POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
{{'POLICY.RESET' | translate}}
</button>
</ng-template>
<div class="content" *ngIf="ageData">
<div class="row">
<span class="left-desc">{{'ORG.POLICY.DATA.EXPIREWARNDAYS' | translate}}</span>
<span class="left-desc">{{'POLICY.DATA.EXPIREWARNDAYS' | translate}}</span>
<span class="fill-space"></span>
<div class="length-wrapper">
<button mat-icon-button (click)="incrementExpireWarnDays()">
@ -23,7 +23,7 @@
</div>
<div class="row">
<span class="left-desc">{{'ORG.POLICY.DATA.MAXAGEDAYS' | translate}}</span>
<span class="left-desc">{{'POLICY.DATA.MAXAGEDAYS' | translate}}</span>
<span class="fill-space"></span>
<div class="length-wrapper">
<button mat-icon-button (click)="incrementMaxAgeDays()">

View File

@ -69,7 +69,7 @@ export class PasswordAgePolicyComponent implements OnDestroy {
public removePolicy(): void {
if (this.serviceType === PolicyComponentServiceType.MGMT) {
(this.service as ManagementService).RemovePasswordAgePolicy().then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.RESETSUCCESS', true);
this.toast.showInfo('POLICY.TOAST.RESETSUCCESS', true);
setTimeout(() => {
this.getData();
}, 1000);
@ -111,7 +111,7 @@ export class PasswordAgePolicyComponent implements OnDestroy {
this.ageData.maxAgeDays,
this.ageData.expireWarnDays,
).then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
this.toast.showInfo('POLICY.TOAST.SET', true);
}).catch(error => {
this.toast.showError(error);
});
@ -120,7 +120,7 @@ export class PasswordAgePolicyComponent implements OnDestroy {
this.ageData.maxAgeDays,
this.ageData.expireWarnDays,
).then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
this.toast.showInfo('POLICY.TOAST.SET', true);
}).catch(error => {
this.toast.showError(error);
});
@ -131,7 +131,7 @@ export class PasswordAgePolicyComponent implements OnDestroy {
this.ageData.maxAgeDays,
this.ageData.expireWarnDays,
).then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
this.toast.showInfo('POLICY.TOAST.SET', true);
}).catch(error => {
this.toast.showError(error);
});

View File

@ -1,8 +1,7 @@
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam' : '/org']"
[title]="'ORG.POLICY.PWD_COMPLEXITY.TITLE' | translate"
[description]="'ORG.POLICY.PWD_COMPLEXITY.DESCRIPTION' | translate">
[title]="'POLICY.PWD_COMPLEXITY.TITLE' | translate" [description]="'POLICY.PWD_COMPLEXITY.DESCRIPTION' | translate">
<p class="default" *ngIf="isDefault"> {{'ORG.POLICY.DEFAULTLABEL' | translate}}</p>
<p class="default" *ngIf="isDefault"> {{'POLICY.DEFAULTLABEL' | translate}}</p>
<div class="spinner-wr">
<mat-spinner diameter="30" *ngIf="loading" color="primary"></mat-spinner>
@ -10,14 +9,14 @@
<ng-template appHasRole [appHasRole]="['policy.delete']">
<button *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
matTooltip="{{'ORG.POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
{{'ORG.POLICY.RESET' | translate}}
matTooltip="{{'POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
{{'POLICY.RESET' | translate}}
</button>
</ng-template>
<div *ngIf="complexityData" class="content">
<div class="row">
<span class="left-desc">{{'ORG.POLICY.DATA.MINLENGTH' | translate}}</span>
<span class="left-desc">{{'POLICY.DATA.MINLENGTH' | translate}}</span>
<span class="fill-space"></span>
<div class="length-wrapper">
<button mat-icon-button (click)="decrementLength()">
@ -30,26 +29,26 @@
</div>
</div>
<div class="row">
<span class="left-desc">{{'ORG.POLICY.DATA.HASNUMBER' | translate}}</span>
<span class="left-desc">{{'POLICY.DATA.HASNUMBER' | translate}}</span>
<span class="fill-space"></span>
<mat-slide-toggle color="primary" name="hasNumber" ngDefaultControl [(ngModel)]="complexityData.hasNumber">
</mat-slide-toggle>
</div>
<div class="row">
<span class="left-desc">{{'ORG.POLICY.DATA.HASSYMBOL' | translate}}</span>
<span class="left-desc">{{'POLICY.DATA.HASSYMBOL' | translate}}</span>
<span class="fill-space"></span>
<mat-slide-toggle color="primary" name="hasSymbol" ngDefaultControl [(ngModel)]="complexityData.hasSymbol">
</mat-slide-toggle>
</div>
<div class="row">
<span class="left-desc">{{'ORG.POLICY.DATA.HASLOWERCASE' | translate}}</span>
<span class="left-desc">{{'POLICY.DATA.HASLOWERCASE' | translate}}</span>
<span class="fill-space"></span>
<mat-slide-toggle color="primary" name="hasLowercase" ngDefaultControl
[(ngModel)]="complexityData.hasLowercase">
</mat-slide-toggle>
</div>
<div class="row">
<span class="left-desc">{{'ORG.POLICY.DATA.HASUPPERCASE' | translate}}</span>
<span class="left-desc">{{'POLICY.DATA.HASUPPERCASE' | translate}}</span>
<span class="fill-space"></span>
<mat-slide-toggle color="primary" name="hasUppercase" ngDefaultControl
[(ngModel)]="complexityData.hasUppercase">

View File

@ -76,7 +76,7 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
public removePolicy(): void {
if (this.service instanceof ManagementService) {
this.service.removePasswordComplexityPolicy().then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.RESETSUCCESS', true);
this.toast.showInfo('POLICY.TOAST.RESETSUCCESS', true);
setTimeout(() => {
this.fetchData();
}, 1000);
@ -110,7 +110,7 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
this.complexityData.hasSymbol,
this.complexityData.minLength,
).then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
this.toast.showInfo('POLICY.TOAST.SET', true);
}).catch(error => {
this.toast.showError(error);
});
@ -122,7 +122,7 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
this.complexityData.hasSymbol,
this.complexityData.minLength,
).then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
this.toast.showInfo('POLICY.TOAST.SET', true);
}).catch(error => {
this.toast.showError(error);
});
@ -136,7 +136,7 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
this.complexityData.hasSymbol,
this.complexityData.minLength,
).then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
this.toast.showInfo('POLICY.TOAST.SET', true);
}).catch(error => {
this.toast.showError(error);
});

View File

@ -1,18 +1,17 @@
<app-detail-layout [backRouterLink]="[ serviceType === PolicyComponentServiceType.ADMIN ? '/iam' : '/org']"
[title]="'ORG.POLICY.PWD_LOCKOUT.TITLE' | translate"
[description]="'ORG.POLICY.PWD_LOCKOUT.DESCRIPTION' | translate">
<p class="default" *ngIf="isDefault"> {{'ORG.POLICY.DEFAULTLABEL' | translate}}</p>
[title]="'POLICY.PWD_LOCKOUT.TITLE' | translate" [description]="'POLICY.PWD_LOCKOUT.DESCRIPTION' | translate">
<p class="default" *ngIf="isDefault"> {{'POLICY.DEFAULTLABEL' | translate}}</p>
<ng-template appHasRole [appHasRole]="['policy.delete']">
<button *ngIf="serviceType === PolicyComponentServiceType.MGMT && !isDefault"
matTooltip="{{'ORG.POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
{{'ORG.POLICY.RESET' | translate}}
matTooltip="{{'POLICY.RESET' | translate}}" color="warn" (click)="removePolicy()" mat-stroked-button>
{{'POLICY.RESET' | translate}}
</button>
</ng-template>
<div class="content" *ngIf="lockoutData">
<div class="row">
<span class="left-desc">{{'ORG.POLICY.DATA.MAXATTEMPTS' | translate}}</span>
<span class="left-desc">{{'POLICY.DATA.MAXATTEMPTS' | translate}}</span>
<span class="fill-space"></span>
<div class="length-wrapper">
<button mat-icon-button (click)="incrementMaxAttempts()">
@ -25,7 +24,7 @@
</div>
</div>
<div class="row">
<span class="left-desc">{{'ORG.POLICY.DATA.SHOWLOCKOUTFAILURES' | translate}}</span>
<span class="left-desc">{{'POLICY.DATA.SHOWLOCKOUTFAILURES' | translate}}</span>
<span class="fill-space"></span>
<mat-slide-toggle color="primary" name="showLockoutFailure" ngDefaultControl
[(ngModel)]="lockoutData.showLockoutFailure">

View File

@ -73,7 +73,7 @@ export class PasswordLockoutPolicyComponent implements OnDestroy {
public removePolicy(): void {
if (this.service instanceof ManagementService) {
this.service.RemovePasswordLockoutPolicy().then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.RESETSUCCESS', true);
this.toast.showInfo('POLICY.TOAST.RESETSUCCESS', true);
this.fetchData();
}).catch(error => {
this.toast.showError(error);
@ -100,7 +100,7 @@ export class PasswordLockoutPolicyComponent implements OnDestroy {
this.lockoutData.maxAttempts,
this.lockoutData.showLockoutFailure,
).then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
this.toast.showInfo('POLICY.TOAST.SET', true);
}).catch(error => {
this.toast.showError(error);
});
@ -110,7 +110,7 @@ export class PasswordLockoutPolicyComponent implements OnDestroy {
this.lockoutData.maxAttempts,
this.lockoutData.showLockoutFailure,
).then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
this.toast.showInfo('POLICY.TOAST.SET', true);
}).catch(error => {
this.toast.showError(error);
});
@ -119,7 +119,7 @@ export class PasswordLockoutPolicyComponent implements OnDestroy {
this.lockoutData.maxAttempts,
this.lockoutData.showLockoutFailure,
).then(() => {
this.toast.showInfo('ORG.POLICY.TOAST.SET', true);
this.toast.showInfo('POLICY.TOAST.SET', true);
}).catch(error => {
this.toast.showError(error);
});

View File

@ -4,6 +4,7 @@ export enum PolicyComponentType {
COMPLEXITY = 'complexity',
IAM = 'iam',
LOGIN = 'login',
LABEL = 'label',
}
export enum PolicyComponentServiceType {
MGMT = 'mgmt',

View File

@ -0,0 +1,109 @@
<h1>{{'POLICY.TITLE' | translate}}</h1>
<p class="top-desc">{{'POLICY.DESCRIPTION' | translate}}</p>
<div class="row-lyt">
<ng-template appHasRole
[appHasRole]="PolicyGridType.IAM ? ['iam.policy.read'] : PolicyGridType.ORG ? ['policy.read'] : []">
<div class="p-item card">
<div class="avatar">
<mat-icon class="icon" svgIcon="mdi_textbox_password"></mat-icon>
</div>
<div class="title">
<span>{{'POLICY.PWD_COMPLEXITY.TITLE' | translate}}</span>
<button mat-icon-button disabled>
<i class="icon las la-check-circle"></i>
</button>
</div>
<p class="desc">
{{'POLICY.PWD_COMPLEXITY.DESCRIPTION' | translate}}</p>
<span class="fill-space"></span>
<div class="btn-wrapper">
<button [routerLink]="[ 'policy', PolicyComponentType.COMPLEXITY ]"
mat-stroked-button>{{'POLICY.BTN_EDIT' | translate}}</button>
</div>
</div>
</ng-template>
<ng-template appHasRole [appHasRole]="['iam.policy.read']">
<div class="p-item card">
<div class="avatar">
<i class="icon las la-gem"></i>
</div>
<div class="title">
<span>{{'POLICY.IAM_POLICY.TITLE' | translate}}</span>
<button mat-icon-button disabled>
<i class="icon las la-check-circle"></i>
</button>
</div>
<p class="desc">
{{'POLICY.IAM_POLICY.DESCRIPTION' | translate}}</p>
<span class="fill-space"></span>
<div class="btn-wrapper">
<ng-template appHasRole [appHasRole]="['iam.policy.write']">
<button [routerLink]="[ 'policy', PolicyComponentType.IAM ]"
mat-stroked-button>{{'POLICY.BTN_EDIT' | translate}}</button>
</ng-template>
</div>
</div>
</ng-template>
<ng-template appHasRole
[appHasRole]="PolicyGridType.IAM ? ['iam.policy.read'] : PolicyGridType.ORG ? ['policy.read'] : []">
<div class="p-item card">
<div class="avatar">
<i class="icon las la-sign-in-alt"></i>
</div>
<div class="title">
<span>{{'POLICY.LOGIN_POLICY.TITLE' | translate}}</span>
<button mat-icon-button disabled>
<i class="icon las la-check-circle"></i>
</button>
</div>
<ng-template #showDescIAM>
<p class="desc">
{{'POLICY.LOGIN_POLICY.DESCRIPTION' | translate}}</p>
</ng-template>
<span class="fill-space"></span>
<div class="btn-wrapper">
<ng-template appHasRole [appHasRole]="['policy.write']">
<button [routerLink]="[ 'policy', PolicyComponentType.LOGIN ]"
mat-stroked-button>{{'POLICY.BTN_EDIT' | translate}}</button>
</ng-template>
</div>
</div>
</ng-template>
<ng-container *ngIf="type === PolicyGridType.IAM">
<ng-template appHasRole [appHasRole]="['iam.policy.read']">
<div class="p-item card">
<div class="avatar">
<i class="icon las la-envelope"></i>
</div>
<div class="title">
<span>{{'POLICY.LABEL.TITLE' | translate}}</span>
<button mat-icon-button disabled>
<i class="icon las la-check-circle"></i>
</button>
</div>
<p class="desc">
{{'POLICY.LABEL.DESCRIPTION' | translate}}</p>
<span class="fill-space"></span>
<div class="btn-wrapper">
<ng-template appHasRole [appHasRole]="['iam.policy.write']">
<button [routerLink]="[ 'policy', PolicyComponentType.LABEL ]"
mat-stroked-button>{{'POLICY.BTN_EDIT' | translate}}</button>
</ng-template>
</div>
</div>
</ng-template>
</ng-container>
</div>

View File

@ -9,11 +9,11 @@ h1 {
.row-lyt {
display: flex;
flex-wrap: wrap;
margin: 0 -1rem;
margin: 0 -.5rem;
.p-item {
flex-basis: 300px;
margin: 1rem;
flex-basis: 290px;
margin: .5rem;
display: flex;
flex-direction: column;
min-height: 200px;
@ -38,6 +38,7 @@ h1 {
font-size: 2.5rem;
height: 2.5rem;
line-height: 2.5rem;
color: white;
}
}
@ -46,7 +47,7 @@ h1 {
align-items: center;
span {
font-size: 1.2rem;
font-size: 1.1rem;
}
.icon {
@ -56,7 +57,7 @@ h1 {
}
.desc {
font-size: .9rem;
font-size: 14px;
color: var(--grey);
}

View File

@ -0,0 +1,19 @@
import { Component, Input } from '@angular/core';
import { PolicyComponentType } from 'src/app/modules/policies/policy-component-types.enum';
export enum PolicyGridType {
ORG,
IAM,
}
@Component({
selector: 'app-policy-grid',
templateUrl: './policy-grid.component.html',
styleUrls: ['./policy-grid.component.scss'],
})
export class PolicyGridComponent {
@Input() public type!: PolicyGridType;
public PolicyComponentType: any = PolicyComponentType;
public PolicyGridType: any = PolicyGridType;
constructor() { }
}

View File

@ -0,0 +1,27 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { RouterModule } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { HasRoleModule } from 'src/app/directives/has-role/has-role.module';
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
import { PolicyGridComponent } from './policy-grid.component';
@NgModule({
declarations: [PolicyGridComponent],
imports: [
CommonModule,
HasRolePipeModule,
HasRoleModule,
TranslateModule,
RouterModule,
MatButtonModule,
MatIconModule,
],
exports: [
PolicyGridComponent,
],
})
export class PolicyGridModule { }

View File

@ -16,7 +16,7 @@
<ng-container matColumnDef="failedSequence">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.FAILEDEVENTS.FAILEDSEQUENCE' | translate }} </th>
<td mat-cell *matCellDef="let event">
<span class="role app-label">{{event?.failedSequence}}</span>
<span>{{event?.failedSequence}}</span>
</td>
</ng-container>

View File

@ -1,78 +0,0 @@
<h1>{{'IAM.POLICY.TITLE' | translate}}</h1>
<p class="top-desc">{{'IAM.POLICY.DESCRIPTION' | translate}}</p>
<div class="row-lyt">
<ng-template appHasRole [appHasRole]="['iam.policy.read']">
<div class="p-item card">
<div class="avatar">
<mat-icon class="icon" svgIcon="mdi_textbox_password"></mat-icon>
</div>
<div class="title">
<span>{{'ORG.POLICY.PWD_COMPLEXITY.TITLE' | translate}}</span>
<button mat-icon-button disabled>
<i *ngIf="complexityPolicy" class="icon las la-check-circle"></i>
</button>
</div>
<p class="desc">
{{'ORG.POLICY.PWD_COMPLEXITY.DESCRIPTION' | translate}}</p>
<span class="fill-space"></span>
<div class="btn-wrapper">
<button [disabled]="!complexityPolicy" [routerLink]="[ 'policy', PolicyComponentType.COMPLEXITY ]"
mat-stroked-button>{{'ORG.POLICY.BTN_EDIT' | translate}}</button>
</div>
</div>
</ng-template>
<ng-template appHasRole [appHasRole]="['iam.policy.read']">
<div class="p-item card">
<div class="avatar">
<i class="icon las la-gem"></i>
</div>
<div class="title">
<span>{{'ORG.POLICY.IAM_POLICY.TITLE' | translate}}</span>
<button mat-icon-button disabled>
<i *ngIf="iamPolicy" class="icon las la-check-circle"></i>
</button>
</div>
<p class="desc">
{{'ORG.POLICY.IAM_POLICY.DESCRIPTION' | translate}}</p>
<span class="fill-space"></span>
<div class="btn-wrapper">
<ng-template appHasRole [appHasRole]="['iam.policy.write']">
<button [disabled]="!iamPolicy" [routerLink]="[ 'policy', PolicyComponentType.IAM ]"
mat-stroked-button>{{'ORG.POLICY.BTN_EDIT' | translate}}</button>
</ng-template>
</div>
</div>
</ng-template>
<ng-template appHasRole [appHasRole]="['policy.read']">
<div class="p-item card">
<div class="avatar">
<i class="icon las la-gem"></i>
</div>
<div class="title">
<span>{{'ORG.POLICY.LOGIN_POLICY.TITLE' | translate}}</span>
<button mat-icon-button disabled>
<i *ngIf="loginPolicy" class="icon las la-check-circle"></i>
</button>
</div>
<p class="desc">
{{'ORG.POLICY.LOGIN_POLICY.DESCRIPTION' | translate}}</p>
<span class="fill-space"></span>
<div class="btn-wrapper">
<ng-template appHasRole [appHasRole]="['iam.policy.write']">
<button [disabled]="!loginPolicy" [routerLink]="[ 'policy', PolicyComponentType.LOGIN ]"
mat-stroked-button>{{'ORG.POLICY.BTN_EDIT' | translate}}</button>
</ng-template>
</div>
</div>
</ng-template>
</div>

View File

@ -1,75 +0,0 @@
h1 {
font-size: 1.2rem;
}
.top-desc {
color: var(--grey);
}
.row-lyt {
display: flex;
flex-wrap: wrap;
margin: 0 -1rem;
.p-item {
flex-basis: 300px;
margin: 1rem;
display: flex;
flex-direction: column;
min-height: 200px;
padding: 1rem;
@media only screen and (max-width: 450px) {
flex-basis: 100%;
}
.avatar {
height: 60px;
width: 60px;
border-radius: 50%;
background: linear-gradient(40deg, rgb(129, 85, 185) 30%, #8983f7);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: .5rem;
.icon,
i {
font-size: 2.5rem;
height: 2.5rem;
line-height: 2.5rem;
}
}
.title {
display: flex;
align-items: center;
span {
font-size: 1.2rem;
}
.icon {
margin-left: 1rem;
margin-right: 1rem;
}
}
.desc {
font-size: .9rem;
color: var(--grey);
}
.fill-space {
flex: 1;
}
.btn-wrapper {
display: flex;
}
button {
margin-right: 1rem;
}
}
}

View File

@ -1,43 +0,0 @@
import { Component } from '@angular/core';
import { PolicyComponentType } from 'src/app/modules/policies/policy-component-types.enum';
import { DefaultLoginPolicy, DefaultPasswordComplexityPolicyView, OrgIamPolicyView } from 'src/app/proto/generated/admin_pb';
import { PolicyState } from 'src/app/proto/generated/management_pb';
import { AdminService } from 'src/app/services/admin.service';
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
@Component({
selector: 'app-iam-policy-grid',
templateUrl: './iam-policy-grid.component.html',
styleUrls: ['./iam-policy-grid.component.scss'],
})
export class IamPolicyGridComponent {
public complexityPolicy!: DefaultPasswordComplexityPolicyView.AsObject;
public loginPolicy!: DefaultLoginPolicy.AsObject;
public iamPolicy!: OrgIamPolicyView.AsObject;
public PolicyState: any = PolicyState;
public PolicyComponentType: any = PolicyComponentType;
constructor(
private authService: GrpcAuthService,
private adminService: AdminService,
) {
this.getData();
}
private getData(): void {
this.authService.isAllowed(['policy.read']).subscribe(allowed => {
if (allowed) {
this.adminService.GetDefaultLoginPolicy().then(data => this.loginPolicy = data.toObject());
this.adminService.GetDefaultPasswordComplexityPolicy().then(data => this.complexityPolicy = data.toObject());
}
});
this.authService.isAllowed(['iam.policy.read']).subscribe(allowed => {
if (allowed) {
this.adminService.GetDefaultOrgIamPolicy().then(data => this.iamPolicy = data.toObject());
}
});
}
}

View File

@ -89,6 +89,14 @@ const routes: Routes = [
loadChildren: () => import('src/app/modules/policies/login-policy/login-policy.module')
.then(m => m.LoginPolicyModule),
},
{
path: PolicyComponentType.LABEL,
data: {
serviceType: PolicyComponentServiceType.ADMIN,
},
loadChildren: () => import('src/app/modules/policies/label-policy/label-policy.module')
.then(m => m.LabelPolicyModule),
},
],
},
];

View File

@ -3,7 +3,7 @@
<h1 class="h1">{{'IAM.DETAIL.TITLE' | translate}}</h1>
<p class="sub">{{'IAM.DETAIL.DESCRIPTION' | translate}} </p>
<app-iam-policy-grid></app-iam-policy-grid>
<app-policy-grid [type]="PolicyGridType.IAM"></app-policy-grid>
<app-card title="{{ 'IAM.VIEWS.TITLE' | translate }}" description="{{ 'IAM.VIEWS.DESCRIPTION' | translate }}">
<app-iam-views></app-iam-views>

View File

@ -5,6 +5,7 @@ import { BehaviorSubject, from, Observable, of } from 'rxjs';
import { catchError, finalize, map } from 'rxjs/operators';
import { CreationType, MemberCreateDialogComponent } from 'src/app/modules/add-member-dialog/member-create-dialog.component';
import { PolicyComponentServiceType } from 'src/app/modules/policies/policy-component-types.enum';
import { PolicyGridType } from 'src/app/modules/policy-grid/policy-grid.component';
import { OrgMemberView, UserView } from 'src/app/proto/generated/management_pb';
import { AdminService } from 'src/app/services/admin.service';
import { ToastService } from 'src/app/services/toast.service';
@ -22,6 +23,8 @@ export class IamComponent {
public membersSubject: BehaviorSubject<OrgMemberView.AsObject[]>
= new BehaviorSubject<OrgMemberView.AsObject[]>([]);
public PolicyGridType: any = PolicyGridType;
constructor(public adminService: AdminService, private dialog: MatDialog, private toast: ToastService,
private router: Router) {
this.loadMembers();

View File

@ -20,6 +20,7 @@ import { CardModule } from 'src/app/modules/card/card.module';
import { ChangesModule } from 'src/app/modules/changes/changes.module';
import { ContributorsModule } from 'src/app/modules/contributors/contributors.module';
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
import { PolicyGridModule } from 'src/app/modules/policy-grid/policy-grid.module';
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
import { SharedModule } from 'src/app/modules/shared/shared.module';
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
@ -27,13 +28,12 @@ import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe/local
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe/timestamp-to-date-pipe.module';
import { FailedEventsComponent } from './failed-events/failed-events.component';
import { IamPolicyGridComponent } from './iam-policy-grid/iam-policy-grid.component';
import { IamRoutingModule } from './iam-routing.module';
import { IamViewsComponent } from './iam-views/iam-views.component';
import { IamComponent } from './iam.component';
@NgModule({
declarations: [IamComponent, IamViewsComponent, FailedEventsComponent, IamPolicyGridComponent],
declarations: [IamComponent, IamViewsComponent, FailedEventsComponent],
imports: [
CommonModule,
IamRoutingModule,
@ -64,6 +64,7 @@ import { IamComponent } from './iam.component';
RefreshTableModule,
HasRolePipeModule,
MatSortModule,
PolicyGridModule,
],
})
export class IamModule { }

View File

@ -29,7 +29,7 @@
</ng-container>
<ng-template appHasRole [appHasRole]="['policy.read']">
<app-policy-grid></app-policy-grid>
<app-policy-grid [type]="PolicyGridType.ORG"></app-policy-grid>
</ng-template>
</div>

View File

@ -10,6 +10,7 @@ import { catchError, finalize, map } 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 { PolicyComponentServiceType } from 'src/app/modules/policies/policy-component-types.enum';
import { PolicyGridType } from 'src/app/modules/policy-grid/policy-grid.component';
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
import {
Org,
@ -54,6 +55,7 @@ export class OrgDetailComponent implements OnInit, OnDestroy {
public totalMemberResult: number = 0;
public membersSubject: BehaviorSubject<OrgMemberView.AsObject[]>
= new BehaviorSubject<OrgMemberView.AsObject[]>([]);
public PolicyGridType: any = PolicyGridType;
constructor(
private dialog: MatDialog,

View File

@ -17,6 +17,7 @@ import { MemberCreateDialogModule } from 'src/app/modules/add-member-dialog/memb
import { CardModule } from 'src/app/modules/card/card.module';
import { ContributorsModule } from 'src/app/modules/contributors/contributors.module';
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
import { PolicyGridModule } from 'src/app/modules/policy-grid/policy-grid.module';
import { SharedModule } from 'src/app/modules/shared/shared.module';
import { WarnDialogModule } from 'src/app/modules/warn-dialog/warn-dialog.module';
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
@ -26,10 +27,9 @@ import { AddDomainDialogModule } from './org-detail/add-domain-dialog/add-domain
import { DomainVerificationComponent } from './org-detail/domain-verification/domain-verification.component';
import { OrgDetailComponent } from './org-detail/org-detail.component';
import { OrgsRoutingModule } from './orgs-routing.module';
import { PolicyGridComponent } from './policy-grid/policy-grid.component';
@NgModule({
declarations: [OrgDetailComponent, PolicyGridComponent, DomainVerificationComponent],
declarations: [OrgDetailComponent, DomainVerificationComponent],
imports: [
CommonModule,
HasRolePipeModule,
@ -56,6 +56,7 @@ import { PolicyGridComponent } from './policy-grid/policy-grid.component';
SharedModule,
ContributorsModule,
CopyToClipboardModule,
PolicyGridModule,
],
})
export class OrgsModule { }

View File

@ -1,80 +0,0 @@
<h1>{{'ORG.POLICY.TITLE' | translate}}</h1>
<p class="top-desc">{{'ORG.POLICY.DESCRIPTION' | translate}}</p>
<div class="row-lyt">
<ng-template appHasRole [appHasRole]="['iam.policy.read']">
<div class="p-item card">
<div class="avatar">
<mat-icon class="icon" svgIcon="mdi_textbox_password"></mat-icon>
</div>
<div class="title">
<span>{{'ORG.POLICY.PWD_COMPLEXITY.TITLE' | translate}}</span>
<button mat-icon-button disabled>
<i *ngIf="complexityPolicy" class="icon las la-check-circle"></i>
</button>
</div>
<p class="desc">
{{'ORG.POLICY.PWD_COMPLEXITY.DESCRIPTION' | translate}}</p>
<span class="fill-space"></span>
<div class="btn-wrapper">
<button [disabled]="!complexityPolicy" [routerLink]="[ 'policy', PolicyComponentType.COMPLEXITY ]"
mat-stroked-button>{{'ORG.POLICY.BTN_EDIT' | translate}}</button>
</div>
</div>
</ng-template>
<ng-template appHasRole [appHasRole]="['iam.policy.read']">
<div class="p-item card">
<div class="avatar">
<i class="icon las la-gem"></i>
</div>
<div class="title">
<span>{{'ORG.POLICY.IAM_POLICY.TITLE' | translate}}</span>
<button mat-icon-button disabled>
<i *ngIf="iamPolicy" class="icon las la-check-circle"></i>
</button>
</div>
<p class="desc">
{{'ORG.POLICY.IAM_POLICY.DESCRIPTION' | translate}}</p>
<span class="fill-space"></span>
<div class="btn-wrapper">
<ng-template appHasRole [appHasRole]="['iam.policy.write']">
<button [disabled]="!iamPolicy" [routerLink]="[ 'policy', PolicyComponentType.IAM ]"
mat-stroked-button>{{'ORG.POLICY.BTN_EDIT' | translate}}</button>
</ng-template>
</div>
</div>
</ng-template>
<ng-template appHasRole [appHasRole]="['policy.read']">
<div class="p-item card">
<div class="avatar">
<i class="icon las la-gem"></i>
</div>
<div class="title">
<span>{{'ORG.POLICY.LOGIN_POLICY.TITLE' | translate}}</span>
<button mat-icon-button disabled>
<i *ngIf="loginPolicy" class="icon las la-check-circle"></i>
</button>
</div>
<ng-template #showDescIAM>
<p class="desc">
{{'ORG.POLICY.LOGIN_POLICY.DESCRIPTION' | translate}}</p>
</ng-template>
<span class="fill-space"></span>
<div class="btn-wrapper">
<ng-template appHasRole [appHasRole]="['policy.write']">
<button [disabled]="!loginPolicy" [routerLink]="[ 'policy', PolicyComponentType.LOGIN ]"
mat-stroked-button>{{'ORG.POLICY.BTN_EDIT' | translate}}</button>
</ng-template>
</div>
</div>
</ng-template>
</div>

View File

@ -1,41 +0,0 @@
import { Component } from '@angular/core';
import { PolicyComponentType } from 'src/app/modules/policies/policy-component-types.enum';
import {
LoginPolicyView,
OrgIamPolicyView,
PasswordComplexityPolicyView,
PolicyState,
} from 'src/app/proto/generated/management_pb';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
@Component({
selector: 'app-policy-grid',
templateUrl: './policy-grid.component.html',
styleUrls: ['./policy-grid.component.scss'],
})
export class PolicyGridComponent {
public complexityPolicy!: PasswordComplexityPolicyView.AsObject;
public iamPolicy!: OrgIamPolicyView.AsObject;
public loginPolicy!: LoginPolicyView.AsObject;
public PolicyState: any = PolicyState;
public PolicyComponentType: any = PolicyComponentType;
constructor(
public mgmtService: ManagementService,
private toast: ToastService,
) {
this.getData();
}
private getData(): void {
this.mgmtService.GetPasswordComplexityPolicy().then(data => this.complexityPolicy = data.toObject()).catch(error => {
this.toast.showError(error);
});
this.mgmtService.GetMyOrgIamPolicy().then(data => this.iamPolicy = data.toObject());
this.mgmtService.GetLoginPolicy().then(data => {
this.loginPolicy = data.toObject();
});
}
}

View File

@ -7,6 +7,9 @@ import {
CreateHumanRequest,
CreateOrgRequest,
CreateUserRequest,
DefaultLabelPolicy,
DefaultLabelPolicyUpdate,
DefaultLabelPolicyView,
DefaultLoginPolicy,
DefaultLoginPolicyView,
DefaultPasswordAgePolicyRequest,
@ -162,6 +165,17 @@ export class AdminService {
return this.grpcService.admin.updateDefaultPasswordLockoutPolicy(req);
}
/* label */
public GetDefaultLabelPolicy(): Promise<DefaultLabelPolicyView> {
const req = new Empty();
return this.grpcService.admin.getDefaultLabelPolicy(req);
}
public UpdateDefaultLabelPolicy(req: DefaultLabelPolicyUpdate): Promise<DefaultLabelPolicy> {
return this.grpcService.admin.updateDefaultLabelPolicy(req);
}
/* login */
public GetDefaultLoginPolicy(

View File

@ -612,13 +612,13 @@ export class ManagementService {
public getLocalizedComplexityPolicyPatternErrorString(policy: PasswordComplexityPolicy.AsObject): string {
if (policy.hasNumber && policy.hasSymbol) {
return 'ORG.POLICY.PWD_COMPLEXITY.SYMBOLANDNUMBERERROR';
return 'POLICY.PWD_COMPLEXITY.SYMBOLANDNUMBERERROR';
} else if (policy.hasNumber) {
return 'ORG.POLICY.PWD_COMPLEXITY.NUMBERERROR';
return 'POLICY.PWD_COMPLEXITY.NUMBERERROR';
} else if (policy.hasSymbol) {
return 'ORG.POLICY.PWD_COMPLEXITY.SYMBOLERROR';
return 'POLICY.PWD_COMPLEXITY.SYMBOLERROR';
} else {
return 'ORG.POLICY.PWD_COMPLEXITY.PATTERNERROR';
return 'POLICY.PWD_COMPLEXITY.PATTERNERROR';
}
}

View File

@ -350,10 +350,6 @@
"DELETE":"Entfernen",
"DELETESUCCESS":"Gescheiterte Events entfernt."
},
"POLICY": {
"TITLE":"Standardrichtlinien für ihre Organisationen",
"DESCRIPTION":"Diese Einstellungen können von Organisationen erweitert und/oder verändert werden."
},
"TOAST":{
"MEMBERREMOVED":"Manager entfernt.",
"MEMBERSADDED": "Manager hinzugefügt.",
@ -421,74 +417,6 @@
"TITLE":"Manager der Organisation verwalten",
"DESCRIPTION":"Definiere hier die Benutzer, die Operationen auf Deinen Organisationen vornehmen dürfen."
},
"POLICY": {
"TITLE":"Richtlinen entdecken",
"DESCRIPTION":"Vorgefertigte Richtlinien, die Dir Zeit sparen und die Sicherheit erhöhen.",
"PWD_COMPLEXITY": {
"TITLE":"Passwortkomplexität",
"DESCRIPTION":"Stellt sicher, dass alle festgelegten Passwörter einem bestimmten Muster entsprechen.",
"TITLECREATE":"Passwortkomplexitätsrichtlinie erstellen",
"DESCRIPTIONCREATE":"Stellt sicher, dass alle festgelegten Passwörter einem bestimmten Muster entsprechen.",
"SYMBOLANDNUMBERERROR":"Das Password muss ein Symbol/Satzzeichen und eine Ziffer beinhalten.",
"SYMBOLERROR":"Das Password muss ein Symbol/Satzzeichen beinhalten.",
"NUMBERERROR":"Das Password muss eine Ziffer beinhalten.",
"PATTERNERROR":"Das Passwort erfüllt nicht die vorgeschriebene Richtlinie."
},
"PWD_AGE": {
"TITLE":"Gültigkeitsdauer für Passwörter",
"DESCRIPTION":"Du kannst eine Richtlinie für die maximale Gültigkeitsdauer von Passwörtern festlegen. Diese Richtlinie löst eine Warnung nach Ablauf einer festgelegten Gültigkeitsdauer aus.",
"TITLECREATE":"Richtlinie für Gültigkeitsdauer von Passwörtern festlegen",
"DESCRIPTIONCREATE":"Du kannst eine Richtlinie für die Gültigkeitsdauer von Passwörtern festlegen. Diese Richtlinie löst eine Warnung nach Ablauf einer festgelegten Gültigkeitsdauer aus."
},
"PWD_LOCKOUT": {
"TITLE":"Passwortsperre",
"DESCRIPTION":"Standardmässig sind die Passwortwiederholungen bei Falscheingabe nicht begrenzt. Du musst diese Richtlinie installieren, wenn Du Wiederholungsversuche anzeigen, oder eine maximale Anzahl von wiederholten Passworteingaben festlegen möchtest.",
"TITLECREATE":"Richtline zur Passwortsperre festlegen",
"DESCRIPTIONCREATE":"Standardmässig sind die Passwortwiederholungen bei Falscheingabe nicht begrenzt. Du musst diese Richtlinie anwenden, wenn Du Wiederholungsversuche anzeigen, oder eine maximale Anzahl von wiederholten Passworteingaben festlegen möchtest."
},
"IAM_POLICY": {
"TITLE":"Zugangseinstellungen IAM",
"DESCRIPTION":"Definiere die Zugangseistellungen für Benutzer.",
"TITLECREATE":"Zugangseinstellungen für IAM festlegen",
"DESCRIPTIONCREATE":"E-Mails als Benutzernamen sind nicht erlaubt, wenn die Eigenschaft \"UserLoginMustBeDomain\" gesetzt ist."
},
"LOGIN_POLICY": {
"TITLE":"Login Richtlinien",
"DESCRIPTION":"Definiere die Loginmethoden für Benutzer",
"TITLECREATE":"Definiere die Loginmethoden für Benutzer",
"DESCRIPTIONCREATEADMIN":"Nutzer können sich mit den verfügbaren Idps authentifizieren.",
"DESCRIPTIONCREATEMGMT":"Nutzer können sich mit den verfügbaren Idps authentifizieren. Achtung: Es kann zwischen System- und organisationsspezifischen Providern gewählt werden.",
"SAVED":"Erfolgreich gespeichert."
},
"DEFAULTLABEL":"Die aktuelle Richtlinie entspricht der IAM-Standard Einstellung.",
"BTN_INSTALL":"Installieren",
"BTN_EDIT":"Modifizieren",
"DATA": {
"DESCRIPTION":"Beschreibung",
"MINLENGTH":"Mindestlänge",
"HASNUMBER": "erfordert Ziffer",
"HASSYMBOL": "erfordert Symbol/Satzzeichen",
"HASLOWERCASE": "erfordert Kleinbuchstaben",
"HASUPPERCASE": "erfordert Grossbuchstaben",
"SHOWLOCKOUTFAILURES":"Zeige Anzahl Anmeldeversuche",
"MAXATTEMPTS":"Maximale Anzahl an Versuchen",
"EXPIREWARNDAYS":"Ablauf Warnung nach Tagen",
"MAXAGEDAYS":"Maximale Gültigkeit in Tagen",
"USERLOGINMUSTBEDOMAIN":"Benutzer-Login muss eine Domain sein",
"ALLOWUSERNAMEPASSWORD":"Benutzername Password erlaubt",
"ALLOWEXTERNALIDP":"Externer IDP erlaubt",
"ALLOWREGISTER":"Registrieren erlaubt",
"ALLOWUSERNAMEPASSWORD_DESC":"Der konventionelle Login mit Benutzername und Passwort wird erlaubt.",
"ALLOWEXTERNALIDP_DESC":"Der Login wird für die darunter liegenden Identity Provider erlaubt.",
"ALLOWREGISTER_DESC":"Ist die Option gewählt, erscheint im Login ein zusätzlicher Schritt zum Registrieren eines Benutzers."
},
"RESET":"Richtlinie zurücksetzen",
"CREATECUSTOM":"Benutzerdefinierte Richtlinie erstellen",
"TOAST":{
"SET":"Richtline erfolgreich gesetzt!",
"RESETSUCCESS":"Richtline zurückgesetzt!"
}
},
"TOAST": {
"DEACTIVATED":"Organisation deaktiviert.",
"REACTIVATED":"Organisation reaktiviert.",
@ -500,6 +428,72 @@
"SETPRIMARY":"Primäre Domain gesetzt."
}
},
"POLICY": {
"TITLE":"Richtlinen entdecken",
"DESCRIPTION":"Vorgefertigte Richtlinien, die Dir Zeit sparen und die Sicherheit erhöhen.",
"PWD_COMPLEXITY": {
"TITLE":"Passwortkomplexität",
"DESCRIPTION":"Stellt sicher, dass alle festgelegten Passwörter einem bestimmten Muster entsprechen.",
"SYMBOLANDNUMBERERROR":"Das Password muss ein Symbol/Satzzeichen und eine Ziffer beinhalten.",
"SYMBOLERROR":"Das Password muss ein Symbol/Satzzeichen beinhalten.",
"NUMBERERROR":"Das Password muss eine Ziffer beinhalten.",
"PATTERNERROR":"Das Passwort erfüllt nicht die vorgeschriebene Richtlinie."
},
"PWD_AGE": {
"TITLE":"Gültigkeitsdauer für Passwörter",
"DESCRIPTION":"Du kannst eine Richtlinie für die maximale Gültigkeitsdauer von Passwörtern festlegen. Diese Richtlinie löst eine Warnung nach Ablauf einer festgelegten Gültigkeitsdauer aus."
},
"PWD_LOCKOUT": {
"TITLE":"Passwortsperre",
"DESCRIPTION":"Standardmässig sind die Passwortwiederholungen bei Falscheingabe nicht begrenzt. Du musst diese Richtlinie installieren, wenn Du Wiederholungsversuche anzeigen, oder eine maximale Anzahl von wiederholten Passworteingaben festlegen möchtest."
},
"IAM_POLICY": {
"TITLE":"Zugangseinstellungen IAM",
"DESCRIPTION":"Definiere die Zugangseistellungen für Benutzer."
},
"LOGIN_POLICY": {
"TITLE":"Login Richtlinien",
"DESCRIPTION":"Definiere die Loginmethoden für Benutzer",
"DESCRIPTIONCREATEADMIN":"Nutzer können sich mit den verfügbaren Idps authentifizieren.",
"DESCRIPTIONCREATEMGMT":"Nutzer können sich mit den verfügbaren Idps authentifizieren. Achtung: Es kann zwischen System- und organisationsspezifischen Providern gewählt werden.",
"SAVED":"Erfolgreich gespeichert."
},
"LABEL": {
"TITLE":"Email Labelling Einstellungen",
"DESCRIPTION":"Definieren Sie das Erscheinungsbild Ihrer Benachrichtigungs-Mails",
"PRIMARYCOLOR":"Hintergrundfarbe",
"SECONDARYCOLOR":"Schriftfarbe",
"SAVED":"Erfolgreich gespeichert."
},
"DEFAULTLABEL":"Die aktuelle Richtlinie entspricht der IAM-Standard Einstellung.",
"BTN_INSTALL":"Installieren",
"BTN_EDIT":"Modifizieren",
"DATA": {
"DESCRIPTION":"Beschreibung",
"MINLENGTH":"Mindestlänge",
"HASNUMBER": "erfordert Ziffer",
"HASSYMBOL": "erfordert Symbol/Satzzeichen",
"HASLOWERCASE": "erfordert Kleinbuchstaben",
"HASUPPERCASE": "erfordert Grossbuchstaben",
"SHOWLOCKOUTFAILURES":"Zeige Anzahl Anmeldeversuche",
"MAXATTEMPTS":"Maximale Anzahl an Versuchen",
"EXPIREWARNDAYS":"Ablauf Warnung nach Tagen",
"MAXAGEDAYS":"Maximale Gültigkeit in Tagen",
"USERLOGINMUSTBEDOMAIN":"Benutzer-Login muss eine Domain sein",
"ALLOWUSERNAMEPASSWORD":"Benutzername Password erlaubt",
"ALLOWEXTERNALIDP":"Externer IDP erlaubt",
"ALLOWREGISTER":"Registrieren erlaubt",
"ALLOWUSERNAMEPASSWORD_DESC":"Der konventionelle Login mit Benutzername und Passwort wird erlaubt.",
"ALLOWEXTERNALIDP_DESC":"Der Login wird für die darunter liegenden Identity Provider erlaubt.",
"ALLOWREGISTER_DESC":"Ist die Option gewählt, erscheint im Login ein zusätzlicher Schritt zum Registrieren eines Benutzers."
},
"RESET":"Richtlinie zurücksetzen",
"CREATECUSTOM":"Benutzerdefinierte Richtlinie erstellen",
"TOAST":{
"SET":"Richtline erfolgreich gesetzt!",
"RESETSUCCESS":"Richtline zurückgesetzt!"
}
},
"ORG_DETAIL": {
"TITLE": "Organisation",
"DESCRIPTION": "Hier kannst Du Deine Konfiguration der Organisation bearbeiten und Mitglieder verwalten.",

View File

@ -350,10 +350,6 @@
"DELETE":"Remove",
"DELETESUCCESS":"Failed events removed."
},
"POLICY": {
"TITLE":"Default policies for organisations",
"DESCRIPTION":"These settings can be enhanced and/or customized by registered organisations."
},
"TOAST":{
"MEMBERREMOVED":"Manager removed.",
"MEMBERSADDED": "Managers added.",
@ -421,74 +417,6 @@
"TITLE":"Organisation Managers",
"DESCRIPTION":"Define the users who can change your organisations preferences."
},
"POLICY": {
"TITLE":"Explore Policies",
"DESCRIPTION":"Pre-packaged policies that enhance your security.",
"PWD_COMPLEXITY": {
"TITLE":"Password Complexity",
"DESCRIPTION":"Ensures that all set passwords correspond to a specific pattern",
"TITLECREATE":"Create Password Complexity Policy",
"DESCRIPTIONCREATE":"Ensures that all set passwords correspond to a specific pattern",
"SYMBOLANDNUMBERERROR":"The password must consist of a digit and a symbol/punctuation mark.",
"SYMBOLERROR":"The password must include a symbol/punctuation mark.",
"NUMBERERROR":"The password must include a digit.",
"PATTERNERROR":"The password does not meet the required pattern."
},
"PWD_AGE": {
"TITLE":"Password Aging",
"DESCRIPTION":"You can set a policy for the aging of passwords. This policy emits a warning after the specific aging time has elapsed.",
"TITLECREATE":"Create Password Aging Policy",
"DESCRIPTIONCREATE":"You can set a policy for the aging of passwords. This policy emits a warning after the specific aging time has elapsed."
},
"PWD_LOCKOUT": {
"TITLE":"Password Lockout",
"DESCRIPTION":"Password retries are infinite in default mode. You have to apply this policy if you want to show the number of retries, or set a maximum number of retries after which the account will be blocked.",
"TITLECREATE":"Create Password Lockout Policy",
"DESCRIPTIONCREATE":"Password retries are infinite in default mode. You have to apply this policy if you want to show the number of retries, or set a maximum number of retries after which the account will be blocked."
},
"IAM_POLICY": {
"TITLE":"IAM Access Preferences",
"DESCRIPTION":"Define access properties of your users.",
"TITLECREATE":"Set IAM Access Preferences",
"DESCRIPTIONCREATE":"If the property \"UserLoginMustBeDomain\" is enabled an e-mail address cannot be used as a user name."
},
"LOGIN_POLICY": {
"TITLE":"Login Policy",
"DESCRIPTION":"Define how Users can be authenticated",
"TITLECREATE":"Define how Users can be authenticated",
"DESCRIPTIONCREATEADMIN":"Users can choose from the available identity providers below.",
"DESCRIPTIONCREATEMGMT":"Users can choose from the available identity providers below. Note: You can use System-set providers as well as providers set for your organisation only.",
"SAVED":"Saved successfully!"
},
"DEFAULTLABEL":"The currently set guideline corresponds to the standard setting set by the IAM Administrator.",
"BTN_INSTALL":"Setup",
"BTN_EDIT":"Modify",
"DATA": {
"DESCRIPTION":"Description",
"MINLENGTH":"minimum length",
"HASNUMBER": "has number",
"HASSYMBOL": "has symbol",
"HASLOWERCASE": "has lowercase",
"HASUPPERCASE": "has uppercase",
"SHOWLOCKOUTFAILURES":"show lockout failures",
"MAXATTEMPTS":"Max Attempts",
"EXPIREWARNDAYS":"Expiration Warning after day",
"MAXAGEDAYS":"Max Age in days",
"USERLOGINMUSTBEDOMAIN":"User Login must be Domain",
"ALLOWUSERNAMEPASSWORD":"Username Password allowed",
"ALLOWEXTERNALIDP":"External IDP allowed",
"ALLOWREGISTER":"Register allowed",
"ALLOWUSERNAMEPASSWORD_DESC":"The conventional login with user name and password is allowed.",
"ALLOWEXTERNALIDP_DESC":"The login is allowed for the underlying identity providers",
"ALLOWREGISTER_DESC":"If the option is selected, an additional step for registering a user appears in the login."
},
"RESET":"Reset Policy",
"CREATECUSTOM":"Create Custom Policy",
"TOAST":{
"SET":"Policy set successfully!",
"RESETSUCCESS":"Policy reset successfully!"
}
},
"TOAST": {
"DEACTIVATED":"Organisation deactivated.",
"REACTIVATED":"Organisation reactivated.",
@ -500,6 +428,72 @@
"SETPRIMARY":"Primary domain set."
}
},
"POLICY": {
"TITLE":"Explore Policies",
"DESCRIPTION":"Pre-packaged policies that enhance your security.",
"PWD_COMPLEXITY": {
"TITLE":"Password Complexity",
"DESCRIPTION":"Ensures that all set passwords correspond to a specific pattern",
"SYMBOLANDNUMBERERROR":"The password must consist of a digit and a symbol/punctuation mark.",
"SYMBOLERROR":"The password must include a symbol/punctuation mark.",
"NUMBERERROR":"The password must include a digit.",
"PATTERNERROR":"The password does not meet the required pattern."
},
"PWD_AGE": {
"TITLE":"Password Aging",
"DESCRIPTION":"You can set a policy for the aging of passwords. This policy emits a warning after the specific aging time has elapsed."
},
"PWD_LOCKOUT": {
"TITLE":"Password Lockout",
"DESCRIPTION":"Password retries are infinite in default mode. You have to apply this policy if you want to show the number of retries, or set a maximum number of retries after which the account will be blocked."
},
"IAM_POLICY": {
"TITLE":"IAM Access Preferences",
"DESCRIPTION":"Define access properties of your users."
},
"LOGIN_POLICY": {
"TITLE":"Login Policy",
"DESCRIPTION":"Define how Users can be authenticated",
"DESCRIPTIONCREATEADMIN":"Users can choose from the available identity providers below.",
"DESCRIPTIONCREATEMGMT":"Users can choose from the available identity providers below. Note: You can use System-set providers as well as providers set for your organisation only.",
"SAVED":"Saved successfully!"
},
"LABEL": {
"TITLE":"Email Labelling Settings",
"DESCRIPTION":"Change the look of your emails.",
"PRIMARYCOLOR":"Background color",
"SECONDARYCOLOR":"Font color",
"SAVED":"Saved successfully"
},
"DEFAULTLABEL":"The currently set guideline corresponds to the standard setting set by the IAM Administrator.",
"BTN_INSTALL":"Setup",
"BTN_EDIT":"Modify",
"DATA": {
"DESCRIPTION":"Description",
"MINLENGTH":"minimum length",
"HASNUMBER": "has number",
"HASSYMBOL": "has symbol",
"HASLOWERCASE": "has lowercase",
"HASUPPERCASE": "has uppercase",
"SHOWLOCKOUTFAILURES":"show lockout failures",
"MAXATTEMPTS":"Max Attempts",
"EXPIREWARNDAYS":"Expiration Warning after day",
"MAXAGEDAYS":"Max Age in days",
"USERLOGINMUSTBEDOMAIN":"User Login must be Domain",
"ALLOWUSERNAMEPASSWORD":"Username Password allowed",
"ALLOWEXTERNALIDP":"External IDP allowed",
"ALLOWREGISTER":"Register allowed",
"ALLOWUSERNAMEPASSWORD_DESC":"The conventional login with user name and password is allowed.",
"ALLOWEXTERNALIDP_DESC":"The login is allowed for the underlying identity providers",
"ALLOWREGISTER_DESC":"If the option is selected, an additional step for registering a user appears in the login."
},
"RESET":"Reset Policy",
"CREATECUSTOM":"Create Custom Policy",
"TOAST":{
"SET":"Policy set successfully!",
"RESETSUCCESS":"Policy reset successfully!"
}
},
"ORG_DETAIL": {
"TITLE": "Organisation",
"DESCRIPTION": "Here you can edit the configuration of your organisation and manage the members.",