mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-10 16:15:12 +00:00
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:
co-authored by
Miguel A. C
parent
eb31c2a3be
commit
d01f4d229f
@@ -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;
|
||||
}
|
||||
-24
@@ -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);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user