mirror of
https://github.com/bitwarden/browser
synced 2025-12-23 11:43:46 +00:00
Merge branch 'master' into patrickhlauke-issue1987
This commit is contained in:
@@ -2,16 +2,16 @@
|
||||
<header>
|
||||
<div class="left"></div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{(pinLock ? 'verifyPin' : 'verifyMasterPassword') | i18n}}</span>
|
||||
<span class="title">{{'verifyIdentity' | i18n}}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick>{{'unlock' | i18n}}</button>
|
||||
<button type="submit" appBlurClick *ngIf="!hideInput">{{'unlock' | i18n}}</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow *ngIf="!hideInput">
|
||||
<div class="row-main" *ngIf="pinLock">
|
||||
<label for="pin">{{'pin' | i18n}}</label>
|
||||
<input id="pin" type="{{showPassword ? 'text' : 'password'}}" name="PIN" class="monospaced"
|
||||
@@ -32,13 +32,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<p>{{(pinLock ? 'yourVaultIsLockedPinCode' : 'yourVaultIsLocked') | i18n}}</p>
|
||||
<p>{{'yourVaultIsLocked' | i18n}}</p>
|
||||
{{'loggedInAsOn' | i18n : email : webVaultHostname}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box" *ngIf="biometricLock">
|
||||
<div class="box-footer">
|
||||
<button type="button" class="btn primary block" (click)="unlockBiometric()" appStopClick>{{'unlockWithBiometrics' | i18n}}</button>
|
||||
<button type="button" class="btn primary block" (click)="unlockBiometric()"
|
||||
appStopClick>{{'unlockWithBiometrics' | i18n}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-center">
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
NgZone,
|
||||
} from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import Swal from 'sweetalert2';
|
||||
|
||||
@@ -8,6 +11,7 @@ import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { KeyConnectorService } from 'jslib-common/abstractions/keyConnector.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
@@ -30,9 +34,11 @@ export class LockComponent extends BaseLockComponent {
|
||||
userService: UserService, cryptoService: CryptoService,
|
||||
storageService: StorageService, vaultTimeoutService: VaultTimeoutService,
|
||||
environmentService: EnvironmentService, stateService: StateService,
|
||||
apiService: ApiService, logService: LogService) {
|
||||
apiService: ApiService, logService: LogService, keyConnectorService: KeyConnectorService,
|
||||
ngZone: NgZone) {
|
||||
super(router, i18nService, platformUtilsService, messagingService, userService, cryptoService,
|
||||
storageService, vaultTimeoutService, environmentService, stateService, apiService, logService);
|
||||
storageService, vaultTimeoutService, environmentService, stateService, apiService, logService,
|
||||
keyConnectorService, ngZone);
|
||||
this.successRoute = '/tabs/current';
|
||||
this.isInitialLockScreen = (window as any).previousPopupUrl == null;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
NgZone,
|
||||
} from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { AuthService } from 'jslib-common/abstractions/auth.service';
|
||||
@@ -24,9 +27,9 @@ export class LoginComponent extends BaseLoginComponent {
|
||||
protected stateService: StateService, protected environmentService: EnvironmentService,
|
||||
protected passwordGenerationService: PasswordGenerationService,
|
||||
protected cryptoFunctionService: CryptoFunctionService, storageService: StorageService,
|
||||
syncService: SyncService, logService: LogService) {
|
||||
syncService: SyncService, logService: LogService, ngZone: NgZone) {
|
||||
super(authService, router, platformUtilsService, i18nService, stateService, environmentService,
|
||||
passwordGenerationService, cryptoFunctionService, storageService, logService);
|
||||
passwordGenerationService, cryptoFunctionService, storageService, logService, ngZone);
|
||||
super.onSuccessfulLogin = async () => {
|
||||
await syncService.fullSync(true);
|
||||
};
|
||||
|
||||
29
src/popup/accounts/remove-password.component.html
Normal file
29
src/popup/accounts/remove-password.component.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<header>
|
||||
<div class="left"></div>
|
||||
<div class="center">
|
||||
<span class="title">{{'removeMasterPassword' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right"></div>
|
||||
</header>
|
||||
|
||||
<content>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<p>{{'convertOrganizationEncryptionDesc' | i18n : organization.name}}</p>
|
||||
</div>
|
||||
<div class="box-content-row">
|
||||
<button type="button" class="btn block primary" (click)="convert()" [disabled]="actionPromise">
|
||||
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true" *ngIf="continuing"></i>
|
||||
{{'removeMasterPassword' | i18n}}
|
||||
</button>
|
||||
</div>
|
||||
<div class="box-content-row">
|
||||
<button type="button" class="btn btn-outline-secondary block" (click)="leave()" [disabled]="actionPromise">
|
||||
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true" *ngIf="leaving"></i>
|
||||
{{'leaveOrganization' | i18n}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
10
src/popup/accounts/remove-password.component.ts
Normal file
10
src/popup/accounts/remove-password.component.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { RemovePasswordComponent as BaseRemovePasswordComponent } from 'jslib-angular/components/remove-password.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-remove-password',
|
||||
templateUrl: 'remove-password.component.html',
|
||||
})
|
||||
export class RemovePasswordComponent extends BaseRemovePasswordComponent {
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
|
||||
|
||||
import { SsoComponent as BaseSsoComponent } from 'jslib-angular/components/sso.component';
|
||||
import { BrowserApi } from '../../browser/browserApi';
|
||||
@@ -30,7 +31,8 @@ export class SsoComponent extends BaseSsoComponent {
|
||||
storageService: StorageService, stateService: StateService,
|
||||
platformUtilsService: PlatformUtilsService, apiService: ApiService,
|
||||
cryptoFunctionService: CryptoFunctionService, passwordGenerationService: PasswordGenerationService,
|
||||
syncService: SyncService, environmentService: EnvironmentService, logService: LogService) {
|
||||
syncService: SyncService, environmentService: EnvironmentService, logService: LogService,
|
||||
private vaultTimeoutService: VaultTimeoutService) {
|
||||
super(authService, router, i18nService, route, storageService, stateService, platformUtilsService,
|
||||
apiService, cryptoFunctionService, environmentService, passwordGenerationService, logService);
|
||||
|
||||
@@ -41,7 +43,11 @@ export class SsoComponent extends BaseSsoComponent {
|
||||
|
||||
super.onSuccessfulLogin = async () => {
|
||||
await syncService.fullSync(true);
|
||||
BrowserApi.reloadOpenWindows();
|
||||
if (await this.vaultTimeoutService.isLocked()) {
|
||||
// If the vault is unlocked then this will clear keys from memory, which we don't want to do
|
||||
BrowserApi.reloadOpenWindows();
|
||||
}
|
||||
|
||||
const thisWindow = window.open('', '_self');
|
||||
thisWindow.close();
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@ import { TwoFactorProviderType } from 'jslib-common/enums/twoFactorProviderType'
|
||||
|
||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { AuthService } from 'jslib-common/abstractions/auth.service';
|
||||
import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service';
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
@@ -18,8 +19,6 @@ import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
|
||||
import { TwoFactorComponent as BaseTwoFactorComponent } from 'jslib-angular/components/two-factor.component';
|
||||
|
||||
import { PopupUtilsService } from '../services/popup-utils.service';
|
||||
|
||||
@@ -7,10 +7,10 @@ import {
|
||||
} from '@angular/router';
|
||||
|
||||
import { AuthGuardService } from 'jslib-angular/services/auth-guard.service';
|
||||
import { LockGuardService } from 'jslib-angular/services/lock-guard.service';
|
||||
|
||||
import { DebounceNavigationService } from './services/debounceNavigationService';
|
||||
import { LaunchGuardService } from './services/launch-guard.service';
|
||||
import { LockGuardService } from './services/lock-guard.service';
|
||||
|
||||
import { EnvironmentComponent } from './accounts/environment.component';
|
||||
import { HintComponent } from './accounts/hint.component';
|
||||
@@ -18,6 +18,7 @@ import { HomeComponent } from './accounts/home.component';
|
||||
import { LockComponent } from './accounts/lock.component';
|
||||
import { LoginComponent } from './accounts/login.component';
|
||||
import { RegisterComponent } from './accounts/register.component';
|
||||
import { RemovePasswordComponent } from './accounts/remove-password.component';
|
||||
import { SetPasswordComponent } from './accounts/set-password.component';
|
||||
import { SsoComponent } from './accounts/sso.component';
|
||||
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
|
||||
@@ -105,6 +106,12 @@ const routes: Routes = [
|
||||
component: SetPasswordComponent,
|
||||
data: { state: 'set-password' },
|
||||
},
|
||||
{
|
||||
path: 'remove-password',
|
||||
component: RemovePasswordComponent,
|
||||
canActivate: [AuthGuardService],
|
||||
data: { state: 'remove-password' },
|
||||
},
|
||||
{
|
||||
path: 'register',
|
||||
component: RegisterComponent,
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
import { BrowserApi } from '../browser/browserApi';
|
||||
|
||||
import {
|
||||
BodyOutputType,
|
||||
Toast,
|
||||
ToasterConfig,
|
||||
ToasterService,
|
||||
} from 'angular2-toaster';
|
||||
import Swal, { SweetAlertIcon } from 'sweetalert2/src/sweetalert2.js';
|
||||
|
||||
import {
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
@@ -21,11 +11,17 @@ import {
|
||||
Router,
|
||||
RouterOutlet,
|
||||
} from '@angular/router';
|
||||
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
import {
|
||||
IndividualConfig,
|
||||
ToastrService,
|
||||
} from 'ngx-toastr';
|
||||
import Swal, { SweetAlertIcon } from 'sweetalert2/src/sweetalert2.js';
|
||||
import { BrowserApi } from '../browser/browserApi';
|
||||
|
||||
import { AuthService } from 'jslib-common/abstractions/auth.service';
|
||||
import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { KeyConnectorService } from 'jslib-common/abstractions/keyConnector.service';
|
||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
@@ -33,7 +29,6 @@ import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
|
||||
import BrowserPlatformUtilsService from 'src/services/browserPlatformUtils.service';
|
||||
import { routerTransition } from './app-routing.animations';
|
||||
|
||||
@Component({
|
||||
@@ -41,29 +36,21 @@ import { routerTransition } from './app-routing.animations';
|
||||
styles: [],
|
||||
animations: [routerTransition],
|
||||
template: `
|
||||
<toaster-container [toasterconfig]="toasterConfig" aria-live="polite"></toaster-container>
|
||||
<main [@routerTransition]="getState(o)">
|
||||
<router-outlet #o="outlet"></router-outlet>
|
||||
</main>`,
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
toasterConfig: ToasterConfig = new ToasterConfig({
|
||||
showCloseButton: false,
|
||||
mouseoverTimerStop: true,
|
||||
animation: 'slideUp',
|
||||
limit: 2,
|
||||
positionClass: 'toast-bottom-full-width',
|
||||
newestOnTop: false,
|
||||
});
|
||||
|
||||
private lastActivity: number = null;
|
||||
|
||||
constructor(private toasterService: ToasterService, private storageService: StorageService,
|
||||
constructor(private toastrService: ToastrService, private storageService: StorageService,
|
||||
private broadcasterService: BroadcasterService, private authService: AuthService,
|
||||
private i18nService: I18nService, private router: Router,
|
||||
private stateService: StateService, private messagingService: MessagingService,
|
||||
private changeDetectorRef: ChangeDetectorRef, private ngZone: NgZone,
|
||||
private sanitizer: DomSanitizer, private platformUtilsService: PlatformUtilsService) { }
|
||||
private sanitizer: DomSanitizer, private platformUtilsService: PlatformUtilsService,
|
||||
private keyConnectoService: KeyConnectorService) { }
|
||||
|
||||
ngOnInit() {
|
||||
if (BrowserApi.getBackgroundPage() == null) {
|
||||
@@ -121,6 +108,11 @@ export class AppComponent implements OnInit {
|
||||
this.ngZone.run(() => {
|
||||
this.router.navigate(['/']);
|
||||
});
|
||||
} else if (msg.command === 'convertAccountToKeyConnector') {
|
||||
this.ngZone.run(async () => {
|
||||
await this.keyConnectoService.setConvertAccountRequired(true);
|
||||
this.router.navigate(['/remove-password']);
|
||||
});
|
||||
} else {
|
||||
msg.webExtSender = sender;
|
||||
this.broadcasterService.send(msg);
|
||||
@@ -178,30 +170,29 @@ export class AppComponent implements OnInit {
|
||||
}
|
||||
|
||||
private showToast(msg: any) {
|
||||
const toast: Toast = {
|
||||
type: msg.type,
|
||||
title: msg.title,
|
||||
};
|
||||
let message = '';
|
||||
|
||||
const options: Partial<IndividualConfig> = {};
|
||||
|
||||
if (typeof (msg.text) === 'string') {
|
||||
toast.body = msg.text;
|
||||
message = msg.text;
|
||||
} else if (msg.text.length === 1) {
|
||||
toast.body = msg.text[0];
|
||||
message = msg.text[0];
|
||||
} else {
|
||||
let message = '';
|
||||
msg.text.forEach((t: string) =>
|
||||
message += ('<p>' + this.sanitizer.sanitize(SecurityContext.HTML, t) + '</p>'));
|
||||
toast.body = message;
|
||||
toast.bodyOutputType = BodyOutputType.TrustedHtml;
|
||||
options.enableHtml = true;
|
||||
}
|
||||
if (msg.options != null) {
|
||||
if (msg.options.trustedHtml === true) {
|
||||
toast.bodyOutputType = BodyOutputType.TrustedHtml;
|
||||
options.enableHtml = true;
|
||||
}
|
||||
if (msg.options.timeout != null && msg.options.timeout > 0) {
|
||||
toast.timeout = msg.options.timeout;
|
||||
options.timeOut = msg.options.timeout;
|
||||
}
|
||||
}
|
||||
this.toasterService.popAsync(toast);
|
||||
|
||||
this.toastrService.show(message, msg.title, options, 'toast-' + msg.type);
|
||||
}
|
||||
|
||||
private async showDialog(msg: any) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { A11yModule } from '@angular/cdk/a11y';
|
||||
import { DragDropModule } from '@angular/cdk/drag-drop';
|
||||
import { ScrollingModule } from '@angular/cdk/scrolling';
|
||||
import { ToasterModule } from 'angular2-toaster';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { ServicesModule } from './services/services.module';
|
||||
@@ -17,6 +16,7 @@ import { HomeComponent } from './accounts/home.component';
|
||||
import { LockComponent } from './accounts/lock.component';
|
||||
import { LoginComponent } from './accounts/login.component';
|
||||
import { RegisterComponent } from './accounts/register.component';
|
||||
import { RemovePasswordComponent } from './accounts/remove-password.component';
|
||||
import { SetPasswordComponent } from './accounts/set-password.component';
|
||||
import { SsoComponent } from './accounts/sso.component';
|
||||
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
|
||||
@@ -80,9 +80,11 @@ import { PasswordRepromptComponent } from './components/password-reprompt.compon
|
||||
import { PopOutComponent } from './components/pop-out.component';
|
||||
import { SendListComponent } from './components/send-list.component';
|
||||
import { SetPinComponent } from './components/set-pin.component';
|
||||
import { VerifyMasterPasswordComponent } from './components/verify-master-password.component';
|
||||
|
||||
import { CalloutComponent } from 'jslib-angular/components/callout.component';
|
||||
import { IconComponent } from 'jslib-angular/components/icon.component';
|
||||
import { BitwardenToastModule } from 'jslib-angular/components/toastr.component';
|
||||
|
||||
import {
|
||||
CurrencyPipe,
|
||||
@@ -186,12 +188,18 @@ registerLocaleData(localeZhTw, 'zh-TW');
|
||||
ReactiveFormsModule,
|
||||
ScrollingModule,
|
||||
ServicesModule,
|
||||
ToasterModule.forRoot(),
|
||||
BitwardenToastModule.forRoot({
|
||||
maxOpened: 2,
|
||||
autoDismiss: true,
|
||||
closeButton: true,
|
||||
positionClass: 'toast-bottom-full-width',
|
||||
}),
|
||||
],
|
||||
declarations: [
|
||||
A11yTitleDirective,
|
||||
ActionButtonsComponent,
|
||||
AddEditComponent,
|
||||
AddEditCustomFieldsComponent,
|
||||
ApiActionDirective,
|
||||
AppComponent,
|
||||
AttachmentsComponent,
|
||||
@@ -212,8 +220,8 @@ registerLocaleData(localeZhTw, 'zh-TW');
|
||||
FolderAddEditComponent,
|
||||
FoldersComponent,
|
||||
GroupingsComponent,
|
||||
HomeComponent,
|
||||
HintComponent,
|
||||
HomeComponent,
|
||||
I18nPipe,
|
||||
IconComponent,
|
||||
InputVerbatimDirective,
|
||||
@@ -223,6 +231,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
|
||||
PasswordGeneratorComponent,
|
||||
PasswordGeneratorHistoryComponent,
|
||||
PasswordHistoryComponent,
|
||||
PasswordRepromptComponent,
|
||||
PopOutComponent,
|
||||
PremiumComponent,
|
||||
PrivateModeComponent,
|
||||
@@ -235,6 +244,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
|
||||
SendListComponent,
|
||||
SendTypeComponent,
|
||||
SetPasswordComponent,
|
||||
SetPinComponent,
|
||||
SettingsComponent,
|
||||
ShareComponent,
|
||||
SsoComponent,
|
||||
@@ -243,15 +253,14 @@ registerLocaleData(localeZhTw, 'zh-TW');
|
||||
SyncComponent,
|
||||
TabsComponent,
|
||||
TrueFalseValueDirective,
|
||||
TwoFactorOptionsComponent,
|
||||
TwoFactorComponent,
|
||||
TwoFactorOptionsComponent,
|
||||
UpdateTempPasswordComponent,
|
||||
ViewComponent,
|
||||
PasswordRepromptComponent,
|
||||
SetPinComponent,
|
||||
VaultTimeoutInputComponent,
|
||||
AddEditCustomFieldsComponent,
|
||||
VerifyMasterPasswordComponent,
|
||||
ViewComponent,
|
||||
ViewCustomFieldsComponent,
|
||||
RemovePasswordComponent,
|
||||
],
|
||||
entryComponents: [],
|
||||
providers: [
|
||||
|
||||
@@ -5,8 +5,6 @@ import {
|
||||
Output,
|
||||
} from '@angular/core';
|
||||
|
||||
import { ToasterService } from 'angular2-toaster';
|
||||
|
||||
import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType';
|
||||
import { CipherType } from 'jslib-common/enums/cipherType';
|
||||
import { EventType } from 'jslib-common/enums/eventType';
|
||||
@@ -33,7 +31,7 @@ export class ActionButtonsComponent {
|
||||
cipherType = CipherType;
|
||||
userHasPremiumAccess = false;
|
||||
|
||||
constructor(private toasterService: ToasterService, private i18nService: I18nService,
|
||||
constructor(private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService, private eventService: EventService,
|
||||
private totpService: TotpService, private userService: UserService,
|
||||
private passwordRepromptService: PasswordRepromptService) { }
|
||||
@@ -63,7 +61,7 @@ export class ActionButtonsComponent {
|
||||
}
|
||||
|
||||
this.platformUtilsService.copyToClipboard(value, { window: window });
|
||||
this.toasterService.popAsync('info', null,
|
||||
this.platformUtilsService.showToast('info', null,
|
||||
this.i18nService.t('valueCopied', this.i18nService.t(typeI18nKey)));
|
||||
|
||||
if (typeI18nKey === 'password' || typeI18nKey === 'verificationCodeTotp') {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<div class="checkbox" *ngIf="showMasterPassOnRestart">
|
||||
<label for="masterPasswordOnRestart">
|
||||
<input type="checkbox" id="masterPasswordOnRestart" name="MasterPasswordOnRestart"
|
||||
[(ngModel)]="masterPassOnRestart">
|
||||
|
||||
25
src/popup/components/verify-master-password.component.html
Normal file
25
src/popup/components/verify-master-password.component.html
Normal file
@@ -0,0 +1,25 @@
|
||||
<ng-container *ngIf="!usesKeyConnector">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="masterPassword">{{'masterPass' | i18n}}</label>
|
||||
<input id="masterPassword" type="password" name="MasterPasswordHash" class="form-control"
|
||||
[formControl]="secret" required appAutofocus appInputVerbatim>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="usesKeyConnector">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label class="d-block">{{'sendVerificationCode' | i18n}}</label>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="requestOTP()" [disabled]="disableRequestOTP">
|
||||
{{'sendCode' | i18n}}
|
||||
</button>
|
||||
<span class="ml-2 text-success" role="alert" @sent *ngIf="sentCode">
|
||||
<i class="fa fa-check-circle-o" aria-hidden="true"></i>
|
||||
{{'codeSent' | i18n}}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="verificationCode">{{'verificationCode' | i18n}}</label>
|
||||
<input id="verificationCode" type="input" name="verificationCode" class="form-control"
|
||||
[formControl]="secret" required appAutofocus appInputVerbatim>
|
||||
</div>
|
||||
</ng-container>
|
||||
31
src/popup/components/verify-master-password.component.ts
Normal file
31
src/popup/components/verify-master-password.component.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import {
|
||||
animate,
|
||||
style,
|
||||
transition,
|
||||
trigger,
|
||||
} from '@angular/animations';
|
||||
import { Component } from '@angular/core';
|
||||
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { VerifyMasterPasswordComponent as BaseComponent } from 'jslib-angular/components/verify-master-password.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-verify-master-password',
|
||||
templateUrl: 'verify-master-password.component.html',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
multi: true,
|
||||
useExisting: VerifyMasterPasswordComponent,
|
||||
},
|
||||
],
|
||||
animations: [
|
||||
trigger('sent', [
|
||||
transition(':enter', [
|
||||
style({ opacity: 0 }),
|
||||
animate('100ms', style({ opacity: 1 })),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
})
|
||||
export class VerifyMasterPasswordComponent extends BaseComponent { }
|
||||
@@ -347,6 +347,22 @@ app-root {
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 601px) {
|
||||
app-login header {
|
||||
padding: 0 calc((100% - 500px) / 2);
|
||||
}
|
||||
|
||||
app-login content {
|
||||
padding: 0 calc((100% - 500px) / 2);
|
||||
}
|
||||
|
||||
app-two-factor header {
|
||||
padding: 0 calc((100% - 500px) / 2);
|
||||
}
|
||||
|
||||
app-two-factor content {
|
||||
padding: 0 calc((100% - 500px) / 2);
|
||||
}
|
||||
|
||||
app-lock header {
|
||||
padding: 0 calc((100% - 500px) / 2);
|
||||
}
|
||||
|
||||
@@ -531,6 +531,10 @@
|
||||
color: themed('mutedColor');
|
||||
}
|
||||
|
||||
&.icon-small {
|
||||
min-width: 25px;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: $border-radius;
|
||||
max-height: 20px;
|
||||
|
||||
@@ -146,7 +146,7 @@ p.lead {
|
||||
}
|
||||
|
||||
.password-wrapper {
|
||||
word-break: break-all;
|
||||
overflow-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
min-width: 0;
|
||||
}
|
||||
@@ -360,14 +360,6 @@ input[type="password"]::-ms-reveal {
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for rendering error in Firefox sidebar
|
||||
// option elements will not render background-color correctly if identical to parent background-color
|
||||
select option {
|
||||
@include themify($themes) {
|
||||
background-color: darken(themed('inputBackgroundColor'), +1);
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for slow performance on external monitors on Chrome + MacOS
|
||||
// See: https://bugs.chromium.org/p/chromium/issues/detail?id=971701#c64
|
||||
@keyframes redraw {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
$fa-font-path: "~font-awesome/fonts";
|
||||
@import "~font-awesome/scss/font-awesome.scss";
|
||||
@import "~angular2-toaster/toaster";
|
||||
@import '~ngx-toastr/toastr';
|
||||
@import "~sweetalert2/src/sweetalert2.scss";
|
||||
|
||||
@import "variables.scss";
|
||||
@@ -9,32 +9,36 @@ $fa-font-path: "~font-awesome/fonts";
|
||||
// Toaster
|
||||
|
||||
.toast-container {
|
||||
&.toast-bottom-full-width div.toast {
|
||||
margin: 0 10px 10px;
|
||||
width: calc(100% - 20px);
|
||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.35);
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
.toast-close-button {
|
||||
font-size: 18px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.toast {
|
||||
&:before {
|
||||
.ngx-toastr {
|
||||
align-items: center;
|
||||
background-image: none !important;
|
||||
border-radius: $border-radius;
|
||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.35);
|
||||
display: flex;
|
||||
padding: 15px;
|
||||
|
||||
.toast-close-button {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.icon i::before {
|
||||
float: left;
|
||||
font-style: normal;
|
||||
font-family: FontAwesome;
|
||||
font-size: 25px;
|
||||
line-height: 20px;
|
||||
float: left;
|
||||
color: #ffffff;
|
||||
margin: auto 0 auto 15px;
|
||||
}
|
||||
|
||||
.toast-content {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.toaster-icon {
|
||||
display: none;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.toast-message {
|
||||
@@ -48,49 +52,41 @@ $fa-font-path: "~font-awesome/fonts";
|
||||
}
|
||||
|
||||
&.toast-danger, &.toast-error {
|
||||
background-image: none !important;
|
||||
|
||||
@include themify($themes) {
|
||||
background-color: themed('dangerColor');
|
||||
}
|
||||
|
||||
&:before {
|
||||
.icon i::before {
|
||||
content: "\f0e7";
|
||||
}
|
||||
}
|
||||
|
||||
&.toast-warning {
|
||||
background-image: none !important;
|
||||
|
||||
@include themify($themes) {
|
||||
background-color: themed('warningColor');
|
||||
}
|
||||
|
||||
&:before {
|
||||
.icon i::before {
|
||||
content: "\f071";
|
||||
}
|
||||
}
|
||||
|
||||
&.toast-info {
|
||||
background-image: none !important;
|
||||
|
||||
@include themify($themes) {
|
||||
background-color: themed('infoColor');
|
||||
}
|
||||
|
||||
&:before {
|
||||
.icon i:before {
|
||||
content: "\f05a";
|
||||
}
|
||||
}
|
||||
|
||||
&.toast-success {
|
||||
background-image: none !important;
|
||||
|
||||
@include themify($themes) {
|
||||
background-color: themed('successColor');
|
||||
}
|
||||
|
||||
&:before {
|
||||
.icon i:before {
|
||||
content: "\f00C";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import { SendView } from 'jslib-common/models/view/sendView';
|
||||
|
||||
import { SendComponent as BaseSendComponent } from 'jslib-angular/components/send/send.component';
|
||||
|
||||
import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service';
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
@@ -23,8 +24,6 @@ import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
|
||||
import { PopupUtilsService } from '../services/popup-utils.service';
|
||||
|
||||
import { SendType } from 'jslib-common/enums/sendType';
|
||||
|
||||
@@ -17,6 +17,7 @@ import { SendView } from 'jslib-common/models/view/sendView';
|
||||
|
||||
import { SendComponent as BaseSendComponent } from 'jslib-angular/components/send/send.component';
|
||||
|
||||
import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service';
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
@@ -27,8 +28,6 @@ import { SendService } from 'jslib-common/abstractions/send.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
|
||||
import { PopupUtilsService } from '../services/popup-utils.service';
|
||||
|
||||
import { SendType } from 'jslib-common/enums/sendType';
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
Router,
|
||||
} from '@angular/router';
|
||||
|
||||
import { UnauthGuardService } from './unauth-guard.service';
|
||||
import { UnauthGuardService } from 'jslib-angular/services/unauth-guard.service';
|
||||
|
||||
@Injectable()
|
||||
export class LaunchGuardService implements CanActivate {
|
||||
|
||||
@@ -4,18 +4,15 @@ import {
|
||||
NgModule,
|
||||
} from '@angular/core';
|
||||
|
||||
import { ToasterModule } from 'angular2-toaster';
|
||||
|
||||
import { DebounceNavigationService } from './debounceNavigationService';
|
||||
import { LaunchGuardService } from './launch-guard.service';
|
||||
import { LockGuardService } from './lock-guard.service';
|
||||
import { PasswordRepromptService } from './password-reprompt.service';
|
||||
import { UnauthGuardService } from './unauth-guard.service';
|
||||
|
||||
import { AuthGuardService } from 'jslib-angular/services/auth-guard.service';
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
import { ModalService } from 'jslib-angular/services/modal.service';
|
||||
import { ValidationService } from 'jslib-angular/services/validation.service';
|
||||
import { JslibServicesModule } from 'jslib-angular/services/jslib-services.module';
|
||||
import { LockGuardService as BaseLockGuardService } from 'jslib-angular/services/lock-guard.service';
|
||||
import { UnauthGuardService as BaseUnauthGuardService } from 'jslib-angular/services/unauth-guard.service';
|
||||
|
||||
import { BrowserApi } from '../../browser/browserApi';
|
||||
|
||||
@@ -33,6 +30,7 @@ import { ExportService } from 'jslib-common/abstractions/export.service';
|
||||
import { FileUploadService } from 'jslib-common/abstractions/fileUpload.service';
|
||||
import { FolderService } from 'jslib-common/abstractions/folder.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { KeyConnectorService } from 'jslib-common/abstractions/keyConnector.service';
|
||||
import { LogService as LogServiceAbstraction } from 'jslib-common/abstractions/log.service';
|
||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||
import { NotificationsService } from 'jslib-common/abstractions/notifications.service';
|
||||
@@ -49,6 +47,7 @@ import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
import { TokenService } from 'jslib-common/abstractions/token.service';
|
||||
import { TotpService } from 'jslib-common/abstractions/totp.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
import { UserVerificationService } from 'jslib-common/abstractions/userVerification.service';
|
||||
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
|
||||
|
||||
import { AutofillService } from '../../services/abstractions/autofill.service';
|
||||
@@ -74,14 +73,9 @@ function getBgService<T>(service: string) {
|
||||
|
||||
const isPrivateMode = BrowserApi.getBackgroundPage() == null;
|
||||
|
||||
const stateService = new StateService();
|
||||
const messagingService = new BrowserMessagingService();
|
||||
const logService = getBgService<ConsoleLogService>('logService')();
|
||||
const searchService = isPrivateMode ? null : new PopupSearchService(getBgService<SearchService>('searchService')(),
|
||||
getBgService<CipherService>('cipherService')(), logService, getBgService<I18nService>('i18nService')());
|
||||
|
||||
export function initFactory(platformUtilsService: PlatformUtilsService, i18nService: I18nService, storageService: StorageService,
|
||||
popupUtilsService: PopupUtilsService): Function {
|
||||
export function initFactory(platformUtilsService: PlatformUtilsService, i18nService: I18nService,
|
||||
storageService: StorageService, popupUtilsService: PopupUtilsService, stateService: StateServiceAbstraction,
|
||||
logService: LogServiceAbstraction): Function {
|
||||
return async () => {
|
||||
if (!popupUtilsService.inPopup(window)) {
|
||||
window.document.body.classList.add('body-full');
|
||||
@@ -128,23 +122,48 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
ToasterModule,
|
||||
JslibServicesModule,
|
||||
],
|
||||
declarations: [],
|
||||
providers: [
|
||||
ValidationService,
|
||||
AuthGuardService,
|
||||
LockGuardService,
|
||||
{
|
||||
provide: LOCALE_ID,
|
||||
useFactory: () => isPrivateMode ? null : getBgService<I18nService>('i18nService')().translationLocale,
|
||||
deps: [],
|
||||
},
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: initFactory,
|
||||
deps: [
|
||||
PlatformUtilsService,
|
||||
I18nService,
|
||||
StorageService,
|
||||
PopupUtilsService,
|
||||
StateServiceAbstraction,
|
||||
LogServiceAbstraction,
|
||||
],
|
||||
multi: true,
|
||||
},
|
||||
LaunchGuardService,
|
||||
UnauthGuardService,
|
||||
{ provide: BaseLockGuardService, useClass: LockGuardService },
|
||||
{ provide: BaseUnauthGuardService, useClass: UnauthGuardService },
|
||||
DebounceNavigationService,
|
||||
PopupUtilsService,
|
||||
BroadcasterService,
|
||||
ModalService,
|
||||
{ provide: MessagingService, useValue: messagingService },
|
||||
{ provide: MessagingService, useClass: BrowserMessagingService },
|
||||
{ provide: AuthServiceAbstraction, useFactory: getBgService<AuthService>('authService'), deps: [] },
|
||||
{ provide: StateServiceAbstraction, useValue: stateService },
|
||||
{ provide: SearchServiceAbstraction, useValue: searchService },
|
||||
{ provide: StateServiceAbstraction, useClass: StateService },
|
||||
{
|
||||
provide: SearchServiceAbstraction,
|
||||
useFactory: (cipherService: CipherService, logService: ConsoleLogService, i18nService: I18nService) => {
|
||||
return isPrivateMode ? null : new PopupSearchService(getBgService<SearchService>('searchService')(),
|
||||
cipherService, logService, i18nService);
|
||||
},
|
||||
deps: [
|
||||
CipherService,
|
||||
LogServiceAbstraction,
|
||||
I18nService,
|
||||
],
|
||||
},
|
||||
{ provide: AuditService, useFactory: getBgService<AuditService>('auditService'), deps: [] },
|
||||
{ provide: FileUploadService, useFactory: getBgService<FileUploadService>('fileUploadService'), deps: [] },
|
||||
{ provide: CipherService, useFactory: getBgService<CipherService>('cipherService'), deps: [] },
|
||||
@@ -182,6 +201,12 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ
|
||||
{ provide: AutofillService, useFactory: getBgService<AutofillService>('autofillService'), deps: [] },
|
||||
{ provide: ExportService, useFactory: getBgService<ExportService>('exportService'), deps: [] },
|
||||
{ provide: SendService, useFactory: getBgService<SendService>('sendService'), deps: [] },
|
||||
{ provide: KeyConnectorService, useFactory: getBgService<KeyConnectorService>('keyConnectorService'), deps: [] },
|
||||
{
|
||||
provide: UserVerificationService,
|
||||
useFactory: getBgService<UserVerificationService>('userVerificationService'),
|
||||
deps: [],
|
||||
},
|
||||
{
|
||||
provide: VaultTimeoutService,
|
||||
useFactory: getBgService<VaultTimeoutService>('vaultTimeoutService'),
|
||||
@@ -192,17 +217,7 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ
|
||||
useFactory: getBgService<NotificationsService>('notificationsService'),
|
||||
deps: [],
|
||||
},
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: initFactory,
|
||||
deps: [PlatformUtilsService, I18nService, StorageService, PopupUtilsService],
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide: LOCALE_ID,
|
||||
useFactory: () => isPrivateMode ? null : getBgService<I18nService>('i18nService')().translationLocale,
|
||||
deps: [],
|
||||
},
|
||||
{ provide: LogServiceAbstraction, useFactory: getBgService<ConsoleLogService>('logService'), deps: [] },
|
||||
{ provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService },
|
||||
],
|
||||
})
|
||||
|
||||
@@ -9,12 +9,11 @@ import { Router } from '@angular/router';
|
||||
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
|
||||
import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
|
||||
import { BrowserApi } from '../../browser/browserApi';
|
||||
|
||||
import { Utils } from 'jslib-common/misc/utils';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<form (ngSubmit)="submit()">
|
||||
<form (ngSubmit)="submit()" [formGroup]="exportForm">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/tabs/settings">
|
||||
@@ -10,7 +10,7 @@
|
||||
<span class="title">{{'exportVault' | i18n}}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button appBlurClick type="submit" [disabled]="disabledByPolicy">{{'submit' | i18n}}</button>
|
||||
<button appBlurClick type="submit" [disabled]="!exportForm.enabled">{{'submit' | i18n}}</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
@@ -22,30 +22,15 @@
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="format">{{'fileFormat' | i18n}}</label>
|
||||
<select id="format" name="Format" [(ngModel)]="format" [disabled]="disabledByPolicy">
|
||||
<option value="json">.json</option>
|
||||
<option value="csv">.csv</option>
|
||||
<option value="encrypted_json">.json (Encrypted)</option>
|
||||
<select id="format" name="Format" formControlName="format">
|
||||
<option *ngFor="let f of formatOptions" [value]="f.value">{{f.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">{{'masterPass' | i18n}}</label>
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword"
|
||||
class="monospaced" [(ngModel)]="masterPassword" required appInputVerbatim appAutofocus
|
||||
[disabled]="disabledByPolicy">
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword()">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<app-verify-master-password ngDefaultControl formControlName="secret" name="Secret">
|
||||
</app-verify-master-password>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<p>{{'exportMasterPassword' | i18n}}</p>
|
||||
<p>{{'confirmIdentity' | i18n}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
|
||||
@@ -8,6 +9,7 @@ import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { PolicyService } from 'jslib-common/abstractions/policy.service';
|
||||
import { UserVerificationService } from 'jslib-common/abstractions/userVerification.service';
|
||||
|
||||
import { ExportComponent as BaseExportComponent } from 'jslib-angular/components/export.component';
|
||||
|
||||
@@ -19,9 +21,9 @@ export class ExportComponent extends BaseExportComponent {
|
||||
constructor(cryptoService: CryptoService, i18nService: I18nService,
|
||||
platformUtilsService: PlatformUtilsService, exportService: ExportService,
|
||||
eventService: EventService, policyService: PolicyService, private router: Router,
|
||||
logService: LogService) {
|
||||
logService: LogService, userVerificationService: UserVerificationService, fb: FormBuilder) {
|
||||
super(cryptoService, i18nService, platformUtilsService, exportService, eventService, policyService, window,
|
||||
logService);
|
||||
logService, userVerificationService, fb);
|
||||
}
|
||||
|
||||
protected saved() {
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
<span><i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i></span>
|
||||
</a>
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="changePassword()">
|
||||
(click)="changePassword()" *ngIf="showChangeMasterPass">
|
||||
<div class="row-main">{{'changeMasterPassword' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</button>
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
} from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { ToasterService } from 'angular2-toaster';
|
||||
import Swal from 'sweetalert2/src/sweetalert2.js';
|
||||
|
||||
import { BrowserApi } from '../../browser/browserApi';
|
||||
@@ -18,6 +17,7 @@ import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { KeyConnectorService } from 'jslib-common/abstractions/keyConnector.service';
|
||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
@@ -58,6 +58,7 @@ export class SettingsComponent implements OnInit {
|
||||
biometric: boolean = false;
|
||||
disableAutoBiometricsPrompt = true;
|
||||
previousVaultTimeout: number = null;
|
||||
showChangeMasterPass = true;
|
||||
|
||||
vaultTimeout: FormControl = new FormControl(null);
|
||||
|
||||
@@ -66,7 +67,8 @@ export class SettingsComponent implements OnInit {
|
||||
public messagingService: MessagingService, private router: Router,
|
||||
private environmentService: EnvironmentService, private cryptoService: CryptoService,
|
||||
private userService: UserService, private popupUtilsService: PopupUtilsService,
|
||||
private modalService: ModalService, private toasterService: ToasterService) {
|
||||
private modalService: ModalService,
|
||||
private keyConnectorService: KeyConnectorService) {
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -118,6 +120,7 @@ export class SettingsComponent implements OnInit {
|
||||
this.biometric = await this.vaultTimeoutService.isBiometricLockSet();
|
||||
this.disableAutoBiometricsPrompt = await this.storageService.get<boolean>(
|
||||
ConstantsService.disableAutoBiometricsPromptKey) ?? true;
|
||||
this.showChangeMasterPass = !await this.keyConnectorService.getUsesKeyConnector();
|
||||
}
|
||||
|
||||
async saveVaultTimeout(newValue: number) {
|
||||
@@ -132,7 +135,7 @@ export class SettingsComponent implements OnInit {
|
||||
}
|
||||
|
||||
if (!this.vaultTimeout.valid) {
|
||||
this.toasterService.popAsync('error', null, this.i18nService.t('vaultTimeoutToLarge'));
|
||||
this.platformUtilsService.showToast('error', null, this.i18nService.t('vaultTimeoutToLarge'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -161,7 +164,7 @@ export class SettingsComponent implements OnInit {
|
||||
}
|
||||
|
||||
if (!this.vaultTimeout.valid) {
|
||||
this.toasterService.popAsync('error', null, this.i18nService.t('vaultTimeoutToLarge'));
|
||||
this.platformUtilsService.showToast('error', null, this.i18nService.t('vaultTimeoutToLarge'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { ToasterService } from 'angular2-toaster';
|
||||
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
|
||||
@Component({
|
||||
@@ -16,7 +15,7 @@ export class SyncComponent implements OnInit {
|
||||
lastSync = '--';
|
||||
syncPromise: Promise<any>;
|
||||
|
||||
constructor(private syncService: SyncService, private toasterService: ToasterService,
|
||||
constructor(private syncService: SyncService, private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService) {
|
||||
}
|
||||
|
||||
@@ -29,9 +28,9 @@ export class SyncComponent implements OnInit {
|
||||
const success = await this.syncPromise;
|
||||
if (success) {
|
||||
await this.setLastSync();
|
||||
this.toasterService.popAsync('success', null, this.i18nService.t('syncingComplete'));
|
||||
this.platformUtilsService.showToast('success', null, this.i18nService.t('syncingComplete'));
|
||||
} else {
|
||||
this.toasterService.popAsync('error', null, this.i18nService.t('syncingFailed'));
|
||||
this.platformUtilsService.showToast('error', null, this.i18nService.t('syncingFailed'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,15 +16,20 @@
|
||||
<div class="row-main">
|
||||
<input id="fieldName{{i}}" type="text" name="Field.Name{{i}}" [(ngModel)]="f.name" class="row-label"
|
||||
placeholder="{{'name' | i18n}}" appInputVerbatim>
|
||||
<!--Custom Field: Text-->
|
||||
<!-- Text -->
|
||||
<input id="fieldValue{{i}}" type="text" name="Field.Value{{i}}" [(ngModel)]="f.value"
|
||||
*ngIf="f.type === fieldType.Text" placeholder="{{'value' | i18n}}" appInputVerbatim>
|
||||
<!--Custom Field: Hidden-->
|
||||
<!-- Hidden -->
|
||||
<input id="fieldValue{{i}}" type="{{f.showValue ? 'text' : 'password'}}" name="Field.Value{{i}}"
|
||||
[(ngModel)]="f.value" class="monospaced" appInputVerbatim *ngIf="f.type === fieldType.Hidden"
|
||||
placeholder="{{'value' | i18n}}" [disabled]="!cipher.viewPassword && !f.newField">
|
||||
<!-- Linked -->
|
||||
<select id="fieldValue{{i}}" name="Field.Value{{i}}" [(ngModel)]="f.linkedId"
|
||||
*ngIf="f.type === fieldType.Linked && cipher.linkedFieldOptions != null">
|
||||
<option *ngFor="let o of linkedFieldOptions" [ngValue]="o.value">{{o.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<!--Custom Field: Boolean-->
|
||||
<!-- Boolean -->
|
||||
<input id="fieldValue{{i}}" name="Field.Value{{i}}" type="checkbox" [(ngModel)]="f.value"
|
||||
*ngIf="f.type === fieldType.Boolean" appTrueFalseValue trueValue="true" falseValue="false">
|
||||
<div class="action-buttons" *ngIf="f.type === fieldType.Hidden && (cipher.viewPassword || f.newField)">
|
||||
@@ -47,6 +52,9 @@
|
||||
<label for="addFieldType" class="sr-only">{{'type' | i18n}}</label>
|
||||
<select id="addFieldType" name="AddFieldType" [(ngModel)]="addFieldType" class="field-type">
|
||||
<option *ngFor="let o of addFieldTypeOptions" [ngValue]="o.value">{{o.name}}</option>
|
||||
<option *ngIf="cipher.linkedFieldOptions != null" [ngValue]="addFieldLinkedTypeOption.value">
|
||||
{{addFieldLinkedTypeOption.name}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -290,7 +290,7 @@
|
||||
<label for="favorite">{{'favorite' | i18n}}</label>
|
||||
<input id="favorite" type="checkbox" name="Favorite" [(ngModel)]="cipher.favorite">
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow *ngIf="canUseReprompt">
|
||||
<label for="passwordPrompt">
|
||||
{{'passwordPrompt' | i18n}}
|
||||
<a target="_blank" rel="noopener" appA11yTitle="{{'learnMore' | i18n}}"
|
||||
@@ -298,8 +298,7 @@
|
||||
<i class="fa fa-question-circle-o" aria-hidden="true"></i>
|
||||
</a>
|
||||
</label>
|
||||
<input id="passwordPrompt" type="checkbox" name="PasswordPrompt" [ngModel]="reprompt"
|
||||
(change)="repromptChanged()">
|
||||
<input id="passwordPrompt" type="checkbox" name="PasswordPrompt" [ngModel]="reprompt" (change)="repromptChanged()">
|
||||
</div>
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="attachments()" *ngIf="editMode && showAttachments && !cloneMode">
|
||||
@@ -324,7 +323,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<app-vault-add-edit-custom-fields [cipher]="cipher" [editMode]="editMode"></app-vault-add-edit-custom-fields>
|
||||
<app-vault-add-edit-custom-fields [cipher]="cipher" [thisCipherType]="cipher.type" [editMode]="editMode">
|
||||
</app-vault-add-edit-custom-fields>
|
||||
<div class="box" *ngIf="allowOwnershipOptions()">
|
||||
<h2 class="box-header">
|
||||
{{'ownership' | i18n}}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { FolderService } from 'jslib-common/abstractions/folder.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||
import { PasswordRepromptService } from 'jslib-common/abstractions/passwordReprompt.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { PolicyService } from 'jslib-common/abstractions/policy.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
@@ -51,9 +52,10 @@ export class AddEditComponent extends BaseAddEditComponent {
|
||||
private router: Router, private location: Location,
|
||||
eventService: EventService, policyService: PolicyService,
|
||||
private popupUtilsService: PopupUtilsService, private storageService: StorageService,
|
||||
logService: LogService) {
|
||||
logService: LogService, passwordRepromptService: PasswordRepromptService) {
|
||||
super(cipherService, folderService, i18nService, platformUtilsService, auditService, stateService,
|
||||
userService, collectionService, messagingService, eventService, policyService, logService);
|
||||
userService, collectionService, messagingService, eventService, policyService, passwordRepromptService,
|
||||
logService);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
|
||||
@@ -15,6 +15,7 @@ import { first } from 'rxjs/operators';
|
||||
|
||||
import { BrowserApi } from '../../browser/browserApi';
|
||||
|
||||
import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service';
|
||||
import { CipherService } from 'jslib-common/abstractions/cipher.service';
|
||||
import { CollectionService } from 'jslib-common/abstractions/collection.service';
|
||||
import { FolderService } from 'jslib-common/abstractions/folder.service';
|
||||
@@ -31,8 +32,6 @@ import { FolderView } from 'jslib-common/models/view/folderView';
|
||||
|
||||
import { TreeNode } from 'jslib-common/models/domain/treeNode';
|
||||
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
|
||||
import { CiphersComponent as BaseCiphersComponent } from 'jslib-angular/components/ciphers.component';
|
||||
|
||||
import { PopupUtilsService } from '../services/popup-utils.service';
|
||||
|
||||
@@ -5,20 +5,16 @@ import {
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { ToasterService } from 'angular2-toaster';
|
||||
|
||||
import { BrowserApi } from '../../browser/browserApi';
|
||||
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
|
||||
import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType';
|
||||
import { CipherType } from 'jslib-common/enums/cipherType';
|
||||
|
||||
import { CipherView } from 'jslib-common/models/view/cipherView';
|
||||
|
||||
import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service';
|
||||
import { CipherService } from 'jslib-common/abstractions/cipher.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { PasswordRepromptService } from 'jslib-common/abstractions/passwordReprompt.service';
|
||||
@@ -60,7 +56,7 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
|
||||
|
||||
constructor(private platformUtilsService: PlatformUtilsService, private cipherService: CipherService,
|
||||
private popupUtilsService: PopupUtilsService, private autofillService: AutofillService,
|
||||
private toasterService: ToasterService, private i18nService: I18nService, private router: Router,
|
||||
private i18nService: I18nService, private router: Router,
|
||||
private ngZone: NgZone, private broadcasterService: BroadcasterService,
|
||||
private changeDetectorRef: ChangeDetectorRef, private syncService: SyncService,
|
||||
private searchService: SearchService, private storageService: StorageService,
|
||||
@@ -141,7 +137,7 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
if (this.pageDetails == null || this.pageDetails.length === 0) {
|
||||
this.toasterService.popAsync('error', null, this.i18nService.t('autofillError'));
|
||||
this.platformUtilsService.showToast('error', null, this.i18nService.t('autofillError'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -165,7 +161,7 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
} catch {
|
||||
this.ngZone.run(() => {
|
||||
this.toasterService.popAsync('error', null, this.i18nService.t('autofillError'));
|
||||
this.platformUtilsService.showToast('error', null, this.i18nService.t('autofillError'));
|
||||
this.changeDetectorRef.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import { CipherView } from 'jslib-common/models/view/cipherView';
|
||||
import { CollectionView } from 'jslib-common/models/view/collectionView';
|
||||
import { FolderView } from 'jslib-common/models/view/folderView';
|
||||
|
||||
import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service';
|
||||
import { CipherService } from 'jslib-common/abstractions/cipher.service';
|
||||
import { CollectionService } from 'jslib-common/abstractions/collection.service';
|
||||
import { FolderService } from 'jslib-common/abstractions/folder.service';
|
||||
@@ -31,8 +32,6 @@ import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
|
||||
import { GroupingsComponent as BaseGroupingsComponent } from 'jslib-angular/components/groupings.component';
|
||||
|
||||
import { PopupUtilsService } from '../services/popup-utils.service';
|
||||
|
||||
@@ -18,6 +18,13 @@
|
||||
<i class="fa fa-square-o" *ngIf="field.value !== 'true'" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{field.value}}</span>
|
||||
</div>
|
||||
<div *ngIf="field.type === fieldType.Linked" class="box-content-row-flex">
|
||||
<div class="icon icon-small">
|
||||
<i class="fa fa-link" aria-hidden="true" appA11yTitle="{{'linkedValue' | i18n}}"></i>
|
||||
<span class="sr-only">{{'linkedValue' | i18n}}</span>
|
||||
</div>
|
||||
<span>{{cipher.linkedFieldI18nKey(field.linkedId) | i18n}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
@@ -27,7 +34,8 @@
|
||||
[ngClass]="{'fa-eye': !field.showValue, 'fa-eye-slash': field.showValue}"></i>
|
||||
</button>
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'copyValue' | i18n}}"
|
||||
*ngIf="field.value && field.type !== fieldType.Boolean && !(field.type === fieldType.Hidden && !cipher.viewPassword)"
|
||||
*ngIf="field.value && field.type !== fieldType.Boolean && field.type !== fieldType.Linked &&
|
||||
!(field.type === fieldType.Hidden && !cipher.viewPassword)"
|
||||
(click)="copy(field.value, 'value', field.type === fieldType.Hidden ? 'H_Field' : 'Field')">
|
||||
<i class="fa fa-lg fa-clone" aria-hidden="true"></i>
|
||||
</button>
|
||||
|
||||
@@ -13,6 +13,7 @@ import { first } from 'rxjs/operators';
|
||||
|
||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { AuditService } from 'jslib-common/abstractions/audit.service';
|
||||
import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service';
|
||||
import { CipherService } from 'jslib-common/abstractions/cipher.service';
|
||||
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
|
||||
import { EventService } from 'jslib-common/abstractions/event.service';
|
||||
@@ -25,8 +26,6 @@ import { TokenService } from 'jslib-common/abstractions/token.service';
|
||||
import { TotpService } from 'jslib-common/abstractions/totp.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
|
||||
import { Cipher } from 'jslib-common/models/domain/cipher';
|
||||
import { LoginUriView } from 'jslib-common/models/view/loginUriView';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user