1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-21 18:53:29 +00:00

Merge branch 'master' of github.com:bitwarden/browser into feature/safari-webext

# Conflicts:
#	src/browser/safariApp.ts
#	src/safari/safari/SafariExtensionViewController.swift
#	src/services/browserPlatformUtils.service.ts
This commit is contained in:
Hinton
2021-01-13 14:21:45 +01:00
21 changed files with 202 additions and 71 deletions

View File

@@ -41,11 +41,11 @@ export class SsoComponent extends BaseSsoComponent {
this.redirectUri = url + '/sso-connector.html';
this.clientId = 'browser';
super.onSuccessfulLogin = () => {
super.onSuccessfulLogin = async () => {
await syncService.fullSync(true);
BrowserApi.reloadOpenWindows();
const thisWindow = window.open('', '_self');
thisWindow.close();
return syncService.fullSync(true);
};
}
}

View File

@@ -150,6 +150,9 @@ export const routerTransition = trigger('routerTransition', [
transition('view-cipher => clone-cipher', inSlideUp),
transition('clone-cipher => view-cipher, clone-cipher => tabs', outSlideDown),
transition('view-cipher => share-cipher', inSlideUp),
transition('share-cipher => view-cipher', outSlideDown),
transition('tabs => add-cipher', inSlideUp),
transition('add-cipher => tabs', outSlideDown),
@@ -159,9 +162,6 @@ export const routerTransition = trigger('routerTransition', [
transition('add-cipher => generator, edit-cipher => generator, clone-cipher => generator', inSlideUp),
transition('generator => add-cipher, generator => edit-cipher, generator => clone-cipher', outSlideDown),
transition('edit-cipher => share-cipher', inSlideUp),
transition('share-cipher => edit-cipher, share-cipher => view-cipher', outSlideDown),
transition('edit-cipher => attachments, edit-cipher => collections', inSlideLeft),
transition('attachments => edit-cipher, collections => edit-cipher', outSlideRight),

View File

@@ -16,6 +16,11 @@
[ngClass]="{disabled: (!cipher.login.password || !cipher.viewPassword)}">
<i class="fa fa-lg fa-key" aria-hidden="true"></i>
</span>
<span class="row-btn" appStopClick appStopProp appA11yTitle="{{'copyVerificationCode' | i18n}}"
(click)="copy(cipher, cipher.login.totp, 'verificationCodeTotp', 'TOTP')"
[ngClass]="{disabled: (!displayTotpCopyButton(cipher))}">
<i class="fa fa-lg fa-clock-o" aria-hidden="true"></i>
</span>
</ng-container>
<ng-container *ngIf="cipher.type === cipherType.Card">
<span class="row-btn" appStopClick appStopProp appA11yTitle="{{'copyNumber' | i18n}}"

View File

@@ -18,6 +18,8 @@ import { CipherView } from 'jslib/models/view/cipherView';
import { EventService } from 'jslib/abstractions/event.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { TotpService } from 'jslib/abstractions/totp.service';
import { UserService } from 'jslib/abstractions/user.service';
import { PopupUtilsService } from '../services/popup-utils.service';
@@ -31,10 +33,16 @@ export class ActionButtonsComponent {
@Input() showView = false;
cipherType = CipherType;
userHasPremiumAccess = false;
constructor(private analytics: Angulartics2, private toasterService: ToasterService,
private i18nService: I18nService, private platformUtilsService: PlatformUtilsService,
private popupUtilsService: PopupUtilsService, private eventService: EventService) { }
private popupUtilsService: PopupUtilsService, private eventService: EventService,
private totpService: TotpService, private userService: UserService) { }
async ngOnInit() {
this.userHasPremiumAccess = await this.userService.canAccessPremium();
}
launch() {
if (this.cipher.type !== CipherType.Login || !this.cipher.login.canLaunch) {
@@ -48,9 +56,11 @@ export class ActionButtonsComponent {
}
}
copy(cipher: CipherView, value: string, typeI18nKey: string, aType: string) {
if (value == null) {
async copy(cipher: CipherView, value: string, typeI18nKey: string, aType: string) {
if (value == null || aType === 'TOTP' && !this.displayTotpCopyButton(cipher)) {
return;
} else if (value === cipher.login.totp) {
value = await this.totpService.getCode(value);
}
if (!cipher.viewPassword) {
@@ -62,13 +72,18 @@ export class ActionButtonsComponent {
this.toasterService.popAsync('info', null,
this.i18nService.t('valueCopied', this.i18nService.t(typeI18nKey)));
if (typeI18nKey === 'password') {
if (typeI18nKey === 'password' || typeI18nKey === 'verificationCodeTotp') {
this.eventService.collect(EventType.Cipher_ClientToggledHiddenFieldVisible, cipher.id);
} else if (typeI18nKey === 'securityCode') {
this.eventService.collect(EventType.Cipher_ClientCopiedCardCode, cipher.id);
}
}
displayTotpCopyButton(cipher: CipherView) {
return (cipher?.login?.hasTotp ?? false) &&
(cipher.organizationUseTotp || this.userHasPremiumAccess);
}
view() {
this.onView.emit(this.cipher);
}

View File

@@ -1,10 +1,12 @@
import { CipherService } from 'jslib/abstractions/cipher.service';
import { ConsoleLogService } from 'jslib/services/consoleLog.service';
import { SearchService } from 'jslib/services/search.service';
export class PopupSearchService extends SearchService {
constructor(private mainSearchService: SearchService, cipherService: CipherService) {
super(cipherService);
constructor(private mainSearchService: SearchService, cipherService: CipherService,
consoleLogService: ConsoleLogService) {
super(cipherService, consoleLogService);
}
clearIndex() {

View File

@@ -50,6 +50,7 @@ import { AuthService } from 'jslib/services/auth.service';
import { ConstantsService } from 'jslib/services/constants.service';
import { SearchService } from 'jslib/services/search.service';
import { StateService } from 'jslib/services/state.service';
import { ConsoleLogService } from 'jslib/services/consoleLog.service';
import { Analytics } from 'jslib/misc/analytics';
@@ -69,11 +70,11 @@ export const authService = new AuthService(getBgService<CryptoService>('cryptoSe
getBgService<ApiService>('apiService')(), getBgService<UserService>('userService')(),
getBgService<TokenService>('tokenService')(), getBgService<AppIdService>('appIdService')(),
getBgService<I18nService>('i18nService')(), getBgService<PlatformUtilsService>('platformUtilsService')(),
messagingService, getBgService<VaultTimeoutService>('vaultTimeoutService')());
messagingService, getBgService<VaultTimeoutService>('vaultTimeoutService')(), getBgService<ConsoleLogService>('consoleLogService')());
export const searchService = new PopupSearchService(getBgService<SearchService>('searchService')(),
getBgService<CipherService>('cipherService')());
getBgService<CipherService>('cipherService')(), getBgService<ConsoleLogService>('consoleLogService')());
export function initFactory(i18nService: I18nService, storageService: StorageService,
export function initFactory(platformUtilsService: PlatformUtilsService, i18nService: I18nService, storageService: StorageService,
popupUtilsService: PopupUtilsService): Function {
return async () => {
if (!popupUtilsService.inPopup(window)) {
@@ -90,7 +91,12 @@ export function initFactory(i18nService: I18nService, storageService: StorageSer
let theme = await storageService.get<string>(ConstantsService.themeKey);
if (theme == null) {
theme = 'light';
theme = platformUtilsService.getDefaultSystemTheme();
platformUtilsService.onDefaultSystemThemeChange((theme) => {
window.document.documentElement.classList.remove('theme_light', 'theme_dark');
window.document.documentElement.classList.add('theme_' + theme);
});
}
window.document.documentElement.classList.add('locale_' + i18nService.translationLocale);
window.document.documentElement.classList.add('theme_' + theme);
@@ -171,7 +177,7 @@ export function initFactory(i18nService: I18nService, storageService: StorageSer
{
provide: APP_INITIALIZER,
useFactory: initFactory,
deps: [I18nService, StorageService, PopupUtilsService],
deps: [PlatformUtilsService, I18nService, StorageService, PopupUtilsService],
multi: true,
},
{

View File

@@ -41,13 +41,6 @@
</div>
<div class="box-footer">
<p>{{'exportMasterPassword' | i18n}}</p>
<strong>{{'warning' | i18n}}</strong>:
<span *ngIf="!encryptedFormat">
{{'exportWarningDesc' | i18n}}
</span>
<span *ngIf="encryptedFormat">
{{'encExportWarningDesc' | i18n}}
</span>
</div>
</div>
</content>

View File

@@ -14,6 +14,9 @@
</div>
</header>
<content *ngIf="cipher">
<app-callout type="info" *ngIf="allowOwnershipOptions() && !allowPersonal">
{{'personalOwnershipPolicyInEffect' | i18n}}
</app-callout>
<div class="box">
<div class="box-header">
{{'itemInformation' | i18n}}
@@ -374,15 +377,6 @@
</div>
<div class="box list" *ngIf="editMode && !cloneMode">
<div class="box-content single-line">
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="share()"
*ngIf="!cipher.organizationId">
<div class="row-main text-primary">
<div class="icon text-primary" aria-hidden="true">
<i class="fa fa-share-alt fa-lg fa-fw"></i>
</div>
<span>{{'shareItem' | i18n}}</span>
</div>
</a>
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="delete()"
[appApiAction]="deletePromise" #deleteBtn>
<div class="row-main text-danger">

View File

@@ -118,12 +118,6 @@ export class AddEditComponent extends BaseAddEditComponent {
this.router.navigate(['/attachments'], { queryParams: { cipherId: this.cipher.id } });
}
share() {
super.share();
if (this.cipher.organizationId == null) {
this.router.navigate(['/share-cipher'], { queryParams: { cipherId: this.cipher.id } });
}
}
editCollections() {
super.editCollections();

View File

@@ -41,14 +41,12 @@ export class ShareComponent extends BaseShareComponent {
async submit(): Promise<boolean> {
const success = await super.submit();
if (success) {
window.setTimeout(() => {
this.location.back();
}, 200);
this.cancel();
}
return success;
}
cancel() {
this.location.back();
this.router.navigate(['/view-cipher'], { replaceUrl: true, queryParams: { cipherId: this.cipher.id } });
}
}

View File

@@ -295,6 +295,14 @@
<span>{{'cloneItem' | i18n}}</span>
</div>
</a>
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="share()" *ngIf="!cipher.organizationId">
<div class="row-main text-primary">
<div class="icon text-primary" aria-hidden="true">
<i class="fa fa-share-alt fa-lg fa-fw"></i>
</div>
<span>{{'shareItem' | i18n}}</span>
</div>
</a>
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="restore()" *ngIf="cipher.isDeleted">
<div class="row-main text-primary">
<div class="icon text-primary" aria-hidden="true">

View File

@@ -129,6 +129,13 @@ export class ViewComponent extends BaseViewComponent {
});
}
share() {
super.share();
if (this.cipher.organizationId == null) {
this.router.navigate(['/share-cipher'], { replaceUrl: true, queryParams: { cipherId: this.cipher.id } });
}
}
async fillCipher() {
const didAutofill = await this.doAutofill();
if (didAutofill) {