fix(console): move org domains into settings page of the organization (#6612)

* fix: hide domains settings for unauthorized users

* refine sidenav object mapping

* move domains to settings

* change docs

* set anchor to list element

* remove canwrite check in ngif

---------

Co-authored-by: Miguel A. C <[email protected]>
This commit is contained in:
Max Peintner
2023-09-29 09:31:35 +02:00
committed by GitHub
co-authored by Miguel A. C
parent eb31c2a3be
commit d01f4d229f
42 changed files with 161 additions and 202 deletions
@@ -1,18 +0,0 @@
<span class="title" mat-dialog-title>{{ 'ORG.DOMAINS.ADD.TITLE' | translate }}</span>
<div mat-dialog-content>
<p class="desc cnsl-secondary-text">{{ 'ORG.DOMAINS.ADD.DESCRIPTION' | translate }}</p>
<cnsl-form-field label="Domain" required="true" class="form-field">
<cnsl-label>Domain</cnsl-label>
<input cnslInput [(ngModel)]="newdomain" />
</cnsl-form-field>
</div>
<div mat-dialog-actions class="action">
<button mat-stroked-button (click)="closeDialog()">
{{ 'ACTIONS.CANCEL' | translate }}
</button>
<button color="primary" mat-raised-button class="ok-button" [disabled]="!newdomain" (click)="closeDialogWithSuccess()">
{{ 'ACTIONS.ADD' | translate }}
</button>
</div>
@@ -1,21 +0,0 @@
.title {
font-size: 1.2rem;
margin-top: 0;
}
.desc {
font-size: 0.9rem;
}
.form-field {
width: 100%;
}
.action {
display: flex;
justify-content: space-between;
.ok-button {
margin-left: 0.5rem;
}
}
@@ -1,24 +0,0 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { AddDomainDialogComponent } from './add-domain-dialog.component';
describe('WarnDialogComponent', () => {
let component: AddDomainDialogComponent;
let fixture: ComponentFixture<AddDomainDialogComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [AddDomainDialogComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AddDomainDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,26 +0,0 @@
import { Component, Inject } from '@angular/core';
import {
MatLegacyDialogRef as MatDialogRef,
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
} from '@angular/material/legacy-dialog';
@Component({
selector: 'cnsl-add-domain-dialog',
templateUrl: './add-domain-dialog.component.html',
styleUrls: ['./add-domain-dialog.component.scss'],
})
export class AddDomainDialogComponent {
public newdomain: string = '';
constructor(
public dialogRef: MatDialogRef<AddDomainDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
) {}
public closeDialog(): void {
this.dialogRef.close(false);
}
public closeDialogWithSuccess(): void {
this.dialogRef.close(this.newdomain);
}
}
@@ -1,14 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button';
import { TranslateModule } from '@ngx-translate/core';
import { InputModule } from 'src/app/modules/input/input.module';
import { AddDomainDialogComponent } from './add-domain-dialog.component';
@NgModule({
declarations: [AddDomainDialogComponent],
imports: [CommonModule, TranslateModule, MatButtonModule, InputModule, FormsModule],
})
export class AddDomainDialogModule {}
@@ -1,87 +0,0 @@
<span class="title" mat-dialog-title>{{ 'ORG.PAGES.ORGDOMAIN.TITLE' | translate }} {{ domain?.domainName }}</span>
<div mat-dialog-content>
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION' | translate }}</p>
<cnsl-info-section [type]="InfoSectionType.WARN" class="desc">{{
'ORG.PAGES.ORGDOMAIN.VERIFICATION_VALIDATION_DESC' | translate
}}</cnsl-info-section>
<p
*ngIf="domain?.validationType !== DomainValidationType.DOMAIN_VALIDATION_TYPE_UNSPECIFIED && !(dns || http)"
class="desc"
>
{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_VALIDATION_ONGOING' | translate: domain }}
{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_VALIDATION_ONGOING_TYPE' | translate }}
{{ 'ORG.PAGES.ORGDOMAIN.TYPES.' + domain?.validationType | translate }}
</p>
<div class="btn-container">
<button
[disabled]="domain?.validationType === DomainValidationType.DOMAIN_VALIDATION_TYPE_UNSPECIFIED"
color="primary"
type="submit"
mat-raised-button
*ngIf="!(dns || http)"
(click)="validate()"
>
{{ 'ACTIONS.VERIFY' | translate }}
</button>
<mat-spinner class="spinner" *ngIf="validating" diameter="20" mode="indeterminate"></mat-spinner>
<button *ngIf="!showNew" mat-stroked-button color="primary" (click)="showNew = true">
{{ 'ORG.PAGES.ORGDOMAIN.REQUESTNEWTOKEN' | translate }}
</button>
</div>
<ng-container *ngIf="showNew">
<p>{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_NEWTOKEN_TITLE' | translate }}</p>
<p class="desc">{{ 'ORG.PAGES.ORGDOMAIN.VERIFICATION_NEWTOKEN_DESC' | translate }}</p>
<div class="btn-container" *ngIf="!(http || dns)">
<button color="primary" mat-raised-button (click)="loadHttpToken()">HTTP</button>
<button color="primary" mat-raised-button (click)="loadDnsToken()">DNS</button>
</div>
<div *ngIf="http">
<p>HTTP TOKEN</p>
<p class="entry">{{ http.url }}</p>
<div class="btn-container">
<button mat-stroked-button (click)="saveFile()" color="primary">{{ 'ORG.PAGES.DOWNLOAD_FILE' | translate }}</button>
<button color="primary" class="verify-button" type="submit" mat-raised-button (click)="validate()">
<span>{{ 'ACTIONS.VERIFY' | translate }}</span>
</button>
<mat-spinner class="spinner" *ngIf="validating" diameter="20" mode="indeterminate"></mat-spinner>
</div>
</div>
<div *ngIf="dns">
<p>DNS TOKEN</p>
<div class="domain-line" *ngIf="dns.token">
<p class="entry">{{ dns.token }}</p>
<button
color="primary"
[disabled]="copied === data.clientSecret"
matTooltip="copy to clipboard"
cnslCopyToClipboard
[valueToCopy]="dns.token"
(copiedValue)="copied = $event"
mat-icon-button
>
<i *ngIf="copied !== dns.token" class="las la-clipboard"></i>
<i *ngIf="copied === dns.token" class="las la-clipboard-check"></i>
</button>
<button color="primary" type="submit" mat-raised-button class="verify-button" (click)="validate()">
{{ 'ACTIONS.VERIFY' | translate }}
</button>
<mat-spinner class="spinner" *ngIf="validating" diameter="20" mode="indeterminate"></mat-spinner>
</div>
<p class="entry">{{ dns.url }}</p>
</div>
</ng-container>
</div>
<div mat-dialog-actions class="action">
<button mat-stroked-button (click)="closeDialog()">
{{ 'ACTIONS.CLOSE' | translate }}
</button>
</div>
@@ -1,28 +0,0 @@
.btn-container {
display: flex;
margin: -0.5rem;
align-items: center;
button {
margin: 1rem 0.5rem;
}
}
.desc {
font-size: 0.9rem;
}
.entry {
margin: 0.5rem 0;
display: inline-block;
}
.domain-line {
display: flex;
align-items: center;
}
.action {
display: flex;
justify-content: flex-start;
}
@@ -1,24 +0,0 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { DomainVerificationComponent } from './domain-verification.component';
describe('DomainVerificationComponent', () => {
let component: DomainVerificationComponent;
let fixture: ComponentFixture<DomainVerificationComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [DomainVerificationComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DomainVerificationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,93 +0,0 @@
import { Component, Inject } from '@angular/core';
import {
MatLegacyDialogRef as MatDialogRef,
MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA,
} from '@angular/material/legacy-dialog';
import { saveAs } from 'file-saver';
import { InfoSectionType } from 'src/app/modules/info-section/info-section.component';
import { GenerateOrgDomainValidationResponse } from 'src/app/proto/generated/zitadel/management_pb';
import { Domain, DomainValidationType } from 'src/app/proto/generated/zitadel/org_pb';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
@Component({
selector: 'cnsl-domain-verification',
templateUrl: './domain-verification.component.html',
styleUrls: ['./domain-verification.component.scss'],
})
export class DomainVerificationComponent {
public domain?: Domain.AsObject;
public DomainValidationType: any = DomainValidationType;
public http?: GenerateOrgDomainValidationResponse.AsObject;
public dns?: GenerateOrgDomainValidationResponse.AsObject;
public copied: string = '';
public showNew: boolean = false;
public validating: boolean = false;
public InfoSectionType: any = InfoSectionType;
constructor(
private toast: ToastService,
public dialogRef: MatDialogRef<DomainVerificationComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private mgmtService: ManagementService,
) {
this.domain = data.domain;
if (this.domain?.validationType === DomainValidationType.DOMAIN_VALIDATION_TYPE_UNSPECIFIED) {
this.showNew = true;
}
}
async loadHttpToken(): Promise<void> {
if (this.domain) {
this.mgmtService
.generateOrgDomainValidation(this.domain.domainName, DomainValidationType.DOMAIN_VALIDATION_TYPE_HTTP)
.then((http) => {
this.http = http;
});
}
}
async loadDnsToken(): Promise<void> {
if (this.domain) {
this.mgmtService
.generateOrgDomainValidation(this.domain.domainName, DomainValidationType.DOMAIN_VALIDATION_TYPE_DNS)
.then((dns) => {
this.dns = dns;
});
}
}
public closeDialog(): void {
this.dialogRef.close(false);
}
public validate(): void {
this.validating = true;
if (this.domain) {
this.mgmtService
.validateOrgDomain(this.domain.domainName)
.then(() => {
this.dialogRef.close(true);
this.toast.showInfo('ORG.PAGES.ORGDOMAIN.VERIFICATION_SUCCESSFUL', true);
this.validating = false;
})
.catch((error) => {
this.toast.showError(error);
this.validating = false;
});
}
}
public saveFile(): void {
if (this.http) {
const blob = new Blob([this.http.token], { type: 'text/plain;charset=utf-8' });
saveAs(blob, this.http.token + '.txt');
}
}
}
@@ -1,17 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { DomainsComponent } from './domains.component';
const routes: Routes = [
{
path: '',
component: DomainsComponent,
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class DomainsRoutingModule {}
@@ -1,69 +0,0 @@
<div class="max-width-container">
<ng-container *ngIf="['org.write$'] | hasRole as canwrite$">
<div class="domain-top-view">
<div>
<div class="domain-title-row">
<h1>{{ 'ORG.DOMAINS.TITLE' | translate }}</h1>
<a
mat-icon-button
href="https://zitadel.com/docs/guides/manage/console/organizations#how-zitadel-handles-usernames"
rel="noreferrer"
target="_blank"
>
<i class="las la-info-circle"></i>
</a>
</div>
<p class="desc cnsl-secondary-text">{{ 'ORG.DOMAINS.DESCRIPTION' | translate }}</p>
</div>
<span class="fill-space"></span>
<button
[disabled]="(canwrite$ | async) === false"
matTooltip="Add domain"
mat-raised-button
color="primary"
class="cnsl-action-button"
(click)="addNewDomain()"
>
<mat-icon>add</mat-icon>
<span>{{ 'ACTIONS.NEW' | translate }}</span>
<cnsl-action-keys (actionTriggered)="addNewDomain()"> </cnsl-action-keys>
</button>
</div>
<cnsl-card *ngFor="let domain of domains" class="domain-card">
<div class="domain">
<span class="title">{{ domain.domainName }}</span>
<i matTooltip="verified" *ngIf="domain.isVerified" class="verified las la-check-circle"></i>
<i matTooltip="primary" *ngIf="domain.isPrimary" class="primary las la-star"></i>
<a
*ngIf="domain.isVerified && !domain.isPrimary && (canwrite$ | async)"
class="primaryset"
(click)="setPrimary(domain)"
>{{ 'ORG.DOMAINS.SETPRIMARY' | translate }}</a
>
<span class="fill-space"></span>
<button
mat-icon-button
[disabled]="(canwrite$ | async) === false || domain.isVerified"
*ngIf="(canwrite$ | async) && verifyOrgDomains"
(click)="verifyDomain(domain)"
>
<i class="las la-pen"></i>
</button>
<button
class="domain-rem-button"
[disabled]="(canwrite$ | async) === false || domain.isPrimary"
matTooltip="Remove domain"
color="warn"
mat-icon-button
(click)="removeDomain(domain.domainName)"
>
<i class="las la-trash"></i>
</button>
</div>
</cnsl-card>
</ng-container>
</div>
@@ -1,69 +0,0 @@
.domain-top-view {
display: flex;
align-items: center;
padding-top: 2rem;
.domain-title-row {
display: flex;
align-items: center;
h1 {
margin: 0;
}
a i {
font-size: 1.2rem;
height: 1.2rem;
line-height: 1.2rem;
}
}
.fill-space {
flex: 1;
}
.actions {
display: flex;
align-items: center;
}
}
.desc {
margin-bottom: 2rem;
font-size: 14px;
}
.domain-card {
.domain {
display: flex;
flex-direction: row;
align-items: center;
.title {
font-size: 16px;
margin-right: 1rem;
}
.primaryset {
font-size: 13px;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
.verified,
.primary {
margin-right: 1rem;
}
.verify-btn {
font-size: 13px;
}
.fill-space {
flex: 1;
}
}
}
@@ -1,24 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { OrgDomainsComponent } from './org-domains.component';
describe('OrgDomainsComponent', () => {
let component: OrgDomainsComponent;
let fixture: ComponentFixture<OrgDomainsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [OrgDomainsComponent],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(OrgDomainsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -1,133 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
import { InfoSectionType } from 'src/app/modules/info-section/info-section.component';
import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component';
import { Domain, DomainValidationType } from 'src/app/proto/generated/zitadel/org_pb';
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
import { AddDomainDialogComponent } from './add-domain-dialog/add-domain-dialog.component';
import { DomainVerificationComponent } from './domain-verification/domain-verification.component';
@Component({
selector: 'cnsl-domains',
templateUrl: './domains.component.html',
styleUrls: ['./domains.component.scss'],
})
export class DomainsComponent implements OnInit {
public domains: Domain.AsObject[] = [];
public primaryDomain: string = '';
public InfoSectionType: any = InfoSectionType;
public verifyOrgDomains: boolean | undefined;
constructor(
private mgmtService: ManagementService,
private toast: ToastService,
private dialog: MatDialog,
breadcrumbService: BreadcrumbService,
) {
const bread: Breadcrumb = {
type: BreadcrumbType.ORG,
routerLink: ['/org'],
};
breadcrumbService.setBreadcrumb([bread]);
}
ngOnInit(): void {
this.loadDomains();
}
public loadDomains(): void {
this.mgmtService.getDomainPolicy().then((result) => {
this.verifyOrgDomains = result.policy?.validateOrgDomains;
});
this.mgmtService.listOrgDomains().then((result) => {
this.domains = result.resultList;
this.primaryDomain = this.domains.find((domain) => domain.isPrimary)?.domainName ?? '';
});
}
public setPrimary(domain: Domain.AsObject): void {
this.mgmtService
.setPrimaryOrgDomain(domain.domainName)
.then(() => {
this.toast.showInfo('ORG.TOAST.SETPRIMARY', true);
this.loadDomains();
})
.catch((error) => {
this.toast.showError(error);
});
}
public addNewDomain(): void {
const dialogRef = this.dialog.open(AddDomainDialogComponent, {
data: {},
width: '400px',
});
dialogRef.afterClosed().subscribe((domainName) => {
if (domainName) {
this.mgmtService
.addOrgDomain(domainName)
.then(() => {
this.toast.showInfo('ORG.TOAST.DOMAINADDED', true);
if (this.verifyOrgDomains) {
this.verifyDomain({
domainName: domainName,
validationType: DomainValidationType.DOMAIN_VALIDATION_TYPE_UNSPECIFIED,
});
} else {
this.loadDomains();
}
})
.catch((error) => {
this.toast.showError(error);
});
}
});
}
public removeDomain(domain: string): void {
const dialogRef = this.dialog.open(WarnDialogComponent, {
data: {
confirmKey: 'ACTIONS.DELETE',
cancelKey: 'ACTIONS.CANCEL',
titleKey: 'ORG.DOMAINS.DELETE.TITLE',
descriptionKey: 'ORG.DOMAINS.DELETE.DESCRIPTION',
},
width: '400px',
});
dialogRef.afterClosed().subscribe((del) => {
if (del) {
this.mgmtService
.removeOrgDomain(domain)
.then(() => {
this.toast.showInfo('ORG.TOAST.DOMAINREMOVED', true);
const index = this.domains.findIndex((d) => d.domainName === domain);
if (index > -1) {
this.domains.splice(index, 1);
}
})
.catch((error) => {
this.toast.showError(error);
});
}
});
}
public verifyDomain(domain: Partial<Domain.AsObject>): void {
const dialogRef = this.dialog.open(DomainVerificationComponent, {
data: {
domain: domain,
},
width: '500px',
});
dialogRef.afterClosed().subscribe(() => {
this.loadDomains();
});
}
}
@@ -1,40 +0,0 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatIconModule } from '@angular/material/icon';
import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button';
import { MatLegacyProgressSpinnerModule as MatProgressSpinnerModule } from '@angular/material/legacy-progress-spinner';
import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { CopyToClipboardModule } from 'src/app/directives/copy-to-clipboard/copy-to-clipboard.module';
import { ActionKeysModule } from 'src/app/modules/action-keys/action-keys.module';
import { CardModule } from 'src/app/modules/card/card.module';
import { InfoSectionModule } from 'src/app/modules/info-section/info-section.module';
import { InputModule } from 'src/app/modules/input/input.module';
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
import { AddDomainDialogModule } from './add-domain-dialog/add-domain-dialog.module';
import { DomainVerificationComponent } from './domain-verification/domain-verification.component';
import { DomainsRoutingModule } from './domains-routing.module';
import { DomainsComponent } from './domains.component';
@NgModule({
declarations: [DomainsComponent, DomainVerificationComponent],
imports: [
DomainsRoutingModule,
AddDomainDialogModule,
CommonModule,
MatIconModule,
CardModule,
HasRolePipeModule,
ActionKeysModule,
InfoSectionModule,
MatButtonModule,
MatTooltipModule,
CopyToClipboardModule,
InputModule,
TranslateModule,
InfoSectionModule,
MatProgressSpinnerModule,
],
})
export default class DomainsModule {}
@@ -8,9 +8,11 @@
</div>
<span class="fill-space"></span>
</div>
<cnsl-settings-list
[selectedId]="id"
[serviceType]="PolicyComponentServiceType.ADMIN"
[settingsList]="settingsList"
></cnsl-settings-list>
<ng-container *ngIf="settingsList | async as list">
<cnsl-settings-list
[selectedId]="id"
[serviceType]="PolicyComponentServiceType.ADMIN"
[settingsList]="list"
></cnsl-settings-list>
</ng-container>
</div>
@@ -1,6 +1,6 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { Subject, takeUntil } from 'rxjs';
import { Observable, of, Subject, takeUntil } from 'rxjs';
import { PolicyComponentServiceType } from 'src/app/modules/policies/policy-component-types.enum';
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
@@ -22,7 +22,6 @@ import {
SECRETS,
SECURITY,
} from '../../modules/settings-list/settings';
import { checkSettingsPermissions } from '../org-settings/org-settings.component';
@Component({
selector: 'cnsl-instance-settings',
@@ -55,7 +54,7 @@ export class InstanceSettingsComponent implements OnInit, OnDestroy {
SECURITY,
];
public settingsList: SidenavSetting[] = [];
public settingsList: Observable<SidenavSetting[]> = of([]);
private destroy$: Subject<void> = new Subject();
constructor(
@@ -81,13 +80,7 @@ export class InstanceSettingsComponent implements OnInit, OnDestroy {
}
ngOnInit(): void {
checkSettingsPermissions(this.defaultSettingsList, PolicyComponentServiceType.ADMIN, this.authService).subscribe(
(allowed) => {
this.settingsList = this.defaultSettingsList.filter((setting, index) => {
return allowed[index];
});
},
);
this.settingsList = this.authService.isAllowedMapper(this.defaultSettingsList, (setting) => setting.requiredRoles.admin);
}
ngOnDestroy(): void {
@@ -8,9 +8,11 @@
</div>
<span class="fill-space"></span>
</div>
<cnsl-settings-list
[selectedId]="id"
[serviceType]="PolicyComponentServiceType.MGMT"
[settingsList]="settingsList"
></cnsl-settings-list>
<ng-container *ngIf="settingsList | async as list">
<cnsl-settings-list
[selectedId]="id"
[serviceType]="PolicyComponentServiceType.MGMT"
[settingsList]="list"
></cnsl-settings-list>
</ng-container>
</div>
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { forkJoin, of, take } from 'rxjs';
import { Observable, of, take } from 'rxjs';
import { PolicyComponentServiceType } from 'src/app/modules/policies/policy-component-types.enum';
import { SidenavSetting } from 'src/app/modules/sidenav/sidenav.component';
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
@@ -17,6 +17,7 @@ import {
MESSAGETEXTS,
NOTIFICATION_POLICY,
PRIVACYPOLICY,
VERIFIED_DOMAINS,
} from '../../modules/settings-list/settings';
@Component({
@@ -34,6 +35,7 @@ export class OrgSettingsComponent implements OnInit {
COMPLEXITY,
LOCKOUT,
NOTIFICATION_POLICY,
VERIFIED_DOMAINS,
DOMAIN,
BRANDING,
MESSAGETEXTS,
@@ -41,7 +43,7 @@ export class OrgSettingsComponent implements OnInit {
PRIVACYPOLICY,
];
public settingsList: SidenavSetting[] = [];
public settingsList: Observable<Array<SidenavSetting>> = of([]);
constructor(
breadcrumbService: BreadcrumbService,
@@ -65,40 +67,8 @@ export class OrgSettingsComponent implements OnInit {
}
ngOnInit(): void {
checkSettingsPermissions(this.defaultSettingsList, PolicyComponentServiceType.MGMT, this.authService).subscribe(
(allowed) => {
this.settingsList = this.defaultSettingsList.filter((setting, index) => {
return allowed[index];
});
},
);
this.settingsList = this.authService
.isAllowedMapper(this.defaultSettingsList, (setting) => setting.requiredRoles.mgmt)
.pipe(take(1));
}
}
// Return a Observables<boolean>[] that will wait till all service calls are finished to then check if user is allowed to see a setting
export function checkSettingsPermissions(settings: SidenavSetting[], serviceType: string, authService: GrpcAuthService) {
return forkJoin(
settings
.filter((setting) => {
if (serviceType === PolicyComponentServiceType.ADMIN) {
return setting.requiredRoles && setting.requiredRoles.admin;
} else {
return setting.requiredRoles && setting.requiredRoles.mgmt;
}
})
.map((setting) => {
if (!setting.requiredRoles) {
return of(true);
}
if (!setting.requiredRoles.mgmt) {
return of(true);
}
if (setting.requiredRoles.mgmt) {
return authService.isAllowed(setting.requiredRoles.mgmt).pipe(take(1));
}
return of(false);
}),
);
}