1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 16:23:44 +00:00

SG-680 - DomainAddEditDialog - Unique domain name enforcement implemented

This commit is contained in:
Jared Snider
2022-12-08 18:14:57 -05:00
parent 64daf70cea
commit cbd6e96aa4
4 changed files with 47 additions and 6 deletions

View File

@@ -5568,6 +5568,9 @@
"domainVerified": {
"message": "Domain verified"
},
"duplicateDomainError": {
"message": "You can't claim the same domain twice."
},
"domainNotVerified": {
"message": "$DOMAIN$ not verified. Check your DNS record.",
"placeholders": {
@@ -5577,5 +5580,4 @@
}
}
}
}

View File

@@ -11,6 +11,7 @@ import { Utils } from "@bitwarden/common/misc/utils";
import { OrganizationDomainRequest } from "@bitwarden/common/services/organization-domain/requests/organization-domain.request";
import { domainNameValidator } from "./domain-name.validator";
import { uniqueInArrayValidator } from "./unique-in-array.validator";
export interface DomainAddEditDialogData {
organizationId: string;
orgDomain: OrganizationDomainResponse;
@@ -26,11 +27,17 @@ export class DomainAddEditDialogComponent implements OnInit {
disablePadding = false;
// TODO: should invalidDomainNameMessage have something like: "'https://', 'http://', or 'www.' domain prefixes not allowed."
// TODO: write separate uniqueIn validator w/ translated msg: "You cant claim the same domain twice."
domainForm: FormGroup = this.formBuilder.group({
domainName: [
"",
[Validators.required, domainNameValidator(this.i18nService.t("invalidDomainNameMessage"))],
[
Validators.required,
domainNameValidator(this.i18nService.t("invalidDomainNameMessage")),
uniqueInArrayValidator(
this.data.existingDomainNames,
this.i18nService.t("duplicateDomainError")
),
],
],
txt: [{ value: null, disabled: true }],
});

View File

@@ -0,0 +1,23 @@
import { AbstractControl, ValidationErrors, ValidatorFn } from "@angular/forms";
export function uniqueInArrayValidator(values: Array<string>, errorMessage: string): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const value = control.value;
if (!value) {
return null;
}
const lowerTrimmedValue = value.toLowerCase().trim();
// check if the entered value is unique
if (values.some((val) => val.toLowerCase().trim() === lowerTrimmedValue)) {
return {
nonUniqueValue: {
message: errorMessage,
},
};
}
return null;
};
}

View File

@@ -1,6 +1,6 @@
import { Component, OnDestroy, OnInit } from "@angular/core";
import { ActivatedRoute, Params } from "@angular/router";
import { concatMap, Observable, Subject, takeUntil } from "rxjs";
import { concatMap, Observable, Subject, take, takeUntil } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
@@ -68,7 +68,7 @@ export class DomainVerificationComponent implements OnInit, OnDestroy {
const domainAddEditDialogData: DomainAddEditDialogData = {
organizationId: this.organizationId,
orgDomain: null,
existingDomainNames: [],
existingDomainNames: this.getExistingDomainNames(),
};
this.dialogService.open(DomainAddEditDialogComponent, {
@@ -80,7 +80,7 @@ export class DomainVerificationComponent implements OnInit, OnDestroy {
const domainAddEditDialogData: DomainAddEditDialogData = {
organizationId: this.organizationId,
orgDomain: orgDomain,
existingDomainNames: [],
existingDomainNames: this.getExistingDomainNames(),
};
this.dialogService.open(DomainAddEditDialogComponent, {
@@ -88,6 +88,15 @@ export class DomainVerificationComponent implements OnInit, OnDestroy {
});
}
private getExistingDomainNames(): Array<string> {
let existingDomainNames: string[];
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
this.orgDomains$.pipe(take(1)).subscribe((orgDomains: Array<OrganizationDomainResponse>) => {
existingDomainNames = orgDomains.map((o) => o.domainName);
});
return existingDomainNames;
}
ngOnDestroy(): void {
this.componentDestroyed$.next();
this.componentDestroyed$.complete();