fix: Merge master (#1373)

* feat(console): app infos, api apps, fix redirects on create, fix role update, redesign idps, policy, prettier history  (#1310)

* idp fixes

* idp cleanup and rehaul, complexity policy preview

* policy fixes, orthodox redirect

* link component, add links to policies

* redirect pipe, state labels

* Cnsl map changes (#1315)

* map changes to different format

* fix changes layout, cursor

* set asc values

* fix user appearance in changes, index

* changes

* app create with api

* api app create

* auth method for api config

* authmethods, app card for api, authmethod in dev create

* move machine keys to own module

* jwt method for oidc

* fix app edit

* save toast

* fix changes, change det in app detail

* regenerate secret

* chore(deps-dev): bump @angular-devkit/build-angular in /console (#1324)

Bumps [@angular-devkit/build-angular](https://github.com/angular/angular-cli) from 0.1102.0 to 0.1102.1.
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Commits](https://github.com/angular/angular-cli/commits)

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix policy backlink

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
(cherry picked from commit 40a7e958d712f83585e25f18f4fff620de5e3269)

* fix: i18n refs, unnecessary logs (#1343)

(cherry picked from commit 2e04c977eba295cab6aa533379f6075d2e27ab42)

* fix: tos link (#1345)

(cherry picked from commit 5333ef10c169e3656e3ca8dfb8edf7f738fa0a26)

* fix: reactivate/deactivate idp, remove idp provider (#1348)

* fix: reactivate/deactivate idp, remove idp provider

* fix build

* fix(console): add jwt to selection, idp deactivate reactivate (#1347)

* fix: log error on idp change

* add jwt to method selection

Co-authored-by: Max Peintner <[email protected]>

(cherry picked from commit c8b9888427f4ea6b513d370f9fed555208594edf)

* fix: reactivate/deactivate idp (#1351)

(cherry picked from commit 54f395e2e05d4adb29321e9597d049800c033b61)

Co-authored-by: Max Peintner <[email protected]>
This commit is contained in:
Fabi
2021-03-01 09:01:34 +01:00
committed by GitHub
co-authored by Max Peintner
parent 3c07a186fc
commit 9f417f3957
113 changed files with 2976 additions and 1327 deletions
@@ -1,4 +1,4 @@
<app-detail-layout [backRouterLink]="['/iam']" [title]="'POLICY.LABEL.TITLE' | translate"
<app-detail-layout [backRouterLink]="['/iam/policies']" [title]="'POLICY.LABEL.TITLE' | translate"
[description]="'POLICY.LABEL.DESCRIPTION' | translate">
<div class="content" *ngIf="labelData">
@@ -14,7 +14,9 @@
</div>
<div class="btn-container">
<button (click)="savePolicy()" color="primary" type="submit"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
<button (click)="savePolicy()" color="primary" type="submit" mat-raised-button>{{ 'ACTIONS.SAVE' | translate
}}</button>
</div>
<cnsl-links *ngIf="nextLinks" [links]="nextLinks"></cnsl-links>
</app-detail-layout>
@@ -4,6 +4,8 @@ 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 { CnslLinks } from '../../links/links.component';
import { IAM_COMPLEXITY_LINK, IAM_LABEL_LINK, IAM_LOGIN_POLICY_LINK, IAM_POLICY_LINK } from '../../policy-grid/policy-links';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
@@ -19,6 +21,11 @@ export class LabelPolicyComponent implements OnDestroy {
private sub: Subscription = new Subscription();
public PolicyComponentServiceType: any = PolicyComponentServiceType;
public nextLinks: CnslLinks[] = [
IAM_COMPLEXITY_LINK,
IAM_POLICY_LINK,
IAM_LOGIN_POLICY_LINK,
];
constructor(
private route: ActivatedRoute,
private toast: ToastService,
@@ -9,6 +9,7 @@ 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 { InputModule } from 'src/app/modules/input/input.module';
import { LinksModule } from '../../links/links.module';
import { LabelPolicyRoutingModule } from './label-policy-routing.module';
import { LabelPolicyComponent } from './label-policy.component';
@@ -27,6 +28,7 @@ import { LabelPolicyComponent } from './label-policy.component';
MatTooltipModule,
TranslateModule,
DetailLayoutModule,
LinksModule,
],
})
export class LabelPolicyModule { }
@@ -28,28 +28,36 @@
[(ngModel)]="loginData.allowUsernamePassword">
{{'POLICY.DATA.ALLOWUSERNAMEPASSWORD' | translate}}
</mat-slide-toggle>
<p>{{'POLICY.DATA.ALLOWUSERNAMEPASSWORD_DESC' | translate}}</p>
<cnsl-info-section class="info">
{{'POLICY.DATA.ALLOWUSERNAMEPASSWORD_DESC' | translate}}
</cnsl-info-section>
</div>
<div class="row">
<mat-slide-toggle class="toggle" color="primary" [disabled]="disabled" ngDefaultControl
[(ngModel)]="loginData.allowRegister">
{{'POLICY.DATA.ALLOWREGISTER' | translate}}
</mat-slide-toggle>
<p> {{'POLICY.DATA.ALLOWREGISTER_DESC' | translate}} </p>
<cnsl-info-section class="info">
{{'POLICY.DATA.ALLOWREGISTER_DESC' | translate}}
</cnsl-info-section>
</div>
<div class="row">
<mat-slide-toggle class="toggle" color="primary" [disabled]="disabled" ngDefaultControl
[(ngModel)]="loginData.allowExternalIdp">
{{'POLICY.DATA.ALLOWEXTERNALIDP' | translate}}
</mat-slide-toggle>
<p> {{'POLICY.DATA.ALLOWEXTERNALIDP_DESC' | translate}} </p>
<cnsl-info-section class="info">
{{'POLICY.DATA.ALLOWEXTERNALIDP_DESC' | translate}}
</cnsl-info-section>
</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>
<cnsl-info-section class="info">
{{'POLICY.DATA.FORCEMFA_DESC' | translate}}
</cnsl-info-section>
</div>
<div class="row">
<cnsl-form-field class="form-field" label="Access Code" required="true">
@@ -92,20 +100,37 @@
<mat-icon matTooltip="{{'ACTIONS.REMOVE' | translate}}">
remove_circle</mat-icon>
</button>
<span class="name">{{idp.name}}</span>
<span class="meta">{{ 'IDP.TYPE' | translate }}: {{ 'IDP.TYPES.'+idp.type | translate }}</span>
<span class="meta">{{ 'IDP.ID' | translate }}: {{idp.idpConfigId}}</span>
<div class="line">
<img src="../../../assets/images/google.png"
*ngIf="idp.stylingType == IdpStylingType.IDPSTYLINGTYPE_GOOGLE" alt="google" />
<div>
<span class="name">{{idp.name}}</span>
<span class="meta-info">{{ 'IDP.TYPE' | translate }}: {{ 'IDP.TYPES.'+idp.type | translate }}</span>
<span class="meta-info">{{ 'IDP.ID' | translate }}: {{idp.idpConfigId}}</span>
</div>
</div>
</div>
<div *ngIf="!disabled" class="new-idp" (click)="openDialog()">
<div *ngIf="!disabled" class="new-idp" (click)="openDialog()" matRipple>
<mat-icon>add</mat-icon>
</div>
</div>
<ng-template appHasRole [appHasRole]="['org.idp.read']">
<h2>{{ 'IDP.LIST.TITLE' | translate }}</h2>
<p>{{ 'IDP.LIST.DESCRIPTION' | translate }}</p>
<app-idp-table [service]="service" [serviceType]="serviceType"
[disabled]="([serviceType == PolicyComponentServiceType.ADMIN ? 'iam.idp.write' : serviceType == PolicyComponentServiceType.MGMT ? 'org.idp.write' : ''] | hasRole | async) == false">
</app-idp-table>
<app-card title="{{ 'IDP.LIST.TITLE' | translate }}" description="{{ 'IDP.LIST.DESCRIPTION' | translate }}"
[expanded]="false">
<div card-actions>
<i class="lab la-google"></i>
<i class="lab la-facebook"></i>
<i class="lab la-apple"></i>
<i class="lab la-github"></i>
<i class="lab la-gitlab"></i>
</div>
<app-idp-table [service]="service" [serviceType]="serviceType"
[disabled]="([serviceType == PolicyComponentServiceType.ADMIN ? 'iam.idp.write' : serviceType == PolicyComponentServiceType.MGMT ? 'org.idp.write' : ''] | hasRole | async) == false">
</app-idp-table>
</app-card>
</ng-template>
<cnsl-links *ngIf="nextLinks" [links]="nextLinks"></cnsl-links>
</app-detail-layout>
@@ -15,18 +15,17 @@
margin: .3rem 0;
}
p {
margin-top: .5rem;
font-size: 14px;
color: var(--grey);
.info {
margin-bottom: 1rem;
display: block;
}
}
}
.save-button {
margin-top: 3rem;
margin-bottom: 3rem;
float: right;
display: block;
padding: .5rem 4rem;
}
.idp-table-card {
@@ -46,6 +45,33 @@
display: flex;
margin: 0 -.5rem;
.idp {
background-color: #506e6e;
color: white;
.line {
display: flex;
align-items: center;
img {
height: 30px;
width: 30px;
margin-right: 1rem;
border-radius: .5rem;
object-fit: contain;
}
div {
flex: 1;
display: block;
* {
display: block;
}
}
}
}
.idp,
.new-idp {
display: grid;
@@ -68,15 +94,18 @@
padding: 2px;
}
.meta {
.meta-info {
font-size: 12px;
color: var(--grey);
color: #fafafa;
}
.rm {
color: #f44336;
position: absolute;
top: 0;
left: 0;
display: none;
top: -2px;
transition: all .2s ease;
left: -2px;
transform: translateX(-50%) translateY(-50%);
cursor: pointer;
@@ -86,11 +115,13 @@
}
&:not(.disabled) {
&:hover {
background-color: #ffffff10;
}
&:hover {
.rm {
display: block;
}
}
}
img {
height: 100%;
width: 100%;
@@ -102,6 +133,6 @@
.divider {
width: 100%;
height: 1px;
background-color: var(--grey);
background-color: rgba(var(--grey), .5);
margin: 1rem 0;
}
@@ -9,6 +9,7 @@ import {
DefaultLoginPolicyRequest,
DefaultLoginPolicyView,
IdpProviderView as AdminIdpProviderView,
IdpStylingType,
IdpView as AdminIdpView,
PasswordlessType as AdminPasswordlessType,
} from 'src/app/proto/generated/admin_pb';
@@ -24,6 +25,8 @@ import {
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 { CnslLinks } from '../../links/links.component';
import { IAM_COMPLEXITY_LINK, IAM_LABEL_LINK, IAM_LOGIN_POLICY_LINK, IAM_POLICY_LINK, ORG_COMPLEXITY_LINK, ORG_IAM_POLICY_LINK } from '../../policy-grid/policy-links';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
import { AddIdpDialogComponent } from './add-idp-dialog/add-idp-dialog.component';
@@ -46,6 +49,9 @@ export class LoginPolicyComponent implements OnDestroy {
public loading: boolean = false;
public disabled: boolean = true;
public IdpStylingType: any = IdpStylingType;
public nextLinks: CnslLinks[] = [];
constructor(
private route: ActivatedRoute,
private toast: ToastService,
@@ -59,11 +65,20 @@ export class LoginPolicyComponent implements OnDestroy {
this.service = this.injector.get(ManagementService as Type<ManagementService>);
this.passwordlessTypes = [MgmtPasswordlessType.PASSWORDLESSTYPE_ALLOWED,
MgmtPasswordlessType.PASSWORDLESSTYPE_NOT_ALLOWED];
this.nextLinks = [
ORG_COMPLEXITY_LINK,
ORG_IAM_POLICY_LINK,
];
break;
case PolicyComponentServiceType.ADMIN:
this.service = this.injector.get(AdminService as Type<AdminService>);
this.passwordlessTypes = [AdminPasswordlessType.PASSWORDLESSTYPE_ALLOWED,
AdminPasswordlessType.PASSWORDLESSTYPE_NOT_ALLOWED];
this.nextLinks = [
IAM_COMPLEXITY_LINK,
IAM_POLICY_LINK,
IAM_LABEL_LINK,
];
break;
}
@@ -207,7 +222,7 @@ export class LoginPolicyComponent implements OnDestroy {
switch (this.serviceType) {
case PolicyComponentServiceType.MGMT:
(this.service as ManagementService).RemoveIdpProviderFromLoginPolicy(idp.idpConfigId).then(() => {
const index = this.idps.findIndex(temp => temp === idp);
const index = (this.idps as MgmtIdpProviderView.AsObject[]).findIndex(temp => temp === idp);
if (index > -1) {
this.idps.splice(index, 1);
}
@@ -215,7 +230,7 @@ export class LoginPolicyComponent implements OnDestroy {
break;
case PolicyComponentServiceType.ADMIN:
(this.service as AdminService).RemoveIdpProviderFromDefaultLoginPolicy(idp.idpConfigId).then(() => {
const index = this.idps.findIndex(temp => temp === idp);
const index = (this.idps as AdminIdpProviderView.AsObject[]).findIndex(temp => temp === idp);
if (index > -1) {
this.idps.splice(index, 1);
}
@@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatRippleModule } from '@angular/material/core';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSelectModule } from '@angular/material/select';
@@ -15,6 +16,8 @@ import { IdpTableModule } from 'src/app/modules/idp-table/idp-table.module';
import { InputModule } from 'src/app/modules/input/input.module';
import { MfaTableModule } from 'src/app/modules/mfa-table/mfa-table.module';
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
import { InfoSectionModule } from '../../info-section/info-section.module';
import { LinksModule } from '../../links/links.module';
import { AddIdpDialogModule } from './add-idp-dialog/add-idp-dialog.module';
import { LoginPolicyRoutingModule } from './login-policy-routing.module';
@@ -25,6 +28,7 @@ import { LoginPolicyComponent } from './login-policy.component';
imports: [
LoginPolicyRoutingModule,
CommonModule,
InfoSectionModule,
FormsModule,
CardModule,
InputModule,
@@ -41,6 +45,8 @@ import { LoginPolicyComponent } from './login-policy.component';
MfaTableModule,
MatProgressSpinnerModule,
MatSelectModule,
MatRippleModule,
LinksModule,
],
})
export class LoginPolicyModule { }
@@ -20,7 +20,9 @@
</div>
<div class="btn-container">
<button (click)="savePolicy()" color="primary" type="submit"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
<button (click)="savePolicy()" color="primary" type="submit" mat-raised-button>{{ 'ACTIONS.SAVE' | translate
}}</button>
</div>
<cnsl-links *ngIf="nextLinks" [links]="nextLinks"></cnsl-links>
</app-detail-layout>
@@ -37,6 +37,5 @@
button {
margin-top: 3rem;
display: block;
padding: .5rem 4rem;
}
}
@@ -9,6 +9,8 @@ import { AdminService } from 'src/app/services/admin.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { StorageService } from 'src/app/services/storage.service';
import { ToastService } from 'src/app/services/toast.service';
import { CnslLinks } from '../../links/links.component';
import { IAM_COMPLEXITY_LINK, IAM_LABEL_LINK, IAM_LOGIN_POLICY_LINK, ORG_LOGIN_POLICY_LINK, ORG_COMPLEXITY_LINK } from '../../policy-grid/policy-links';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
@@ -28,7 +30,7 @@ export class OrgIamPolicyComponent implements OnDestroy {
private org!: Org.AsObject;
public PolicyComponentServiceType: any = PolicyComponentServiceType;
public nextLinks: Array<CnslLinks> = [];
constructor(
private route: ActivatedRoute,
private toast: ToastService,
@@ -44,6 +46,16 @@ export class OrgIamPolicyComponent implements OnDestroy {
this.serviceType = data.serviceType;
if (this.serviceType === PolicyComponentServiceType.MGMT) {
this.managementService = this.injector.get(ManagementService as Type<ManagementService>);
this.nextLinks = [
ORG_COMPLEXITY_LINK,
ORG_LOGIN_POLICY_LINK,
];
} else {
this.nextLinks = [
IAM_COMPLEXITY_LINK,
IAM_LOGIN_POLICY_LINK,
IAM_LABEL_LINK,
];
}
return this.route.params;
})).subscribe(_ => {
@@ -9,6 +9,8 @@ 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 { InputModule } from 'src/app/modules/input/input.module';
import { InfoSectionModule } from '../../info-section/info-section.module';
import { LinksModule } from '../../links/links.module';
import { OrgIamPolicyRoutingModule } from './org-iam-policy-routing.module';
import { OrgIamPolicyComponent } from './org-iam-policy.component';
@@ -25,8 +27,10 @@ import { OrgIamPolicyComponent } from './org-iam-policy.component';
MatIconModule,
HasRoleModule,
MatTooltipModule,
InfoSectionModule,
TranslateModule,
DetailLayoutModule,
LinksModule
],
})
export class OrgIamPolicyModule { }
@@ -34,6 +34,5 @@
button {
margin-top: 3rem;
display: block;
padding: .5rem 4rem;
}
}
@@ -16,6 +16,7 @@
<div *ngIf="complexityData" class="content">
<div class="row">
<mat-icon class="icon" svgIcon="mdi_counter"></mat-icon>
<span class="left-desc">{{'POLICY.DATA.MINLENGTH' | translate}}</span>
<span class="fill-space"></span>
<div class="length-wrapper">
@@ -29,18 +30,21 @@
</div>
</div>
<div class="row">
<mat-icon class="icon" svgIcon="mdi_numeric"></mat-icon>
<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">
<mat-icon class="icon" svgIcon="mdi_symbol"></mat-icon>
<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">
<mat-icon class="icon" svgIcon="mdi_format-letter-case-lower"></mat-icon>
<span class="left-desc">{{'POLICY.DATA.HASLOWERCASE' | translate}}</span>
<span class="fill-space"></span>
<mat-slide-toggle color="primary" name="hasLowercase" ngDefaultControl
@@ -48,6 +52,7 @@
</mat-slide-toggle>
</div>
<div class="row">
<mat-icon class="icon" svgIcon="mdi_format-letter-case-upper"></mat-icon>
<span class="left-desc">{{'POLICY.DATA.HASUPPERCASE' | translate}}</span>
<span class="fill-space"></span>
<mat-slide-toggle color="primary" name="hasUppercase" ngDefaultControl
@@ -57,7 +62,9 @@
</div>
<div class="btn-container">
<button (click)="savePolicy()" color="primary" type="submit"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
<button (click)="savePolicy()" color="primary" type="submit" mat-raised-button>{{ 'ACTIONS.SAVE' | translate
}}</button>
</div>
<cnsl-links *ngIf="nextLinks" [links]="nextLinks"></cnsl-links>
</app-detail-layout>
@@ -18,6 +18,10 @@
align-items: center;
padding: .3rem 0;
.icon {
margin-right: 1rem;
}
.left-desc {
font-size: .9rem;
}
@@ -42,6 +46,5 @@
button {
margin-top: 3rem;
display: block;
padding: .5rem 4rem;
}
}
@@ -7,6 +7,8 @@ import { PasswordComplexityPolicyView } from 'src/app/proto/generated/management
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 { CnslLinks } from '../../links/links.component';
import { IAM_LABEL_LINK, IAM_LOGIN_POLICY_LINK, IAM_POLICY_LINK, ORG_IAM_POLICY_LINK, ORG_LOGIN_POLICY_LINK } from '../../policy-grid/policy-links';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
@@ -25,6 +27,7 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
public PolicyComponentServiceType: any = PolicyComponentServiceType;
public loading: boolean = false;
public nextLinks: CnslLinks[] = [];
constructor(
private route: ActivatedRoute,
private toast: ToastService,
@@ -36,9 +39,18 @@ export class PasswordComplexityPolicyComponent implements OnDestroy {
switch (this.serviceType) {
case PolicyComponentServiceType.MGMT:
this.service = this.injector.get(ManagementService as Type<ManagementService>);
this.nextLinks = [
ORG_IAM_POLICY_LINK,
ORG_LOGIN_POLICY_LINK,
];
break;
case PolicyComponentServiceType.ADMIN:
this.service = this.injector.get(AdminService as Type<AdminService>);
this.nextLinks = [
IAM_POLICY_LINK,
IAM_LOGIN_POLICY_LINK,
IAM_LABEL_LINK,
];
break;
}
@@ -10,6 +10,7 @@ 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 { InputModule } from 'src/app/modules/input/input.module';
import { LinksModule } from '../../links/links.module';
import { PasswordComplexityPolicyRoutingModule } from './password-complexity-policy-routing.module';
import { PasswordComplexityPolicyComponent } from './password-complexity-policy.component';
@@ -29,6 +30,7 @@ import { PasswordComplexityPolicyComponent } from './password-complexity-policy.
TranslateModule,
DetailLayoutModule,
MatProgressSpinnerModule,
LinksModule,
],
})
export class PasswordComplexityPolicyModule { }
@@ -33,7 +33,7 @@
</div>
<div class="btn-container">
<button (click)="savePolicy()" color="primary" type="submit"
mat-raised-button>{{ 'ACTIONS.SAVE' | translate }}</button>
<button (click)="savePolicy()" color="primary" type="submit" mat-raised-button>{{ 'ACTIONS.SAVE' | translate
}}</button>
</div>
</app-detail-layout>
@@ -9,6 +9,7 @@ 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 { InputModule } from 'src/app/modules/input/input.module';
import { LinksModule } from '../../links/links.module';
import { PasswordLockoutPolicyRoutingModule } from './password-lockout-policy-routing.module';
import { PasswordLockoutPolicyComponent } from './password-lockout-policy.component';