mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
Remove v1 generator UI from desktop (#12909)
Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
6deb0dc2ad
commit
ee70c67fce
@@ -54,7 +54,6 @@ import { InternalFolderService } from "@bitwarden/common/vault/abstractions/fold
|
|||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { DialogService, ToastOptions, ToastService } from "@bitwarden/components";
|
import { DialogService, ToastOptions, ToastService } from "@bitwarden/components";
|
||||||
import { CredentialGeneratorHistoryDialogComponent } from "@bitwarden/generator-components";
|
import { CredentialGeneratorHistoryDialogComponent } from "@bitwarden/generator-components";
|
||||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
|
|
||||||
import { KeyService, BiometricStateService } from "@bitwarden/key-management";
|
import { KeyService, BiometricStateService } from "@bitwarden/key-management";
|
||||||
|
|
||||||
import { DeleteAccountComponent } from "../auth/delete-account.component";
|
import { DeleteAccountComponent } from "../auth/delete-account.component";
|
||||||
@@ -65,9 +64,7 @@ import { FolderAddEditComponent } from "../vault/app/vault/folder-add-edit.compo
|
|||||||
import { SettingsComponent } from "./accounts/settings.component";
|
import { SettingsComponent } from "./accounts/settings.component";
|
||||||
import { ExportDesktopComponent } from "./tools/export/export-desktop.component";
|
import { ExportDesktopComponent } from "./tools/export/export-desktop.component";
|
||||||
import { CredentialGeneratorComponent } from "./tools/generator/credential-generator.component";
|
import { CredentialGeneratorComponent } from "./tools/generator/credential-generator.component";
|
||||||
import { GeneratorComponent } from "./tools/generator.component";
|
|
||||||
import { ImportDesktopComponent } from "./tools/import/import-desktop.component";
|
import { ImportDesktopComponent } from "./tools/import/import-desktop.component";
|
||||||
import { PasswordGeneratorHistoryComponent } from "./tools/password-generator-history.component";
|
|
||||||
|
|
||||||
const BroadcasterSubscriptionId = "AppComponent";
|
const BroadcasterSubscriptionId = "AppComponent";
|
||||||
const IdleTimeout = 60000 * 10; // 10 minutes
|
const IdleTimeout = 60000 * 10; // 10 minutes
|
||||||
@@ -126,7 +123,6 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
private broadcasterService: BroadcasterService,
|
private broadcasterService: BroadcasterService,
|
||||||
private folderService: InternalFolderService,
|
private folderService: InternalFolderService,
|
||||||
private syncService: SyncService,
|
private syncService: SyncService,
|
||||||
private passwordGenerationService: PasswordGenerationServiceAbstraction,
|
|
||||||
private cipherService: CipherService,
|
private cipherService: CipherService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
@@ -508,41 +504,13 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async openGenerator() {
|
async openGenerator() {
|
||||||
const isGeneratorSwapEnabled = await this.configService.getFeatureFlag(
|
await this.dialogService.open(CredentialGeneratorComponent);
|
||||||
FeatureFlag.GeneratorToolsModernization,
|
return;
|
||||||
);
|
|
||||||
if (isGeneratorSwapEnabled) {
|
|
||||||
await this.dialogService.open(CredentialGeneratorComponent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.modalService.closeAll();
|
|
||||||
|
|
||||||
[this.modal] = await this.modalService.openViewRef(
|
|
||||||
GeneratorComponent,
|
|
||||||
this.generatorModalRef,
|
|
||||||
(comp) => (comp.comingFromAddEdit = false),
|
|
||||||
);
|
|
||||||
|
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
|
||||||
this.modal.onClosed.subscribe(() => {
|
|
||||||
this.modal = null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async openGeneratorHistory() {
|
async openGeneratorHistory() {
|
||||||
const isGeneratorSwapEnabled = await this.configService.getFeatureFlag(
|
await this.dialogService.open(CredentialGeneratorHistoryDialogComponent);
|
||||||
FeatureFlag.GeneratorToolsModernization,
|
return;
|
||||||
);
|
|
||||||
if (isGeneratorSwapEnabled) {
|
|
||||||
await this.dialogService.open(CredentialGeneratorHistoryDialogComponent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.openModal<PasswordGeneratorHistoryComponent>(
|
|
||||||
PasswordGeneratorHistoryComponent,
|
|
||||||
this.passwordHistoryRef,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async updateAppMenu() {
|
private async updateAppMenu() {
|
||||||
|
|||||||
@@ -47,8 +47,6 @@ import { HeaderComponent } from "./layout/header.component";
|
|||||||
import { NavComponent } from "./layout/nav.component";
|
import { NavComponent } from "./layout/nav.component";
|
||||||
import { SearchComponent } from "./layout/search/search.component";
|
import { SearchComponent } from "./layout/search/search.component";
|
||||||
import { SharedModule } from "./shared/shared.module";
|
import { SharedModule } from "./shared/shared.module";
|
||||||
import { GeneratorComponent } from "./tools/generator.component";
|
|
||||||
import { PasswordGeneratorHistoryComponent } from "./tools/password-generator-history.component";
|
|
||||||
import { AddEditComponent as SendAddEditComponent } from "./tools/send/add-edit.component";
|
import { AddEditComponent as SendAddEditComponent } from "./tools/send/add-edit.component";
|
||||||
import { SendComponent } from "./tools/send/send.component";
|
import { SendComponent } from "./tools/send/send.component";
|
||||||
|
|
||||||
@@ -80,8 +78,6 @@ import { SendComponent } from "./tools/send/send.component";
|
|||||||
HeaderComponent,
|
HeaderComponent,
|
||||||
HintComponent,
|
HintComponent,
|
||||||
NavComponent,
|
NavComponent,
|
||||||
GeneratorComponent,
|
|
||||||
PasswordGeneratorHistoryComponent,
|
|
||||||
PasswordHistoryComponent,
|
PasswordHistoryComponent,
|
||||||
PremiumComponent,
|
PremiumComponent,
|
||||||
RegisterComponent,
|
RegisterComponent,
|
||||||
|
|||||||
@@ -1,636 +0,0 @@
|
|||||||
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="generatorTitle">
|
|
||||||
<div class="modal-dialog modal-md" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-body">
|
|
||||||
<h1 class="modal-title" id="generatorTitle">
|
|
||||||
{{ "generator" | i18n }}
|
|
||||||
</h1>
|
|
||||||
<bit-callout
|
|
||||||
type="info"
|
|
||||||
*ngIf="enforcedPasswordPolicyOptions?.inEffect() && type === 'password'"
|
|
||||||
>
|
|
||||||
{{ "passwordGeneratorPolicyInEffect" | i18n }}
|
|
||||||
</bit-callout>
|
|
||||||
<div class="generated-block" *ngIf="type === 'password'">
|
|
||||||
<div
|
|
||||||
class="generated-wrapper"
|
|
||||||
[innerHTML]="password | colorPassword"
|
|
||||||
[appCopyText]="password"
|
|
||||||
></div>
|
|
||||||
<div class="action-buttons">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="icon-btn primary"
|
|
||||||
appStopClick
|
|
||||||
appA11yTitle="{{ 'copyPassword' | i18n }}"
|
|
||||||
(click)="copy()"
|
|
||||||
>
|
|
||||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="icon-btn primary"
|
|
||||||
appStopClick
|
|
||||||
appA11yTitle="{{ 'regeneratePassword' | i18n }}"
|
|
||||||
(click)="regenerate()"
|
|
||||||
>
|
|
||||||
<i class="bwi bwi-lg bwi-generate" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="generated-block" *ngIf="type === 'username'">
|
|
||||||
<div
|
|
||||||
class="generated-wrapper"
|
|
||||||
[innerHTML]="username | colorPassword"
|
|
||||||
[appCopyText]="username"
|
|
||||||
></div>
|
|
||||||
<div class="action-buttons" #form [appApiAction]="usernameGeneratingPromise">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="icon-btn primary"
|
|
||||||
appStopClick
|
|
||||||
appA11yTitle="{{ 'copyUsername' | i18n }}"
|
|
||||||
(click)="copy()"
|
|
||||||
>
|
|
||||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="icon-btn primary"
|
|
||||||
appStopClick
|
|
||||||
appA11yTitle="{{ 'regenerateUsername' | i18n }}"
|
|
||||||
(click)="$any(form).loading ? false : regenerate()"
|
|
||||||
[attr.aria-disabled]="$any(form).loading ? 'true' : null"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="bwi bwi-lg bwi-generate"
|
|
||||||
[ngClass]="$any(form).loading ? 'bwi-spin' : ''"
|
|
||||||
aria-hidden="true"
|
|
||||||
></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box" *ngIf="!comingFromAddEdit">
|
|
||||||
<div class="box-content condensed">
|
|
||||||
<div
|
|
||||||
class="box-content-row box-content-row-radio"
|
|
||||||
role="radiogroup"
|
|
||||||
aria-labelledby="typeHeading"
|
|
||||||
>
|
|
||||||
<label id="typeHeading" class="radio-header">{{
|
|
||||||
"whatWouldYouLikeToGenerate" | i18n
|
|
||||||
}}</label>
|
|
||||||
<div
|
|
||||||
class="radio-group text-default"
|
|
||||||
appBoxRow
|
|
||||||
name="TypeOptions"
|
|
||||||
*ngFor="let o of typeOptions"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
class="radio"
|
|
||||||
[(ngModel)]="type"
|
|
||||||
name="Type"
|
|
||||||
id="type_{{ o.value }}"
|
|
||||||
[value]="o.value"
|
|
||||||
(change)="typeChanged()"
|
|
||||||
[checked]="type === o.value"
|
|
||||||
/>
|
|
||||||
<label class="unstyled" for="type_{{ o.value }}">
|
|
||||||
{{ o.name }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<ng-container *ngIf="type === 'password'">
|
|
||||||
<div class="box">
|
|
||||||
<h2 class="box-header">
|
|
||||||
<button type="button" (click)="toggleOptions()" [attr.aria-expanded]="showOptions">
|
|
||||||
<i
|
|
||||||
class="bwi bwi-lg"
|
|
||||||
aria-hidden="true"
|
|
||||||
[ngClass]="{ 'bwi-angle-right': !showOptions, 'bwi-angle-down': showOptions }"
|
|
||||||
></i>
|
|
||||||
{{ "options" | i18n }}
|
|
||||||
</button>
|
|
||||||
</h2>
|
|
||||||
<div class="box-content condensed" [hidden]="!showOptions">
|
|
||||||
<div
|
|
||||||
class="box-content-row box-content-row-radio"
|
|
||||||
role="radiogroup"
|
|
||||||
aria-labelledby="passwordTypeHeading"
|
|
||||||
>
|
|
||||||
<label id="passwordTypeHeading" class="radio-header">{{
|
|
||||||
"passwordType" | i18n
|
|
||||||
}}</label>
|
|
||||||
<div
|
|
||||||
class="radio-group text-default"
|
|
||||||
appBoxRow
|
|
||||||
name="PassTypeOptions"
|
|
||||||
*ngFor="let o of passTypeOptions"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
class="radio"
|
|
||||||
[(ngModel)]="passwordOptions.type"
|
|
||||||
name="PasswordType"
|
|
||||||
id="passwordType_{{ o.value }}"
|
|
||||||
[value]="o.value"
|
|
||||||
(change)="savePasswordOptions()"
|
|
||||||
[checked]="passwordOptions.type === o.value"
|
|
||||||
/>
|
|
||||||
<label class="unstyled" for="passwordType_{{ o.value }}">
|
|
||||||
{{ o.name }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box" [hidden]="!showOptions" *ngIf="passwordOptions.type === 'passphrase'">
|
|
||||||
<div class="box-content condensed">
|
|
||||||
<div class="box-content-row box-content-row-input" appBoxRow>
|
|
||||||
<label for="num-words">{{ "numWords" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="num-words"
|
|
||||||
type="number"
|
|
||||||
min="3"
|
|
||||||
max="20"
|
|
||||||
(change)="savePasswordOptions()"
|
|
||||||
[(ngModel)]="passwordOptions.numWords"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row box-content-row-input" appBoxRow>
|
|
||||||
<label for="word-separator">{{ "wordSeparator" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="word-separator"
|
|
||||||
type="text"
|
|
||||||
maxlength="1"
|
|
||||||
(input)="savePasswordOptions()"
|
|
||||||
[(ngModel)]="passwordOptions.wordSeparator"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="capitalize">{{ "capitalize" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="capitalize"
|
|
||||||
type="checkbox"
|
|
||||||
(change)="savePasswordOptions()"
|
|
||||||
[(ngModel)]="passwordOptions.capitalize"
|
|
||||||
[disabled]="enforcedPasswordPolicyOptions?.capitalize"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="include-number">{{ "includeNumber" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="include-number"
|
|
||||||
type="checkbox"
|
|
||||||
(change)="savePasswordOptions()"
|
|
||||||
[(ngModel)]="passwordOptions.includeNumber"
|
|
||||||
[disabled]="enforcedPasswordPolicyOptions?.includeNumber"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<ng-container *ngIf="passwordOptions.type === 'password'">
|
|
||||||
<div class="box" [hidden]="!showOptions">
|
|
||||||
<div class="box-content condensed">
|
|
||||||
<div class="box-content-row box-content-row-slider" appBoxRow>
|
|
||||||
<label for="length">{{ "length" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="length"
|
|
||||||
type="number"
|
|
||||||
[min]="passwordOptions.minLength"
|
|
||||||
max="128"
|
|
||||||
[(ngModel)]="passwordOptions.length"
|
|
||||||
(blur)="savePasswordOptions()"
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
id="lengthRange"
|
|
||||||
type="range"
|
|
||||||
[min]="passwordOptions.minLength"
|
|
||||||
max="128"
|
|
||||||
step="1"
|
|
||||||
[(ngModel)]="passwordOptions.length"
|
|
||||||
(change)="sliderChanged()"
|
|
||||||
(input)="sliderInput()"
|
|
||||||
attr.aria-label="{{ 'length' | i18n }}"
|
|
||||||
tabindex="-1"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<span>{{ "passwordMinLength" | i18n }}</span>
|
|
||||||
<span class="txt-right">{{ passwordOptions.minLength }}</span>
|
|
||||||
<span
|
|
||||||
class="sr-only"
|
|
||||||
attr.aria-label="{{ 'passwordMinLength' | i18n }}"
|
|
||||||
role="status"
|
|
||||||
aria-live="polite"
|
|
||||||
>
|
|
||||||
{{ passwordOptionsMinLengthForReader$ | async }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="uppercase">A-Z</label>
|
|
||||||
<input
|
|
||||||
id="uppercase"
|
|
||||||
type="checkbox"
|
|
||||||
(change)="savePasswordOptions()"
|
|
||||||
[disabled]="enforcedPasswordPolicyOptions?.useUppercase"
|
|
||||||
[(ngModel)]="passwordOptions.uppercase"
|
|
||||||
attr.aria-label="{{ 'uppercase' | i18n }}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="lowercase">a-z</label>
|
|
||||||
<input
|
|
||||||
id="lowercase"
|
|
||||||
type="checkbox"
|
|
||||||
(change)="savePasswordOptions()"
|
|
||||||
[disabled]="enforcedPasswordPolicyOptions?.useLowercase"
|
|
||||||
[(ngModel)]="passwordOptions.lowercase"
|
|
||||||
attr.aria-label="{{ 'lowercase' | i18n }}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="numbers">0-9</label>
|
|
||||||
<input
|
|
||||||
id="numbers"
|
|
||||||
type="checkbox"
|
|
||||||
(change)="savePasswordOptions()"
|
|
||||||
[disabled]="enforcedPasswordPolicyOptions?.useNumbers"
|
|
||||||
[ngModel]="passwordOptions.number"
|
|
||||||
(ngModelChange)="setPasswordOptionsNumber($event)"
|
|
||||||
attr.aria-label="{{ 'numbers' | i18n }}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="special">!@#$%^&*</label>
|
|
||||||
<input
|
|
||||||
id="special"
|
|
||||||
type="checkbox"
|
|
||||||
(change)="savePasswordOptions()"
|
|
||||||
[disabled]="enforcedPasswordPolicyOptions?.useSpecial"
|
|
||||||
[ngModel]="passwordOptions.special"
|
|
||||||
(ngModelChange)="setPasswordOptionsSpecial($event)"
|
|
||||||
attr.aria-label="{{ 'specialCharacters' | i18n }}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box" [hidden]="!showOptions">
|
|
||||||
<div class="box-content condensed">
|
|
||||||
<div class="box-content-row box-content-row-input" appBoxRow>
|
|
||||||
<label for="min-number">{{ "minNumbers" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="min-number"
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
max="9"
|
|
||||||
(change)="savePasswordOptions()"
|
|
||||||
[(ngModel)]="passwordOptions.minNumber"
|
|
||||||
(input)="onPasswordOptionsMinNumberInput($event)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row box-content-row-input" appBoxRow>
|
|
||||||
<label for="min-special">{{ "minSpecial" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="min-special"
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
max="9"
|
|
||||||
(change)="savePasswordOptions()"
|
|
||||||
[(ngModel)]="passwordOptions.minSpecial"
|
|
||||||
(input)="onPasswordOptionsMinSpecialInput($event)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="ambiguous">{{ "ambiguous" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="ambiguous"
|
|
||||||
type="checkbox"
|
|
||||||
(change)="savePasswordOptions()"
|
|
||||||
[(ngModel)]="avoidAmbiguous"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="type === 'username'">
|
|
||||||
<div class="box">
|
|
||||||
<h2 class="box-header">
|
|
||||||
<button type="button" (click)="toggleOptions()" [attr.aria-expanded]="showOptions">
|
|
||||||
<i
|
|
||||||
class="bwi bwi-lg"
|
|
||||||
aria-hidden="true"
|
|
||||||
[ngClass]="{ 'bwi-angle-right': !showOptions, 'bwi-angle-down': showOptions }"
|
|
||||||
></i>
|
|
||||||
{{ "options" | i18n }}
|
|
||||||
</button>
|
|
||||||
</h2>
|
|
||||||
<div class="box-content condensed" [hidden]="!showOptions">
|
|
||||||
<div
|
|
||||||
class="box-content-row box-content-row-radio"
|
|
||||||
role="radiogroup"
|
|
||||||
aria-labelledby="usernameTypeHeading"
|
|
||||||
>
|
|
||||||
<label id="usernameTypeHeading" class="radio-header">
|
|
||||||
{{ "usernameType" | i18n }}
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
appStopClick
|
|
||||||
(click)="usernameTypesLearnMore()"
|
|
||||||
appA11yTitle="{{ 'learnMore' | i18n }}"
|
|
||||||
>
|
|
||||||
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
|
|
||||||
</a>
|
|
||||||
</label>
|
|
||||||
<div
|
|
||||||
class="radio-group align-start text-default"
|
|
||||||
appBoxRow
|
|
||||||
name="UsernameTypeOptions"
|
|
||||||
*ngFor="let o of usernameTypeOptions"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
class="radio"
|
|
||||||
[(ngModel)]="usernameOptions.type"
|
|
||||||
name="UsernameType"
|
|
||||||
id="usernameType_{{ o.value }}"
|
|
||||||
[value]="o.value"
|
|
||||||
(change)="saveUsernameOptions()"
|
|
||||||
[checked]="usernameOptions.type === o.value"
|
|
||||||
/>
|
|
||||||
<label class="unstyled" for="usernameType_{{ o.value }}">
|
|
||||||
{{ o.name }}
|
|
||||||
<small class="help-block" *ngIf="o.desc">{{ o.desc }}</small>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box" *ngIf="usernameOptions.type === 'forwarded'" [hidden]="!showOptions">
|
|
||||||
<div class="box-content condensed">
|
|
||||||
<div class="box-content-row" role="listbox" aria-labelledby="forwardTypeHeading">
|
|
||||||
<label id="forwardTypeHeading">{{ "service" | i18n }}</label>
|
|
||||||
<select
|
|
||||||
id="ForwardTypeDropdown"
|
|
||||||
name="ForwardType"
|
|
||||||
[(ngModel)]="usernameOptions.forwardedService"
|
|
||||||
(change)="saveUsernameOptions()"
|
|
||||||
>
|
|
||||||
<option *ngFor="let o of forwardOptions" [ngValue]="o.value" role="option">
|
|
||||||
{{ o.name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<ng-container *ngIf="usernameOptions.forwardedService === 'simplelogin'">
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="simplelogin-apikey">{{ "apiKey" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="simplelogin-apikey"
|
|
||||||
type="password"
|
|
||||||
name="SimpleLoginApiKey"
|
|
||||||
[(ngModel)]="usernameOptions.forwardedSimpleLoginApiKey"
|
|
||||||
(blur)="saveUsernameOptions()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="simplelogin-baseUrl">{{ "baseUrl" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="simplelogin-baseUrl"
|
|
||||||
type="text"
|
|
||||||
name="SimpleLoginDomain"
|
|
||||||
[(ngModel)]="usernameOptions.forwardedSimpleLoginBaseUrl"
|
|
||||||
(blur)="saveUsernameOptions()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="usernameOptions.forwardedService === 'duckduckgo'">
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="duckduckgo-apikey">{{ "apiKey" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="duckduckgo-apikey"
|
|
||||||
type="password"
|
|
||||||
name="DuckDuckGoApiKey"
|
|
||||||
[(ngModel)]="usernameOptions.forwardedDuckDuckGoToken"
|
|
||||||
(blur)="saveUsernameOptions()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="usernameOptions.forwardedService === 'anonaddy'">
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="anonaddy-accessToken">{{ "apiAccessToken" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="anonaddy-accessToken"
|
|
||||||
type="password"
|
|
||||||
name="AnonAddyAccessToken"
|
|
||||||
[(ngModel)]="usernameOptions.forwardedAnonAddyApiToken"
|
|
||||||
(blur)="saveUsernameOptions()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="anonaddy-domain">{{ "aliasDomain" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="anonaddy-domain"
|
|
||||||
type="text"
|
|
||||||
name="AnonAddyDomain"
|
|
||||||
[(ngModel)]="usernameOptions.forwardedAnonAddyDomain"
|
|
||||||
(blur)="saveUsernameOptions()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="anonaddy-baseUrl">{{ "baseUrl" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="anonaddy-baseUrl"
|
|
||||||
type="text"
|
|
||||||
name="AnonAddyDomain"
|
|
||||||
[(ngModel)]="usernameOptions.forwardedAnonAddyBaseUrl"
|
|
||||||
(blur)="saveUsernameOptions()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="usernameOptions.forwardedService === 'firefoxrelay'">
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="firefox-apikey">{{ "apiAccessToken" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="firefox-apikey"
|
|
||||||
type="password"
|
|
||||||
name="FirefoxApiKey"
|
|
||||||
[(ngModel)]="usernameOptions.forwardedFirefoxApiToken"
|
|
||||||
(blur)="saveUsernameOptions()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="usernameOptions.forwardedService === 'fastmail'">
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="fastmail-apiToken">{{ "apiAccessToken" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="fastmail-apiToken"
|
|
||||||
type="password"
|
|
||||||
name="FastmailApiToken"
|
|
||||||
[(ngModel)]="usernameOptions.forwardedFastmailApiToken"
|
|
||||||
(blur)="saveUsernameOptions()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container *ngIf="usernameOptions.forwardedService === 'forwardemail'">
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="forwardemail-accessToken">{{ "apiAccessToken" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="forwardemail-accessToken"
|
|
||||||
type="password"
|
|
||||||
name="ForwardEmailAccessToken"
|
|
||||||
[(ngModel)]="usernameOptions.forwardedForwardEmailApiToken"
|
|
||||||
(blur)="saveUsernameOptions()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="forwardemail-domain">{{ "aliasDomain" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="forwardemail-domain"
|
|
||||||
type="text"
|
|
||||||
name="ForwardEmailDomain"
|
|
||||||
[(ngModel)]="usernameOptions.forwardedForwardEmailDomain"
|
|
||||||
(blur)="saveUsernameOptions()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box" *ngIf="usernameOptions.type === 'subaddress'" [hidden]="!showOptions">
|
|
||||||
<div class="box-content condensed">
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="subaddress-email">{{ "emailAddress" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="subaddress-email"
|
|
||||||
type="text"
|
|
||||||
name="SubaddressEmail"
|
|
||||||
[(ngModel)]="usernameOptions.subaddressEmail"
|
|
||||||
(blur)="saveUsernameOptions()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="box-content-row"
|
|
||||||
role="radiogroup"
|
|
||||||
aria-labelledby="subaddressTypeHeading"
|
|
||||||
*ngIf="subaddressOptions.length > 1"
|
|
||||||
>
|
|
||||||
<label id="subaddressTypeHeading" class="radio-header">{{ "type" | i18n }}</label>
|
|
||||||
<div class="radio-group text-default" appBoxRow *ngFor="let o of subaddressOptions">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
[(ngModel)]="usernameOptions.subaddressType"
|
|
||||||
name="SubaddressType"
|
|
||||||
id="subaddresstype_{{ o.value }}"
|
|
||||||
[value]="o.value"
|
|
||||||
(change)="saveUsernameOptions()"
|
|
||||||
[checked]="usernameOptions.subaddressType === o.value"
|
|
||||||
/>
|
|
||||||
<label for="subaddresstype_{{ o.value }}">
|
|
||||||
{{ o.name }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row" appBoxRow *ngIf="usernameWebsite">
|
|
||||||
<label for="subaddress-website">{{ "website" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="subaddress-website"
|
|
||||||
type="text"
|
|
||||||
name="SubaddressWebsite"
|
|
||||||
[value]="usernameOptions.website"
|
|
||||||
disabled
|
|
||||||
readonly
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box" *ngIf="usernameOptions.type === 'catchall'" [hidden]="!showOptions">
|
|
||||||
<div class="box-content condensed">
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="catchall-domain">{{ "domainName" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="catchall-domain"
|
|
||||||
type="text"
|
|
||||||
name="CatchallDomain"
|
|
||||||
[(ngModel)]="usernameOptions.catchallDomain"
|
|
||||||
(blur)="saveUsernameOptions()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="box-content-row"
|
|
||||||
role="radiogroup"
|
|
||||||
aria-labelledby="catchallTypeHeading"
|
|
||||||
*ngIf="catchallOptions.length > 1"
|
|
||||||
>
|
|
||||||
<label id="catchallTypeHeading" class="radio-header">{{ "type" | i18n }}</label>
|
|
||||||
<div class="radio-group text-default" appBoxRow *ngFor="let o of catchallOptions">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
[(ngModel)]="usernameOptions.catchallType"
|
|
||||||
name="CatchallType"
|
|
||||||
id="catchalltype_{{ o.value }}"
|
|
||||||
[value]="o.value"
|
|
||||||
(change)="saveUsernameOptions()"
|
|
||||||
[checked]="usernameOptions.catchallType === o.value"
|
|
||||||
/>
|
|
||||||
<label for="catchalltype_{{ o.value }}">
|
|
||||||
{{ o.name }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row" appBoxRow *ngIf="usernameWebsite">
|
|
||||||
<label for="catchall-website">{{ "website" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="catchall-website"
|
|
||||||
type="text"
|
|
||||||
name="CatchallWebsite"
|
|
||||||
[value]="usernameOptions.website"
|
|
||||||
disabled
|
|
||||||
readonly
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box" *ngIf="usernameOptions.type === 'word'" [hidden]="!showOptions">
|
|
||||||
<div class="box-content condensed">
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="capitalize">{{ "capitalize" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="capitalize"
|
|
||||||
type="checkbox"
|
|
||||||
(change)="saveUsernameOptions()"
|
|
||||||
[(ngModel)]="usernameOptions.wordCapitalize"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="include-number">{{ "includeNumber" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="include-number"
|
|
||||||
type="checkbox"
|
|
||||||
(change)="saveUsernameOptions()"
|
|
||||||
[(ngModel)]="usernameOptions.wordIncludeNumber"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="primary"
|
|
||||||
*ngIf="comingFromAddEdit"
|
|
||||||
(click)="select()"
|
|
||||||
appA11yTitle="{{ 'select' | i18n }}"
|
|
||||||
>
|
|
||||||
<i class="bwi bwi-lg bwi-fw bwi-check" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
<button type="button" data-dismiss="modal">
|
|
||||||
{{ (comingFromAddEdit ? "cancel" : "close") | i18n }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
import { NO_ERRORS_SCHEMA } from "@angular/core";
|
|
||||||
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
|
||||||
import { ActivatedRoute } from "@angular/router";
|
|
||||||
import { mock, MockProxy } from "jest-mock-extended";
|
|
||||||
|
|
||||||
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
|
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
|
||||||
import { ToastService } from "@bitwarden/components";
|
|
||||||
import {
|
|
||||||
PasswordGenerationServiceAbstraction,
|
|
||||||
UsernameGenerationServiceAbstraction,
|
|
||||||
} from "@bitwarden/generator-legacy";
|
|
||||||
|
|
||||||
import { GeneratorComponent } from "./generator.component";
|
|
||||||
|
|
||||||
describe("GeneratorComponent", () => {
|
|
||||||
let component: GeneratorComponent;
|
|
||||||
let fixture: ComponentFixture<GeneratorComponent>;
|
|
||||||
let platformUtilsServiceMock: MockProxy<PlatformUtilsService>;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
platformUtilsServiceMock = mock<PlatformUtilsService>();
|
|
||||||
|
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [GeneratorComponent, I18nPipe],
|
|
||||||
providers: [
|
|
||||||
{
|
|
||||||
provide: PasswordGenerationServiceAbstraction,
|
|
||||||
useValue: mock<PasswordGenerationServiceAbstraction>(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: UsernameGenerationServiceAbstraction,
|
|
||||||
useValue: mock<UsernameGenerationServiceAbstraction>(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: PlatformUtilsService,
|
|
||||||
useValue: platformUtilsServiceMock,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: I18nService,
|
|
||||||
useValue: mock<I18nService>(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: ActivatedRoute,
|
|
||||||
useValue: mock<ActivatedRoute>(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: LogService,
|
|
||||||
useValue: mock<LogService>(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: CipherService,
|
|
||||||
useValue: mock<CipherService>(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: AccountService,
|
|
||||||
useValue: mock<AccountService>(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: ToastService,
|
|
||||||
useValue: mock<ToastService>(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
schemas: [NO_ERRORS_SCHEMA],
|
|
||||||
}).compileComponents();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(GeneratorComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should create", () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("usernameTypesLearnMore()", () => {
|
|
||||||
it("should call platformUtilsService.launchUri() once", () => {
|
|
||||||
component.usernameTypesLearnMore();
|
|
||||||
expect(platformUtilsServiceMock.launchUri).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
import { Component, NgZone } from "@angular/core";
|
|
||||||
import { ActivatedRoute } from "@angular/router";
|
|
||||||
|
|
||||||
import { GeneratorComponent as BaseGeneratorComponent } from "@bitwarden/angular/tools/generator/components/generator.component";
|
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
|
||||||
import { ToastService } from "@bitwarden/components";
|
|
||||||
import {
|
|
||||||
PasswordGenerationServiceAbstraction,
|
|
||||||
UsernameGenerationServiceAbstraction,
|
|
||||||
} from "@bitwarden/generator-legacy";
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: "app-generator",
|
|
||||||
templateUrl: "generator.component.html",
|
|
||||||
})
|
|
||||||
export class GeneratorComponent extends BaseGeneratorComponent {
|
|
||||||
constructor(
|
|
||||||
passwordGenerationService: PasswordGenerationServiceAbstraction,
|
|
||||||
usernameGenerationService: UsernameGenerationServiceAbstraction,
|
|
||||||
accountService: AccountService,
|
|
||||||
platformUtilsService: PlatformUtilsService,
|
|
||||||
i18nService: I18nService,
|
|
||||||
route: ActivatedRoute,
|
|
||||||
ngZone: NgZone,
|
|
||||||
logService: LogService,
|
|
||||||
toastService: ToastService,
|
|
||||||
) {
|
|
||||||
super(
|
|
||||||
passwordGenerationService,
|
|
||||||
usernameGenerationService,
|
|
||||||
platformUtilsService,
|
|
||||||
accountService,
|
|
||||||
i18nService,
|
|
||||||
logService,
|
|
||||||
route,
|
|
||||||
ngZone,
|
|
||||||
window,
|
|
||||||
toastService,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
usernameTypesLearnMore() {
|
|
||||||
this.platformUtilsService.launchUri("https://bitwarden.com/help/generator/#username-types");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="passwordGenHistoryTitle">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-body">
|
|
||||||
<div class="box">
|
|
||||||
<h1 class="box-header" id="passwordGenHistoryTitle">
|
|
||||||
{{ "passwordHistory" | i18n }}
|
|
||||||
</h1>
|
|
||||||
<div class="box-content condensed">
|
|
||||||
<div class="box-content-row box-content-row-flex" *ngFor="let h of history">
|
|
||||||
<div class="row-main">
|
|
||||||
<div
|
|
||||||
class="password-wrapper monospaced"
|
|
||||||
[appCopyText]="h.password"
|
|
||||||
[innerHTML]="h.password | colorPassword"
|
|
||||||
></div>
|
|
||||||
<span class="detail">{{ h.date | date: "medium" }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="action-buttons">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="row-btn"
|
|
||||||
appStopClick
|
|
||||||
appA11yTitle="{{ 'copyPassword' | i18n }}"
|
|
||||||
(click)="copy(h.password)"
|
|
||||||
>
|
|
||||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box-content-row" *ngIf="!history.length">
|
|
||||||
{{ "noPasswordsInList" | i18n }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" data-dismiss="modal">{{ "close" | i18n }}</button>
|
|
||||||
<div class="right">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
(click)="clear()"
|
|
||||||
class="danger"
|
|
||||||
appA11yTitle="{{ 'clear' | i18n }}"
|
|
||||||
>
|
|
||||||
<i class="bwi bwi-trash bwi-lg bwi-fw" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import { Component } from "@angular/core";
|
|
||||||
|
|
||||||
import { PasswordGeneratorHistoryComponent as BasePasswordGeneratorHistoryComponent } from "@bitwarden/angular/tools/generator/components/password-generator-history.component";
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
|
||||||
import { ToastService } from "@bitwarden/components";
|
|
||||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: "app-password-generator-history",
|
|
||||||
templateUrl: "password-generator-history.component.html",
|
|
||||||
})
|
|
||||||
export class PasswordGeneratorHistoryComponent extends BasePasswordGeneratorHistoryComponent {
|
|
||||||
constructor(
|
|
||||||
passwordGenerationService: PasswordGenerationServiceAbstraction,
|
|
||||||
platformUtilsService: PlatformUtilsService,
|
|
||||||
i18nService: I18nService,
|
|
||||||
toastService: ToastService,
|
|
||||||
) {
|
|
||||||
super(passwordGenerationService, platformUtilsService, i18nService, window, toastService);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -188,44 +188,6 @@ p.lead {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.generated-block {
|
|
||||||
font-size: $font-size-large;
|
|
||||||
font-family: $font-family-monospace;
|
|
||||||
padding: 8px 10px 8px 0;
|
|
||||||
display: flex;
|
|
||||||
border-radius: $border-radius;
|
|
||||||
border: 1px solid;
|
|
||||||
|
|
||||||
@include themify($themes) {
|
|
||||||
background-color: transparent;
|
|
||||||
border-color: themed("borderColorAlt");
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-body & {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.generated-wrapper {
|
|
||||||
text-align: left;
|
|
||||||
width: 100%;
|
|
||||||
min-width: 0;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
word-break: break-all;
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-buttons {
|
|
||||||
display: flex;
|
|
||||||
align-self: center;
|
|
||||||
height: 100%;
|
|
||||||
margin-left: 10px;
|
|
||||||
|
|
||||||
button {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.password-wrapper {
|
.password-wrapper {
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
|||||||
@@ -39,8 +39,8 @@
|
|||||||
(onCancelled)="cancelledAddEdit($event)"
|
(onCancelled)="cancelledAddEdit($event)"
|
||||||
(onShareCipher)="shareCipher($event)"
|
(onShareCipher)="shareCipher($event)"
|
||||||
(onEditCollections)="cipherCollections($event)"
|
(onEditCollections)="cipherCollections($event)"
|
||||||
(onGeneratePassword)="openGenerator(true, true)"
|
(onGeneratePassword)="openGenerator(true)"
|
||||||
(onGenerateUsername)="openGenerator(true, false)"
|
(onGenerateUsername)="openGenerator(false)"
|
||||||
>
|
>
|
||||||
</app-vault-add-edit>
|
</app-vault-add-edit>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import { EventCollectionService } from "@bitwarden/common/abstractions/event/eve
|
|||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
|
||||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@@ -39,7 +38,6 @@ import { DialogService, ToastService } from "@bitwarden/components";
|
|||||||
import { DecryptionFailureDialogComponent, PasswordRepromptService } from "@bitwarden/vault";
|
import { DecryptionFailureDialogComponent, PasswordRepromptService } from "@bitwarden/vault";
|
||||||
|
|
||||||
import { SearchBarService } from "../../../app/layout/search/search-bar.service";
|
import { SearchBarService } from "../../../app/layout/search/search-bar.service";
|
||||||
import { GeneratorComponent } from "../../../app/tools/generator.component";
|
|
||||||
import { invokeMenu, RendererMenuItem } from "../../../utils";
|
import { invokeMenu, RendererMenuItem } from "../../../utils";
|
||||||
|
|
||||||
import { AddEditComponent } from "./add-edit.component";
|
import { AddEditComponent } from "./add-edit.component";
|
||||||
@@ -666,65 +664,21 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
return "searchVault";
|
return "searchVault";
|
||||||
}
|
}
|
||||||
|
|
||||||
async openGenerator(comingFromAddEdit: boolean, passwordType = true) {
|
async openGenerator(passwordType = true) {
|
||||||
const isGeneratorSwapEnabled = await this.configService.getFeatureFlag(
|
CredentialGeneratorDialogComponent.open(this.dialogService, {
|
||||||
FeatureFlag.GeneratorToolsModernization,
|
onCredentialGenerated: (value?: string) => {
|
||||||
);
|
if (this.addEditComponent != null) {
|
||||||
|
this.addEditComponent.markPasswordAsDirty();
|
||||||
if (isGeneratorSwapEnabled) {
|
if (passwordType) {
|
||||||
CredentialGeneratorDialogComponent.open(this.dialogService, {
|
this.addEditComponent.cipher.login.password = value ?? "";
|
||||||
onCredentialGenerated: (value?: string) => {
|
} else {
|
||||||
if (this.addEditComponent != null) {
|
this.addEditComponent.cipher.login.username = value ?? "";
|
||||||
this.addEditComponent.markPasswordAsDirty();
|
|
||||||
if (passwordType) {
|
|
||||||
this.addEditComponent.cipher.login.password = value ?? "";
|
|
||||||
} else {
|
|
||||||
this.addEditComponent.cipher.login.username = value ?? "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
type: passwordType ? "password" : "username",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Legacy code below, remove once the new generator is fully implemented
|
|
||||||
// https://bitwarden.atlassian.net/browse/PM-7121
|
|
||||||
const cipher = this.addEditComponent?.cipher;
|
|
||||||
const loginType = cipher != null && cipher.type === CipherType.Login && cipher.login != null;
|
|
||||||
|
|
||||||
const [modal, childComponent] = await this.modalService.openViewRef(
|
|
||||||
GeneratorComponent,
|
|
||||||
this.generatorModalRef,
|
|
||||||
(comp) => {
|
|
||||||
comp.comingFromAddEdit = comingFromAddEdit;
|
|
||||||
if (comingFromAddEdit) {
|
|
||||||
comp.type = passwordType ? "password" : "username";
|
|
||||||
if (loginType && cipher.login.hasUris && cipher.login.uris[0].hostname != null) {
|
|
||||||
comp.usernameWebsite = cipher.login.uris[0].hostname;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
type: passwordType ? "password" : "username",
|
||||||
this.modal = modal;
|
|
||||||
|
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
|
||||||
childComponent.onSelected.subscribe((value: string) => {
|
|
||||||
this.modal.close();
|
|
||||||
if (loginType) {
|
|
||||||
this.addEditComponent.markPasswordAsDirty();
|
|
||||||
if (passwordType) {
|
|
||||||
this.addEditComponent.cipher.login.password = value;
|
|
||||||
} else {
|
|
||||||
this.addEditComponent.cipher.login.username = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
|
||||||
this.modal.onClosed.subscribe(() => {
|
|
||||||
this.modal = null;
|
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
async addFolder() {
|
async addFolder() {
|
||||||
|
|||||||
Reference in New Issue
Block a user