mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-22 16:29:09 +01:00
password generator
This commit is contained in:
parent
82f3c39167
commit
58f920821d
@ -1085,5 +1085,8 @@
|
||||
},
|
||||
"allItems": {
|
||||
"message": "All Items"
|
||||
},
|
||||
"noPasswordsInList": {
|
||||
"message": "There are no passwords to list."
|
||||
}
|
||||
}
|
||||
|
@ -103,4 +103,10 @@ export const routerTransition = trigger('routerTransition', [
|
||||
|
||||
transition('tabs => add-cipher, ciphers => add-cipher', inSlideUp),
|
||||
transition('add-cipher => tabs, add-cipher => ciphers', outSlideDown),
|
||||
|
||||
transition('generator => generator-history', inSlideLeft),
|
||||
transition('generator-history => generator', outSlideRight),
|
||||
|
||||
transition('add-cipher => generator, edit-cipher => generator, tabs => generator', inSlideUp),
|
||||
transition('generator => add-cipher, generator => edit-cipher, generator => tabs', outSlideDown),
|
||||
]);
|
||||
|
@ -14,7 +14,11 @@ import { LoginComponent } from './accounts/login.component';
|
||||
import { RegisterComponent } from './accounts/register.component';
|
||||
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
|
||||
import { TwoFactorComponent } from './accounts/two-factor.component';
|
||||
import { SettingsComponent } from './settings/settings.component';
|
||||
import { TabsComponent } from './tabs.component';
|
||||
import { PasswordGeneratorComponent } from './tools/password-generator.component';
|
||||
import { PasswordGeneratorHistoryComponent } from './tools/password-generator-history.component';
|
||||
import { ToolsComponent } from './tools/tools.component';
|
||||
import { AddEditComponent } from './vault/add-edit.component';
|
||||
import { CiphersComponent } from './vault/ciphers.component';
|
||||
import { CurrentTabComponent } from './vault/current-tab.component';
|
||||
@ -36,6 +40,8 @@ const routes: Routes = [
|
||||
{ path: 'view-cipher', component: ViewComponent, data: { state: 'view-cipher' } },
|
||||
{ path: 'add-cipher', component: AddEditComponent, data: { state: 'add-cipher' } },
|
||||
{ path: 'edit-cipher', component: AddEditComponent, data: { state: 'edit-cipher' } },
|
||||
{ path: 'generator', component: PasswordGeneratorComponent, data: { state: 'generator' } },
|
||||
{ path: 'generator-history', component: PasswordGeneratorHistoryComponent, data: { state: 'generator-history' } },
|
||||
{
|
||||
path: 'tabs', component: TabsComponent,
|
||||
data: { state: 'tabs' },
|
||||
@ -52,7 +58,19 @@ const routes: Routes = [
|
||||
component: GroupingsComponent,
|
||||
canActivate: [AuthGuardService],
|
||||
data: { state: 'tabs_vault' },
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'tools',
|
||||
component: ToolsComponent,
|
||||
canActivate: [AuthGuardService],
|
||||
data: { state: 'tabs_tools' },
|
||||
},
|
||||
{
|
||||
path: 'settings',
|
||||
component: SettingsComponent,
|
||||
canActivate: [AuthGuardService],
|
||||
data: { state: 'tabs_settings' },
|
||||
},
|
||||
]
|
||||
}
|
||||
];
|
||||
|
@ -92,6 +92,9 @@ export class AppComponent implements OnInit {
|
||||
this.stateService.remove('GroupingsComponent');
|
||||
this.stateService.remove('CiphersComponent');
|
||||
}
|
||||
if (url.startsWith('/tabs/')) {
|
||||
this.stateService.remove('addEditCipher');
|
||||
}
|
||||
this.previousUrl = url;
|
||||
}
|
||||
});
|
||||
|
@ -23,7 +23,11 @@ import { LoginComponent } from './accounts/login.component';
|
||||
import { RegisterComponent } from './accounts/register.component';
|
||||
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
|
||||
import { TwoFactorComponent } from './accounts/two-factor.component';
|
||||
import { SettingsComponent } from './settings/settings.component';
|
||||
import { TabsComponent } from './tabs.component';
|
||||
import { PasswordGeneratorComponent } from './tools/password-generator.component';
|
||||
import { PasswordGeneratorHistoryComponent } from './tools/password-generator-history.component';
|
||||
import { ToolsComponent } from './tools/tools.component';
|
||||
import { AddEditComponent } from './vault/add-edit.component';
|
||||
import { CiphersComponent } from './vault/ciphers.component';
|
||||
import { CurrentTabComponent } from './vault/current-tab.component';
|
||||
@ -81,12 +85,16 @@ import { IconComponent } from 'jslib/angular/components/icon.component';
|
||||
IconComponent,
|
||||
LockComponent,
|
||||
LoginComponent,
|
||||
PasswordGeneratorComponent,
|
||||
PasswordGeneratorHistoryComponent,
|
||||
PopOutComponent,
|
||||
RegisterComponent,
|
||||
SearchCiphersPipe,
|
||||
SettingsComponent,
|
||||
StopClickDirective,
|
||||
StopPropDirective,
|
||||
TabsComponent,
|
||||
ToolsComponent,
|
||||
TwoFactorOptionsComponent,
|
||||
TwoFactorComponent,
|
||||
ViewComponent,
|
||||
|
16
src/popup2/settings/settings.component.html
Normal file
16
src/popup2/settings/settings.component.html
Normal file
@ -0,0 +1,16 @@
|
||||
<header>
|
||||
<div class="left">
|
||||
<app-pop-out></app-pop-out>
|
||||
</div>
|
||||
<div class="center">
|
||||
<span class="title">{{'settings' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right"></div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box list">
|
||||
<div class="box-content">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
7
src/popup2/settings/settings.component.ts
Normal file
7
src/popup2/settings/settings.component.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings',
|
||||
templateUrl: 'settings.component.html',
|
||||
})
|
||||
export class SettingsComponent { }
|
39
src/popup2/tools/password-generator-history.component.html
Normal file
39
src/popup2/tools/password-generator-history.component.html
Normal file
@ -0,0 +1,39 @@
|
||||
<header>
|
||||
<div class="left">
|
||||
<button appBlurClick type="button" (click)="close()">
|
||||
<i class="fa fa-chevron-left"></i>
|
||||
<span>{{'back' | i18n}}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="center">
|
||||
<span class="title">{{'passwordHistory' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button appBlurClick type="button" (click)="clear()">
|
||||
{{'clear' | i18n}}
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box list full-list" *ngIf="history && history.length">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-flex" *ngFor="let h of history">
|
||||
<div class="row-main">
|
||||
<span class="text monospaced no-ellipsis">
|
||||
{{h.password}}
|
||||
</span>
|
||||
<span class="detail">{{h.date | date:'medium'}}</span>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick title="{{'copyPassword' | i18n}}"
|
||||
(click)="copy(h.password)">
|
||||
<i class="fa fa-lg fa-clipboard"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="no-items" *ngIf="!history || !history.length">
|
||||
<p>{{'noPasswordsInList' | i18n}}</p>
|
||||
</div>
|
||||
</content>
|
29
src/popup2/tools/password-generator-history.component.ts
Normal file
29
src/popup2/tools/password-generator-history.component.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { ToasterService } from 'angular2-toaster';
|
||||
import { Angulartics2 } from 'angulartics2';
|
||||
|
||||
import { Location } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
|
||||
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||
|
||||
import {
|
||||
PasswordGeneratorHistoryComponent as BasePasswordGeneratorHistoryComponent
|
||||
} from 'jslib/angular/components/password-generator-history.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-password-generator-history',
|
||||
templateUrl: 'password-generator-history.component.html',
|
||||
})
|
||||
export class PasswordGeneratorHistoryComponent extends BasePasswordGeneratorHistoryComponent {
|
||||
constructor(passwordGenerationService: PasswordGenerationService, analytics: Angulartics2,
|
||||
platformUtilsService: PlatformUtilsService, i18nService: I18nService,
|
||||
toasterService: ToasterService, private location: Location) {
|
||||
super(passwordGenerationService, analytics, platformUtilsService, i18nService, toasterService);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.location.back();
|
||||
}
|
||||
}
|
79
src/popup2/tools/password-generator.component.html
Normal file
79
src/popup2/tools/password-generator.component.html
Normal file
@ -0,0 +1,79 @@
|
||||
<header>
|
||||
<div class="left">
|
||||
<button type="button" appBlurClick (click)="close()">{{'close' | i18n}}</button>
|
||||
</div>
|
||||
<div class="center">
|
||||
<span class="title">{{'passGen' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button type="button" appBlurClick (click)="select()" *ngIf="showSelect">{{'select' | i18n}}</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="password-block">{{password}}</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<a class="box-content-row" href="#" appStopClick appBlurClick
|
||||
(click)="regenerate()">{{'regeneratePassword' | i18n}}</a>
|
||||
<a class="box-content-row" href="#" appStopClick appBlurClick
|
||||
(click)="copy()">{{'copyPassword' | i18n}}</a>
|
||||
<a class="box-content-row box-content-row-flex" routerLink="/generator-history">
|
||||
<div class="row-main">{{'passwordHistory' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right row-sub-icon"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
{{'options' | i18n}}
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-slider" appBoxRow>
|
||||
<label for="length">{{'length' | i18n}}</label>
|
||||
<input id="length" type="number" min="5" max="128" [(ngModel)]="options.length"
|
||||
(input)="saveOptions()">
|
||||
<input id="lengthRange" type="range" min="5" max="128" step="1"
|
||||
[(ngModel)]="options.length" (change)="sliderChanged()" (input)="sliderInput()">
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="uppercase">A-Z</label>
|
||||
<input id="uppercase" type="checkbox" (change)="saveOptions()"
|
||||
[(ngModel)]="options.uppercase">
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="lowercase">a-z</label>
|
||||
<input id="lowercase" type="checkbox" (change)="saveOptions()"
|
||||
[(ngModel)]="options.lowercase">
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="numbers">0-9</label>
|
||||
<input id="numbers" type="checkbox" (change)="saveOptions()"
|
||||
[(ngModel)]="options.number">
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="special">!@#$%^&*</label>
|
||||
<input id="special" type="checkbox" (change)="saveOptions()"
|
||||
[(ngModel)]="options.special">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<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" (input)="saveOptions()"
|
||||
[(ngModel)]="options.minNumber">
|
||||
</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" (input)="saveOptions()"
|
||||
[(ngModel)]="options.minSpecial">
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="ambiguous">{{'avoidAmbChar' | i18n}}</label>
|
||||
<input id="ambiguous" type="checkbox" (change)="saveOptions()"
|
||||
[(ngModel)]="avoidAmbiguous">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
52
src/popup2/tools/password-generator.component.ts
Normal file
52
src/popup2/tools/password-generator.component.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { ToasterService } from 'angular2-toaster';
|
||||
import { Angulartics2 } from 'angulartics2';
|
||||
|
||||
import { Location } from '@angular/common';
|
||||
import {
|
||||
Component,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
Router,
|
||||
} from '@angular/router';
|
||||
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
|
||||
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||
import { StateService } from 'jslib/abstractions/state.service';
|
||||
|
||||
import { CipherView } from 'jslib/models/view/cipherView';
|
||||
|
||||
import {
|
||||
PasswordGeneratorComponent as BasePasswordGeneratorComponent
|
||||
} from 'jslib/angular/components/password-generator.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-password-generator',
|
||||
templateUrl: 'password-generator.component.html',
|
||||
})
|
||||
export class PasswordGeneratorComponent extends BasePasswordGeneratorComponent {
|
||||
private cipherState: CipherView;
|
||||
|
||||
constructor(passwordGenerationService: PasswordGenerationService, analytics: Angulartics2,
|
||||
platformUtilsService: PlatformUtilsService, i18nService: I18nService,
|
||||
toasterService: ToasterService, private stateService: StateService,
|
||||
private router: Router, private location: Location) {
|
||||
super(passwordGenerationService, analytics, platformUtilsService, i18nService, toasterService);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
await super.ngOnInit();
|
||||
this.cipherState = await this.stateService.get<CipherView>('addEditCipher');
|
||||
super.showSelect = this.cipherState != null;
|
||||
}
|
||||
|
||||
select() {
|
||||
super.select();
|
||||
this.cipherState.login.password = this.password;
|
||||
this.close();
|
||||
}
|
||||
|
||||
close() {
|
||||
this.location.back();
|
||||
}
|
||||
}
|
19
src/popup2/tools/tools.component.html
Normal file
19
src/popup2/tools/tools.component.html
Normal file
@ -0,0 +1,19 @@
|
||||
<header>
|
||||
<div class="left">
|
||||
<app-pop-out></app-pop-out>
|
||||
</div>
|
||||
<div class="center">
|
||||
<span class="title">{{'tools' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right"></div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box list">
|
||||
<div class="box-content">
|
||||
<a routerLink="/generator" class="box-content-row box-content-row-flex text-default">
|
||||
<div class="row-main">{{'passGen' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right row-sub-icon"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
7
src/popup2/tools/tools.component.ts
Normal file
7
src/popup2/tools/tools.component.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tools',
|
||||
templateUrl: 'tools.component.html',
|
||||
})
|
||||
export class ToolsComponent { }
|
@ -16,6 +16,7 @@ import { CipherService } from 'jslib/abstractions/cipher.service';
|
||||
import { FolderService } from 'jslib/abstractions/folder.service';
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||
import { StateService } from 'jslib/abstractions/state.service';
|
||||
|
||||
import { AddEditComponent as BaseAddEditComponent } from 'jslib/angular/components/add-edit.component';
|
||||
|
||||
@ -27,10 +28,11 @@ export class AddEditComponent extends BaseAddEditComponent implements OnInit {
|
||||
constructor(cipherService: CipherService, folderService: FolderService,
|
||||
i18nService: I18nService, platformUtilsService: PlatformUtilsService,
|
||||
analytics: Angulartics2, toasterService: ToasterService,
|
||||
auditService: AuditService, private route: ActivatedRoute,
|
||||
private router: Router, private location: Location) {
|
||||
auditService: AuditService, stateService: StateService,
|
||||
private route: ActivatedRoute, private router: Router,
|
||||
private location: Location) {
|
||||
super(cipherService, folderService, i18nService, platformUtilsService, analytics,
|
||||
toasterService, auditService);
|
||||
toasterService, auditService, stateService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@ -56,4 +58,10 @@ export class AddEditComponent extends BaseAddEditComponent implements OnInit {
|
||||
super.cancel();
|
||||
this.location.back();
|
||||
}
|
||||
|
||||
async generatePassword() {
|
||||
await super.generatePassword();
|
||||
this.stateService.save('addEditCipher', this.cipher);
|
||||
this.router.navigate(['generator']);
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +125,7 @@
|
||||
<div class="no-items" *ngIf="!searchedCiphers.length">
|
||||
<p>{{'noItemsInList' | i18n}}</p>
|
||||
</div>
|
||||
<div class="box list only-list" *ngIf="searchedCiphers.length > 0">
|
||||
<div class="box list full-list" *ngIf="searchedCiphers.length > 0">
|
||||
<div class="box-content">
|
||||
<app-ciphers-list [ciphers]="searchedCiphers" title="{{'viewItem' | i18n}}"
|
||||
(onSelected)="selectCipher($event)"></app-ciphers-list>
|
||||
|
@ -368,7 +368,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.text, .detail {
|
||||
.text:not(.no-ellipsis), .detail {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@ -391,4 +391,12 @@
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.full-list {
|
||||
margin: 0;
|
||||
|
||||
.box-content {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,3 +97,11 @@ app-root > #loading {
|
||||
width: 100%;
|
||||
color: $text-muted;
|
||||
}
|
||||
|
||||
app-password-generator .password-block {
|
||||
font-size: $font-size-large;
|
||||
word-break: break-all;
|
||||
font-family: $font-family-monospace;
|
||||
text-align: center;
|
||||
margin: 20px;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user