1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-09-27 04:03:00 +02:00

Merge remote-tracking branch 'origin/main' into ps/pm-10744/remove-get-bg-service

This commit is contained in:
Justin Baur 2024-09-24 07:14:01 -04:00
commit 15077e6094
No known key found for this signature in database
93 changed files with 583 additions and 259 deletions

View File

@ -1,6 +1,6 @@
{
"name": "@bitwarden/browser",
"version": "2024.9.1",
"version": "2024.9.2",
"scripts": {
"build": "cross-env MANIFEST_VERSION=3 webpack",
"build:mv2": "webpack",

View File

@ -2374,6 +2374,10 @@
"message": "Are you sure you want to delete this Send?",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"deleteSendPermanentConfirmation": {
"message": "Are you sure you want to permanently delete this Send?",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
},
"editSend": {
"message": "Edit Send",
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."

View File

@ -416,7 +416,7 @@ export default class MainBackground {
this.logService = new ConsoleLogService(isDev);
this.cryptoFunctionService = new WebCryptoFunctionService(self);
this.keyGenerationService = new KeyGenerationService(this.cryptoFunctionService);
this.storageService = new BrowserLocalStorageService();
this.storageService = new BrowserLocalStorageService(this.logService);
this.intraprocessMessagingSubject = new Subject<Message<Record<string, unknown>>>();
@ -681,6 +681,7 @@ export default class MainBackground {
this.collectionService = new CollectionService(
this.cryptoService,
this.encryptService,
this.i18nService,
this.stateProvider,
);
@ -791,9 +792,11 @@ export default class MainBackground {
this.cipherFileUploadService,
this.configService,
this.stateProvider,
this.accountService,
);
this.folderService = new FolderService(
this.cryptoService,
this.encryptService,
this.i18nService,
this.cipherService,
this.stateProvider,
@ -947,6 +950,7 @@ export default class MainBackground {
this.i18nService,
this.collectionService,
this.cryptoService,
this.encryptService,
this.pinService,
this.accountService,
);
@ -956,8 +960,10 @@ export default class MainBackground {
this.cipherService,
this.pinService,
this.cryptoService,
this.encryptService,
this.cryptoFunctionService,
this.kdfConfigService,
this.accountService,
);
this.organizationVaultExportService = new OrganizationVaultExportService(
@ -965,6 +971,7 @@ export default class MainBackground {
this.apiService,
this.pinService,
this.cryptoService,
this.encryptService,
this.cryptoFunctionService,
this.collectionService,
this.kdfConfigService,
@ -1068,6 +1075,7 @@ export default class MainBackground {
);
this.nativeMessagingBackground = new NativeMessagingBackground(
this.cryptoService,
this.encryptService,
this.cryptoFunctionService,
this.runtimeBackground,
this.messagingService,

View File

@ -6,6 +6,7 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -73,6 +74,7 @@ export class NativeMessagingBackground {
constructor(
private cryptoService: CryptoService,
private encryptService: EncryptService,
private cryptoFunctionService: CryptoFunctionService,
private runtimeBackground: RuntimeBackground,
private messagingService: MessagingService,
@ -227,7 +229,7 @@ export class NativeMessagingBackground {
await this.secureCommunication();
}
return await this.cryptoService.encrypt(JSON.stringify(message), this.sharedSecret);
return await this.encryptService.encrypt(JSON.stringify(message), this.sharedSecret);
}
getResponse(): Promise<any> {
@ -273,7 +275,7 @@ export class NativeMessagingBackground {
let message = rawMessage as ReceiveMessage;
if (!this.platformUtilsService.isSafari()) {
message = JSON.parse(
await this.cryptoService.decryptToUtf8(rawMessage as EncString, this.sharedSecret),
await this.encryptService.decryptToUtf8(rawMessage as EncString, this.sharedSecret),
);
}

View File

@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "__MSG_extName__",
"short_name": "__MSG_appName__",
"version": "2024.9.1",
"version": "2024.9.2",
"description": "__MSG_extDesc__",
"default_locale": "en",
"author": "Bitwarden Inc.",

View File

@ -3,7 +3,7 @@
"minimum_chrome_version": "102.0",
"name": "__MSG_extName__",
"short_name": "__MSG_appName__",
"version": "2024.9.1",
"version": "2024.9.2",
"description": "__MSG_extDesc__",
"default_locale": "en",
"author": "Bitwarden Inc.",

View File

@ -1,10 +1,67 @@
import AbstractChromeStorageService from "./abstractions/abstract-chrome-storage-api.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import AbstractChromeStorageService, {
SerializedValue,
} from "./abstractions/abstract-chrome-storage-api.service";
export default class BrowserLocalStorageService extends AbstractChromeStorageService {
constructor() {
constructor(private readonly logService: LogService) {
super(chrome.storage.local);
}
override async get<T>(key: string): Promise<T> {
return await this.getWithRetries<T>(key, 0);
}
private async getWithRetries<T>(key: string, retryNum: number): Promise<T> {
// See: https://github.com/EFForg/privacybadger/pull/2980
const MAX_RETRIES = 5;
const WAIT_TIME = 200;
const store = await this.getStore(key);
if (store == null) {
if (retryNum >= MAX_RETRIES) {
throw new Error(`Failed to get a value for key '${key}', see logs for more details.`);
}
retryNum++;
this.logService.warning(`Retrying attempt to get value for key '${key}' in ${WAIT_TIME}ms`);
await new Promise<void>((resolve) => setTimeout(resolve, WAIT_TIME));
return await this.getWithRetries(key, retryNum);
}
// We have a store
return this.processGetObject<T>(store[key] as T | SerializedValue);
}
private async getStore(key: string) {
if (this.chromeStorageApi == null) {
this.logService.warning(
`chrome.storage.local was not initialized while retrieving key '${key}'.`,
);
return null;
}
return new Promise<{ [key: string]: unknown }>((resolve) => {
this.chromeStorageApi.get(key, (store) => {
if (chrome.runtime.lastError) {
this.logService.warning(`Failed to get value for key '${key}'`, chrome.runtime.lastError);
resolve(null);
return;
}
if (store == null) {
this.logService.warning(`Store was empty while retrieving value for key '${key}'`);
resolve(null);
return;
}
resolve(store);
});
});
}
async fillBuffer() {
// Write 4MB of data in chrome.storage.local, log files will hold 4MB of data (by default)
// before forcing a compaction. To force a compaction and have it remove previously saved data,

View File

@ -305,7 +305,7 @@ const safeProviders: SafeProvider[] = [
safeProvider({
provide: AbstractStorageService,
useClass: BrowserLocalStorageService,
deps: [],
deps: [LogService],
}),
safeProvider({
provide: AutofillServiceAbstraction,

View File

@ -13,5 +13,14 @@
<button bitButton type="submit" form="sendForm" buttonType="primary" #submitBtn>
{{ "save" | i18n }}
</button>
<button
*ngIf="config?.mode !== 'add'"
type="button"
buttonType="danger"
class="tw-ml-auto bwi-lg"
bitIconButton="bwi-trash"
[bitAction]="deleteSend"
appA11yTitle="{{ 'delete' | i18n }}"
></button>
</popup-footer>
</popup-page>

View File

@ -8,8 +8,16 @@ import { map, switchMap } from "rxjs";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
import { SendId } from "@bitwarden/common/types/guid";
import { AsyncActionsModule, ButtonModule, SearchModule } from "@bitwarden/components";
import {
AsyncActionsModule,
ButtonModule,
DialogService,
IconButtonModule,
SearchModule,
ToastService,
} from "@bitwarden/components";
import {
DefaultSendFormConfigService,
SendFormConfig,
@ -58,6 +66,7 @@ export type AddEditQueryParams = Partial<Record<keyof QueryParams, string>>;
JslibModule,
FormsModule,
ButtonModule,
IconButtonModule,
PopupPageComponent,
PopupHeaderComponent,
PopupFooterComponent,
@ -81,6 +90,9 @@ export class SendAddEditComponent {
private location: Location,
private i18nService: I18nService,
private addEditFormConfigService: SendFormConfigService,
private sendApiService: SendApiService,
private toastService: ToastService,
private dialogService: DialogService,
) {
this.subscribeToParams();
}
@ -92,6 +104,37 @@ export class SendAddEditComponent {
this.location.back();
}
deleteSend = async () => {
const confirmed = await this.dialogService.openSimpleDialog({
title: { key: "deleteSend" },
content: { key: "deleteSendPermanentConfirmation" },
type: "warning",
});
if (!confirmed) {
return;
}
try {
await this.sendApiService.delete(this.config.originalSend?.id);
} catch (e) {
this.toastService.showToast({
variant: "error",
title: null,
message: e.message,
});
return;
}
this.location.back();
this.toastService.showToast({
variant: "success",
title: null,
message: this.i18nService.t("deletedSend"),
});
};
/**
* Subscribes to the route query parameters and builds the configuration based on the parameters.
*/

View File

@ -1,9 +1,13 @@
import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { NoopAnimationsModule } from "@angular/platform-browser/animations";
import { BehaviorSubject } from "rxjs";
import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { UserId } from "@bitwarden/common/types/guid";
import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction";
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
import { Folder } from "@bitwarden/common/vault/models/domain/folder";
@ -25,6 +29,7 @@ describe("AddEditFolderDialogComponent", () => {
const save = jest.fn().mockResolvedValue(null);
const deleteFolder = jest.fn().mockResolvedValue(null);
const openSimpleDialog = jest.fn().mockResolvedValue(true);
const getUserKeyWithLegacySupport = jest.fn().mockResolvedValue("");
const error = jest.fn();
const close = jest.fn();
const showToast = jest.fn();
@ -41,12 +46,29 @@ describe("AddEditFolderDialogComponent", () => {
close.mockClear();
showToast.mockClear();
const userId = "" as UserId;
const accountInfo: AccountInfo = {
email: "",
emailVerified: true,
name: undefined,
};
await TestBed.configureTestingModule({
imports: [AddEditFolderDialogComponent, NoopAnimationsModule],
providers: [
{ provide: I18nService, useValue: { t: (key: string) => key } },
{ provide: FolderService, useValue: { encrypt } },
{ provide: FolderApiServiceAbstraction, useValue: { save, delete: deleteFolder } },
{
provide: AccountService,
useValue: { activeAccount$: new BehaviorSubject({ id: userId, ...accountInfo }) },
},
{
provide: CryptoService,
useValue: {
getUserKeyWithLegacySupport,
},
},
{ provide: LogService, useValue: { error } },
{ provide: ToastService, useValue: { showToast } },
{ provide: DIALOG_DATA, useValue: dialogData },
@ -82,7 +104,7 @@ describe("AddEditFolderDialogComponent", () => {
const newFolder = new FolderView();
newFolder.name = "New Folder";
expect(encrypt).toHaveBeenCalledWith(newFolder);
expect(encrypt).toHaveBeenCalledWith(newFolder, "");
expect(save).toHaveBeenCalled();
});
@ -137,10 +159,13 @@ describe("AddEditFolderDialogComponent", () => {
component.folderForm.controls.name.setValue("Edited Folder");
await component.submit();
expect(encrypt).toHaveBeenCalledWith({
...dialogData.editFolderConfig.folder,
name: "Edited Folder",
});
expect(encrypt).toHaveBeenCalledWith(
{
...dialogData.editFolderConfig.folder,
name: "Edited Folder",
},
"",
);
});
it("deletes the folder", async () => {

View File

@ -11,8 +11,11 @@ import {
} from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
import { firstValueFrom } from "rxjs";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction";
@ -68,6 +71,8 @@ export class AddEditFolderDialogComponent implements AfterViewInit, OnInit {
private formBuilder: FormBuilder,
private folderService: FolderService,
private folderApiService: FolderApiServiceAbstraction,
private accountService: AccountService,
private cryptoService: CryptoService,
private toastService: ToastService,
private i18nService: I18nService,
private logService: LogService,
@ -107,7 +112,9 @@ export class AddEditFolderDialogComponent implements AfterViewInit, OnInit {
this.folder.name = this.folderForm.controls.name.value;
try {
const folder = await this.folderService.encrypt(this.folder);
const activeUserId = await firstValueFrom(this.accountService.activeAccount$);
const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeUserId.id);
const folder = await this.folderService.encrypt(this.folder, userKey);
await this.folderApiService.save(folder);
this.toastService.showToast({

View File

@ -8,6 +8,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -28,6 +29,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent implements On
cipherService: CipherService,
i18nService: I18nService,
cryptoService: CryptoService,
encryptService: EncryptService,
platformUtilsService: PlatformUtilsService,
apiService: ApiService,
private location: Location,
@ -44,6 +46,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent implements On
cipherService,
i18nService,
cryptoService,
encryptService,
platformUtilsService,
apiService,
window,

View File

@ -13,6 +13,7 @@ import { TokenService } from "@bitwarden/common/auth/abstractions/token.service"
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -80,6 +81,7 @@ export class ViewComponent extends BaseViewComponent implements OnInit, OnDestro
tokenService: TokenService,
i18nService: I18nService,
cryptoService: CryptoService,
encryptService: EncryptService,
platformUtilsService: PlatformUtilsService,
auditService: AuditService,
private route: ActivatedRoute,
@ -108,6 +110,7 @@ export class ViewComponent extends BaseViewComponent implements OnInit, OnDestro
tokenService,
i18nService,
cryptoService,
encryptService,
platformUtilsService,
auditService,
window,

View File

@ -4,6 +4,8 @@ import { ActivatedRoute, Router } from "@angular/router";
import { first } from "rxjs/operators";
import { FolderAddEditComponent as BaseFolderAddEditComponent } from "@bitwarden/angular/vault/components/folder-add-edit.component";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.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";
@ -20,6 +22,8 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent implement
constructor(
folderService: FolderService,
folderApiService: FolderApiServiceAbstraction,
accountService: AccountService,
cryptoService: CryptoService,
i18nService: I18nService,
platformUtilsService: PlatformUtilsService,
private router: Router,
@ -31,6 +35,8 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent implement
super(
folderService,
folderApiService,
accountService,
cryptoService,
i18nService,
platformUtilsService,
logService,

View File

@ -1,7 +1,7 @@
{
"name": "@bitwarden/cli",
"description": "A secure and free password manager for all of your devices.",
"version": "2024.9.0",
"version": "2024.9.1",
"keywords": [
"bitwarden",
"password",

View File

@ -1,6 +1,6 @@
import * as fet from "node-fetch";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
@ -9,7 +9,7 @@ import { FileResponse } from "../models/response/file.response";
import { CliUtils } from "../utils";
export abstract class DownloadCommand {
constructor(protected cryptoService: CryptoService) {}
constructor(protected encryptService: EncryptService) {}
protected async saveAttachmentToFile(
url: string,
@ -26,7 +26,7 @@ export abstract class DownloadCommand {
try {
const encBuf = await EncArrayBuffer.fromResponse(response);
const decBuf = await this.cryptoService.decryptFromBytes(encBuf, key);
const decBuf = await this.encryptService.decryptToBytes(encBuf, key);
if (process.env.BW_SERVE === "true") {
const res = new FileResponse(Buffer.from(decBuf), fileName);
return Response.success(res);

View File

@ -7,6 +7,7 @@ import { CipherExport } from "@bitwarden/common/models/export/cipher.export";
import { CollectionExport } from "@bitwarden/common/models/export/collection.export";
import { FolderExport } from "@bitwarden/common/models/export/folder.export";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction";
@ -25,6 +26,7 @@ export class EditCommand {
private cipherService: CipherService,
private folderService: FolderService,
private cryptoService: CryptoService,
private encryptService: EncryptService,
private apiService: ApiService,
private folderApiService: FolderApiServiceAbstraction,
private accountService: AccountService,
@ -139,7 +141,10 @@ export class EditCommand {
let folderView = await folder.decrypt();
folderView = FolderExport.toView(req, folderView);
const encFolder = await this.folderService.encrypt(folderView);
const activeUserId = await firstValueFrom(this.accountService.activeAccount$);
const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeUserId.id);
const encFolder = await this.folderService.encrypt(folderView, userKey);
try {
await this.folderApiService.save(encFolder);
const updatedFolder = await this.folderService.get(folder.id);
@ -187,7 +192,7 @@ export class EditCommand {
(u) => new SelectionReadOnlyRequest(u.id, u.readOnly, u.hidePasswords, u.manage),
);
const request = new CollectionRequest();
request.name = (await this.cryptoService.encrypt(req.name, orgKey)).encryptedString;
request.name = (await this.encryptService.encrypt(req.name, orgKey)).encryptedString;
request.externalId = req.externalId;
request.groups = groups;
request.users = users;

View File

@ -20,6 +20,7 @@ import { LoginExport } from "@bitwarden/common/models/export/login.export";
import { SecureNoteExport } from "@bitwarden/common/models/export/secure-note.export";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
@ -56,7 +57,8 @@ export class GetCommand extends DownloadCommand {
private collectionService: CollectionService,
private totpService: TotpService,
private auditService: AuditService,
cryptoService: CryptoService,
private cryptoService: CryptoService,
encryptService: EncryptService,
private stateService: StateService,
private searchService: SearchService,
private apiService: ApiService,
@ -65,7 +67,7 @@ export class GetCommand extends DownloadCommand {
private accountProfileService: BillingAccountProfileStateService,
private accountService: AccountService,
) {
super(cryptoService);
super(encryptService);
}
async run(object: string, id: string, cmdOptions: Record<string, any>): Promise<Response> {
@ -451,7 +453,7 @@ export class GetCommand extends DownloadCommand {
const response = await this.apiService.getCollectionAccessDetails(options.organizationId, id);
const decCollection = new CollectionView(response);
decCollection.name = await this.cryptoService.decryptToUtf8(
decCollection.name = await this.encryptService.decryptToUtf8(
new EncString(response.name),
orgKey,
);

View File

@ -57,6 +57,7 @@ export class OssServeConfigurator {
this.serviceContainer.totpService,
this.serviceContainer.auditService,
this.serviceContainer.cryptoService,
this.serviceContainer.encryptService,
this.serviceContainer.stateService,
this.serviceContainer.searchService,
this.serviceContainer.apiService,
@ -79,6 +80,7 @@ export class OssServeConfigurator {
this.serviceContainer.cipherService,
this.serviceContainer.folderService,
this.serviceContainer.cryptoService,
this.serviceContainer.encryptService,
this.serviceContainer.apiService,
this.serviceContainer.folderApiService,
this.serviceContainer.billingAccountProfileStateService,
@ -89,6 +91,7 @@ export class OssServeConfigurator {
this.serviceContainer.cipherService,
this.serviceContainer.folderService,
this.serviceContainer.cryptoService,
this.serviceContainer.encryptService,
this.serviceContainer.apiService,
this.serviceContainer.folderApiService,
this.serviceContainer.accountService,
@ -150,7 +153,7 @@ export class OssServeConfigurator {
this.serviceContainer.sendService,
this.serviceContainer.environmentService,
this.serviceContainer.searchService,
this.serviceContainer.cryptoService,
this.serviceContainer.encryptService,
);
this.sendEditCommand = new SendEditCommand(
this.serviceContainer.sendService,

View File

@ -494,6 +494,7 @@ export class ServiceContainer {
this.collectionService = new CollectionService(
this.cryptoService,
this.encryptService,
this.i18nService,
this.stateProvider,
);
@ -631,10 +632,12 @@ export class ServiceContainer {
this.cipherFileUploadService,
this.configService,
this.stateProvider,
this.accountService,
);
this.folderService = new FolderService(
this.cryptoService,
this.encryptService,
this.i18nService,
this.cipherService,
this.stateProvider,
@ -721,6 +724,7 @@ export class ServiceContainer {
this.i18nService,
this.collectionService,
this.cryptoService,
this.encryptService,
this.pinService,
this.accountService,
);
@ -730,8 +734,10 @@ export class ServiceContainer {
this.cipherService,
this.pinService,
this.cryptoService,
this.encryptService,
this.cryptoFunctionService,
this.kdfConfigService,
this.accountService,
);
this.organizationExportService = new OrganizationVaultExportService(
@ -739,6 +745,7 @@ export class ServiceContainer {
this.apiService,
this.pinService,
this.cryptoService,
this.encryptService,
this.cryptoFunctionService,
this.collectionService,
this.kdfConfigService,

View File

@ -2,7 +2,7 @@ import { OptionValues } from "commander";
import { firstValueFrom } from "rxjs";
import { SearchService } from "@bitwarden/common/abstractions/search.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
@ -17,9 +17,9 @@ export class SendGetCommand extends DownloadCommand {
private sendService: SendService,
private environmentService: EnvironmentService,
private searchService: SearchService,
cryptoService: CryptoService,
encryptService: EncryptService,
) {
super(cryptoService);
super(encryptService);
}
async run(id: string, options: OptionValues) {

View File

@ -2,10 +2,10 @@ import { OptionValues } from "commander";
import * as inquirer from "inquirer";
import { firstValueFrom } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
@ -27,14 +27,14 @@ export class SendReceiveCommand extends DownloadCommand {
private sendAccessRequest: SendAccessRequest;
constructor(
private apiService: ApiService,
cryptoService: CryptoService,
private cryptoService: CryptoService,
encryptService: EncryptService,
private cryptoFunctionService: CryptoFunctionService,
private platformUtilsService: PlatformUtilsService,
private environmentService: EnvironmentService,
private sendApiService: SendApiService,
) {
super(cryptoService);
super(encryptService);
}
async run(url: string, options: OptionValues): Promise<Response> {

View File

@ -100,8 +100,8 @@ export class SendProgram extends BaseProgram {
})
.action(async (url: string, options: OptionValues) => {
const cmd = new SendReceiveCommand(
this.serviceContainer.apiService,
this.serviceContainer.cryptoService,
this.serviceContainer.encryptService,
this.serviceContainer.cryptoFunctionService,
this.serviceContainer.platformUtilsService,
this.serviceContainer.environmentService,
@ -143,6 +143,7 @@ export class SendProgram extends BaseProgram {
this.serviceContainer.totpService,
this.serviceContainer.auditService,
this.serviceContainer.cryptoService,
this.serviceContainer.encryptService,
this.serviceContainer.stateService,
this.serviceContainer.searchService,
this.serviceContainer.apiService,
@ -187,7 +188,7 @@ export class SendProgram extends BaseProgram {
this.serviceContainer.sendService,
this.serviceContainer.environmentService,
this.serviceContainer.searchService,
this.serviceContainer.cryptoService,
this.serviceContainer.encryptService,
);
const response = await cmd.run(id, options);
this.processResponse(response);
@ -246,7 +247,7 @@ export class SendProgram extends BaseProgram {
this.serviceContainer.sendService,
this.serviceContainer.environmentService,
this.serviceContainer.searchService,
this.serviceContainer.cryptoService,
this.serviceContainer.encryptService,
);
const cmd = new SendEditCommand(
this.serviceContainer.sendService,

View File

@ -178,6 +178,7 @@ export class VaultProgram extends BaseProgram {
this.serviceContainer.totpService,
this.serviceContainer.auditService,
this.serviceContainer.cryptoService,
this.serviceContainer.encryptService,
this.serviceContainer.stateService,
this.serviceContainer.searchService,
this.serviceContainer.apiService,
@ -224,6 +225,7 @@ export class VaultProgram extends BaseProgram {
this.serviceContainer.cipherService,
this.serviceContainer.folderService,
this.serviceContainer.cryptoService,
this.serviceContainer.encryptService,
this.serviceContainer.apiService,
this.serviceContainer.folderApiService,
this.serviceContainer.billingAccountProfileStateService,
@ -272,6 +274,7 @@ export class VaultProgram extends BaseProgram {
this.serviceContainer.cipherService,
this.serviceContainer.folderService,
this.serviceContainer.cryptoService,
this.serviceContainer.encryptService,
this.serviceContainer.apiService,
this.serviceContainer.folderApiService,
this.serviceContainer.accountService,

View File

@ -12,6 +12,7 @@ import { CipherExport } from "@bitwarden/common/models/export/cipher.export";
import { CollectionExport } from "@bitwarden/common/models/export/collection.export";
import { FolderExport } from "@bitwarden/common/models/export/folder.export";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { FolderApiServiceAbstraction } from "@bitwarden/common/vault/abstractions/folder/folder-api.service.abstraction";
@ -31,6 +32,7 @@ export class CreateCommand {
private cipherService: CipherService,
private folderService: FolderService,
private cryptoService: CryptoService,
private encryptService: EncryptService,
private apiService: ApiService,
private folderApiService: FolderApiServiceAbstraction,
private accountProfileService: BillingAccountProfileStateService,
@ -167,7 +169,9 @@ export class CreateCommand {
}
private async createFolder(req: FolderExport) {
const folder = await this.folderService.encrypt(FolderExport.toView(req));
const activeAccountId = await firstValueFrom(this.accountService.activeAccount$);
const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeAccountId.id);
const folder = await this.folderService.encrypt(FolderExport.toView(req), userKey);
try {
await this.folderApiService.save(folder);
const newFolder = await this.folderService.get(folder.id);
@ -210,7 +214,7 @@ export class CreateCommand {
(u) => new SelectionReadOnlyRequest(u.id, u.readOnly, u.hidePasswords, u.manage),
);
const request = new CollectionRequest();
request.name = (await this.cryptoService.encrypt(req.name, orgKey)).encryptedString;
request.name = (await this.encryptService.encrypt(req.name, orgKey)).encryptedString;
request.externalId = req.externalId;
request.groups = groups;
request.users = users;

View File

@ -1,7 +1,7 @@
{
"name": "@bitwarden/desktop",
"description": "A secure and free password manager for all of your devices.",
"version": "2024.9.1",
"version": "2024.9.2",
"keywords": [
"bitwarden",
"password",

View File

@ -234,7 +234,7 @@ const safeProviders: SafeProvider[] = [
provide: NativeMessageHandlerService,
deps: [
StateServiceAbstraction,
CryptoServiceAbstraction,
EncryptService,
CryptoFunctionServiceAbstraction,
MessagingServiceAbstraction,
EncryptedMessageHandlerService,

View File

@ -1,12 +1,12 @@
{
"name": "@bitwarden/desktop",
"version": "2024.9.1",
"version": "2024.9.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@bitwarden/desktop",
"version": "2024.9.1",
"version": "2024.9.2",
"license": "GPL-3.0",
"dependencies": {
"@bitwarden/desktop-napi": "file:../desktop_native/napi",

View File

@ -2,7 +2,7 @@
"name": "@bitwarden/desktop",
"productName": "Bitwarden",
"description": "A secure and free password manager for all of your devices.",
"version": "2024.9.1",
"version": "2024.9.2",
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)",
"homepage": "https://bitwarden.com",
"license": "GPL-3.0",

View File

@ -3,7 +3,7 @@ import { firstValueFrom } from "rxjs";
import { NativeMessagingVersion } from "@bitwarden/common/enums";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
@ -31,7 +31,7 @@ export class NativeMessageHandlerService {
constructor(
private stateService: StateService,
private cryptoService: CryptoService,
private encryptService: EncryptService,
private cryptoFunctionService: CryptoFunctionService,
private messagingService: MessagingService,
private encryptedMessageHandlerService: EncryptedMessageHandlerService,
@ -162,7 +162,7 @@ export class NativeMessageHandlerService {
payload: DecryptedCommandData,
key: SymmetricCryptoKey,
): Promise<EncString> {
return await this.cryptoService.encrypt(JSON.stringify(payload), key);
return await this.encryptService.encrypt(JSON.stringify(payload), key);
}
private async decryptPayload(message: EncryptedMessage): Promise<DecryptedCommandData> {
@ -182,7 +182,7 @@ export class NativeMessageHandlerService {
}
try {
let decryptedResult = await this.cryptoService.decryptToUtf8(
let decryptedResult = await this.encryptService.decryptToUtf8(
message.encryptedCommand as EncString,
this.ddgSharedSecret,
);

View File

@ -6,6 +6,7 @@ import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { BiometricStateService } from "@bitwarden/common/platform/biometrics/biometric-state.service";
@ -33,6 +34,7 @@ export class NativeMessagingService {
constructor(
private cryptoFunctionService: CryptoFunctionService,
private cryptoService: CryptoService,
private encryptService: EncryptService,
private logService: LogService,
private messagingService: MessagingService,
private desktopSettingService: DesktopSettingsService,
@ -111,7 +113,7 @@ export class NativeMessagingService {
}
const message: LegacyMessage = JSON.parse(
await this.cryptoService.decryptToUtf8(
await this.encryptService.decryptToUtf8(
rawMessage as EncString,
SymmetricCryptoKey.fromString(await ipc.platform.ephemeralStore.getEphemeralValue(appId)),
),
@ -224,7 +226,7 @@ export class NativeMessagingService {
private async send(message: any, appId: string) {
message.timestamp = Date.now();
const encrypted = await this.cryptoService.encrypt(
const encrypted = await this.encryptService.encrypt(
JSON.stringify(message),
SymmetricCryptoKey.fromString(await ipc.platform.ephemeralStore.getEphemeralValue(appId)),
);

View File

@ -5,6 +5,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -22,6 +23,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
cipherService: CipherService,
i18nService: I18nService,
cryptoService: CryptoService,
encryptService: EncryptService,
platformUtilsService: PlatformUtilsService,
apiService: ApiService,
logService: LogService,
@ -36,6 +38,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
cipherService,
i18nService,
cryptoService,
encryptService,
platformUtilsService,
apiService,
window,

View File

@ -2,6 +2,8 @@ import { Component } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { FolderAddEditComponent as BaseFolderAddEditComponent } from "@bitwarden/angular/vault/components/folder-add-edit.component";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.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";
@ -17,6 +19,8 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent {
constructor(
folderService: FolderService,
folderApiService: FolderApiServiceAbstraction,
accountService: AccountService,
cryptoService: CryptoService,
i18nService: I18nService,
platformUtilsService: PlatformUtilsService,
logService: LogService,
@ -26,6 +30,8 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent {
super(
folderService,
folderApiService,
accountService,
cryptoService,
i18nService,
platformUtilsService,
logService,

View File

@ -19,6 +19,7 @@ import { TokenService } from "@bitwarden/common/auth/abstractions/token.service"
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -48,6 +49,7 @@ export class ViewComponent extends BaseViewComponent implements OnInit, OnDestro
tokenService: TokenService,
i18nService: I18nService,
cryptoService: CryptoService,
encryptService: EncryptService,
platformUtilsService: PlatformUtilsService,
auditService: AuditService,
broadcasterService: BroadcasterService,
@ -72,6 +74,7 @@ export class ViewComponent extends BaseViewComponent implements OnInit, OnDestro
tokenService,
i18nService,
cryptoService,
encryptService,
platformUtilsService,
auditService,
window,

View File

@ -1,6 +1,6 @@
{
"name": "@bitwarden/web-vault",
"version": "2024.9.1",
"version": "2024.9.2",
"scripts": {
"build:oss": "webpack",
"build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js",

View File

@ -5,6 +5,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -26,6 +27,7 @@ export class EmergencyAccessAttachmentsComponent extends BaseAttachmentsComponen
cipherService: CipherService,
i18nService: I18nService,
cryptoService: CryptoService,
encryptService: EncryptService,
stateService: StateService,
platformUtilsService: PlatformUtilsService,
apiService: ApiService,
@ -40,6 +42,7 @@ export class EmergencyAccessAttachmentsComponent extends BaseAttachmentsComponen
cipherService,
i18nService,
cryptoService,
encryptService,
platformUtilsService,
apiService,
window,

View File

@ -31,6 +31,7 @@ import { PlanResponse } from "@bitwarden/common/billing/models/response/plan.res
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@ -147,6 +148,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy {
private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService,
private cryptoService: CryptoService,
private encryptService: EncryptService,
private router: Router,
private syncService: SyncService,
private policyService: PolicyService,
@ -590,7 +592,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy {
if (this.createOrganization) {
const orgKey = await this.cryptoService.makeOrgKey<OrgKey>();
const key = orgKey[0].encryptedString;
const collection = await this.cryptoService.encrypt(
const collection = await this.encryptService.encrypt(
this.i18nService.t("defaultCollection"),
orgKey[1],
);
@ -744,7 +746,7 @@ export class OrganizationPlansComponent implements OnInit, OnDestroy {
);
const providerKey = await this.cryptoService.getProviderKey(this.providerId);
providerRequest.organizationCreateRequest.key = (
await this.cryptoService.encrypt(orgKey.key, providerKey)
await this.encryptService.encrypt(orgKey.key, providerKey)
).encryptedString;
const orgId = (
await this.apiService.postProviderCreateOrganization(this.providerId, providerRequest)

View File

@ -1,6 +1,6 @@
import { Component, Input } from "@angular/core";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
@ -26,7 +26,7 @@ export class SendAccessFileComponent {
constructor(
private i18nService: I18nService,
private toastService: ToastService,
private cryptoService: CryptoService,
private encryptService: EncryptService,
private fileDownloadService: FileDownloadService,
private sendApiService: SendApiService,
) {}
@ -62,7 +62,7 @@ export class SendAccessFileComponent {
try {
const encBuf = await EncArrayBuffer.fromResponse(response);
const decBuf = await this.cryptoService.decryptFromBytes(encBuf, this.decKey);
const decBuf = await this.encryptService.decryptToBytes(encBuf, this.decKey);
this.fileDownloadService.download({
fileName: this.send.file.fileName,
blobData: decBuf,

View File

@ -3,6 +3,7 @@ import { Injectable } from "@angular/core";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { SelectionReadOnlyRequest } from "@bitwarden/common/admin-console/models/request/selection-read-only.request";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
import { CollectionData } from "@bitwarden/common/vault/models/data/collection.data";
@ -23,6 +24,7 @@ export class CollectionAdminService {
constructor(
private apiService: ApiService,
private cryptoService: CryptoService,
private encryptService: EncryptService,
private collectionService: CollectionService,
) {}
@ -116,7 +118,7 @@ export class CollectionAdminService {
const promises = collections.map(async (c) => {
const view = new CollectionAdminView();
view.id = c.id;
view.name = await this.cryptoService.decryptToUtf8(new EncString(c.name), orgKey);
view.name = await this.encryptService.decryptToUtf8(new EncString(c.name), orgKey);
view.externalId = c.externalId;
view.organizationId = c.organizationId;
@ -146,7 +148,7 @@ export class CollectionAdminService {
}
const collection = new CollectionRequest();
collection.externalId = model.externalId;
collection.name = (await this.cryptoService.encrypt(model.name, key)).encryptedString;
collection.name = (await this.encryptService.encrypt(model.name, key)).encryptedString;
collection.groups = model.groups.map(
(group) =>
new SelectionReadOnlyRequest(group.id, group.readOnly, group.hidePasswords, group.manage),

View File

@ -5,6 +5,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -25,6 +26,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
cipherService: CipherService,
i18nService: I18nService,
cryptoService: CryptoService,
encryptService: EncryptService,
stateService: StateService,
platformUtilsService: PlatformUtilsService,
apiService: ApiService,
@ -39,6 +41,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
cipherService,
i18nService,
cryptoService,
encryptService,
platformUtilsService,
apiService,
window,

View File

@ -1,8 +1,11 @@
import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog";
import { Component, Inject } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { firstValueFrom } from "rxjs";
import { FolderAddEditComponent as BaseFolderAddEditComponent } from "@bitwarden/angular/vault/components/folder-add-edit.component";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.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";
@ -19,6 +22,8 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent {
constructor(
folderService: FolderService,
folderApiService: FolderApiServiceAbstraction,
protected accountSerivce: AccountService,
protected cryptoService: CryptoService,
i18nService: I18nService,
platformUtilsService: PlatformUtilsService,
logService: LogService,
@ -31,6 +36,8 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent {
super(
folderService,
folderApiService,
accountSerivce,
cryptoService,
i18nService,
platformUtilsService,
logService,
@ -73,7 +80,9 @@ export class FolderAddEditComponent extends BaseFolderAddEditComponent {
}
try {
const folder = await this.folderService.encrypt(this.folder);
const activeAccountId = (await firstValueFrom(this.accountSerivce.activeAccount$)).id;
const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeAccountId);
const folder = await this.folderService.encrypt(this.folder, userKey);
this.formPromise = this.folderApiService.save(folder);
await this.formPromise;
this.platformUtilsService.showToast(

View File

@ -5,6 +5,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -31,6 +32,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent implements On
cipherService: CipherService,
i18nService: I18nService,
cryptoService: CryptoService,
encryptService: EncryptService,
stateService: StateService,
platformUtilsService: PlatformUtilsService,
apiService: ApiService,
@ -45,6 +47,7 @@ export class AttachmentsComponent extends BaseAttachmentsComponent implements On
cipherService,
i18nService,
cryptoService,
encryptService,
stateService,
platformUtilsService,
apiService,

View File

@ -11,7 +11,6 @@ import { ActivatedRoute, Params, Router } from "@angular/router";
import {
BehaviorSubject,
combineLatest,
defer,
firstValueFrom,
lastValueFrom,
Observable,
@ -283,27 +282,10 @@ export class VaultComponent implements OnInit, OnDestroy {
this.currentSearchText$ = this.route.queryParams.pipe(map((queryParams) => queryParams.search));
this.allCollectionsWithoutUnassigned$ = combineLatest([
organizationId$.pipe(switchMap((orgId) => this.collectionAdminService.getAll(orgId))),
defer(() => this.collectionService.getAllDecrypted()),
]).pipe(
map(([adminCollections, syncCollections]) => {
const syncCollectionDict = Object.fromEntries(syncCollections.map((c) => [c.id, c]));
return adminCollections.map((collection) => {
const currentId: any = collection.id;
const match = syncCollectionDict[currentId];
if (match) {
collection.manage = match.manage;
collection.readOnly = match.readOnly;
collection.hidePasswords = match.hidePasswords;
}
return collection;
});
}),
shareReplay({ refCount: true, bufferSize: 1 }),
this.allCollectionsWithoutUnassigned$ = this.refresh$.pipe(
switchMap(() => organizationId$),
switchMap((orgId) => this.collectionAdminService.getAll(orgId)),
shareReplay({ refCount: false, bufferSize: 1 }),
);
this.editableCollections$ = this.allCollectionsWithoutUnassigned$.pipe(
@ -367,7 +349,6 @@ export class VaultComponent implements OnInit, OnDestroy {
map((ciphers) => {
return Object.fromEntries(ciphers.map((c) => [c.id, c]));
}),
shareReplay({ refCount: true, bufferSize: 1 }),
);
const nestedCollections$ = allCollections$.pipe(

View File

@ -18,6 +18,7 @@ export class ServiceContainer extends OssServiceContainer {
this.organizationAuthRequestService = new OrganizationAuthRequestService(
this.organizationAuthRequestApiService,
this.cryptoService,
this.encryptService,
this.organizationUserApiService,
);
}

View File

@ -6,6 +6,7 @@ import {
} from "@bitwarden/admin-console/common";
import { ListResponse } from "@bitwarden/common/models/response/list.response";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { OrganizationAuthRequestApiService } from "./organization-auth-request-api.service";
@ -16,16 +17,19 @@ import { PendingAuthRequestView } from "./pending-auth-request.view";
describe("OrganizationAuthRequestService", () => {
let organizationAuthRequestApiService: MockProxy<OrganizationAuthRequestApiService>;
let cryptoService: MockProxy<CryptoService>;
let encryptService: MockProxy<EncryptService>;
let organizationUserApiService: MockProxy<OrganizationUserApiService>;
let organizationAuthRequestService: OrganizationAuthRequestService;
beforeEach(() => {
organizationAuthRequestApiService = mock<OrganizationAuthRequestApiService>();
cryptoService = mock<CryptoService>();
encryptService = mock<EncryptService>();
organizationUserApiService = mock<OrganizationUserApiService>();
organizationAuthRequestService = new OrganizationAuthRequestService(
organizationAuthRequestApiService,
cryptoService,
encryptService,
organizationUserApiService,
);
});

View File

@ -3,6 +3,7 @@ import {
OrganizationUserResetPasswordDetailsResponse,
} from "@bitwarden/admin-console/common";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
@ -15,6 +16,7 @@ export class OrganizationAuthRequestService {
constructor(
private organizationAuthRequestApiService: OrganizationAuthRequestApiService,
private cryptoService: CryptoService,
private encryptService: EncryptService,
private organizationUserApiService: OrganizationUserApiService,
) {}
@ -109,7 +111,7 @@ export class OrganizationAuthRequestService {
// Decrypt Organization's encrypted Private Key with org key
const orgSymKey = await this.cryptoService.getOrgKey(organizationId);
const decOrgPrivateKey = await this.cryptoService.decryptToBytes(
const decOrgPrivateKey = await this.encryptService.decryptToBytes(
new EncString(encryptedOrgPrivateKey),
orgSymKey,
);

View File

@ -10,6 +10,7 @@ import { PendingAuthRequestView } from "@bitwarden/bit-common/admin-console/auth
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.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";
@ -30,7 +31,12 @@ import { SharedModule } from "@bitwarden/web-vault/app/shared/shared.module";
}),
safeProvider({
provide: OrganizationAuthRequestService,
deps: [OrganizationAuthRequestApiService, CryptoService, OrganizationUserApiService],
deps: [
OrganizationAuthRequestApiService,
CryptoService,
EncryptService,
OrganizationUserApiService,
],
}),
] satisfies SafeProvider[],
imports: [SharedModule, NoItemsModule, LooseComponentsModule],

View File

@ -27,7 +27,7 @@ export class WebProviderService {
const orgKey = await this.cryptoService.getOrgKey(organizationId);
const providerKey = await this.cryptoService.getProviderKey(providerId);
const encryptedOrgKey = await this.cryptoService.encrypt(orgKey.key, providerKey);
const encryptedOrgKey = await this.encryptService.encrypt(orgKey.key, providerKey);
const request = new ProviderAddOrganizationRequest();
request.organizationId = organizationId;

View File

@ -449,6 +449,7 @@ const safeProviders: SafeProvider[] = [
fileUploadService: CipherFileUploadServiceAbstraction,
configService: ConfigService,
stateProvider: StateProvider,
accountService: AccountServiceAbstraction,
) =>
new CipherService(
cryptoService,
@ -463,6 +464,7 @@ const safeProviders: SafeProvider[] = [
fileUploadService,
configService,
stateProvider,
accountService,
),
deps: [
CryptoServiceAbstraction,
@ -477,6 +479,7 @@ const safeProviders: SafeProvider[] = [
CipherFileUploadServiceAbstraction,
ConfigService,
StateProvider,
AccountServiceAbstraction,
],
}),
safeProvider({
@ -484,6 +487,7 @@ const safeProviders: SafeProvider[] = [
useClass: FolderService,
deps: [
CryptoServiceAbstraction,
EncryptService,
I18nServiceAbstraction,
CipherServiceAbstraction,
StateProvider,
@ -527,7 +531,7 @@ const safeProviders: SafeProvider[] = [
safeProvider({
provide: CollectionServiceAbstraction,
useClass: CollectionService,
deps: [CryptoServiceAbstraction, I18nServiceAbstraction, StateProvider],
deps: [CryptoServiceAbstraction, EncryptService, I18nServiceAbstraction, StateProvider],
}),
safeProvider({
provide: EnvironmentService,
@ -785,6 +789,7 @@ const safeProviders: SafeProvider[] = [
I18nServiceAbstraction,
CollectionServiceAbstraction,
CryptoServiceAbstraction,
EncryptService,
PinServiceAbstraction,
AccountServiceAbstraction,
],
@ -797,8 +802,10 @@ const safeProviders: SafeProvider[] = [
CipherServiceAbstraction,
PinServiceAbstraction,
CryptoServiceAbstraction,
EncryptService,
CryptoFunctionServiceAbstraction,
KdfConfigServiceAbstraction,
AccountServiceAbstraction,
],
}),
safeProvider({
@ -809,6 +816,7 @@ const safeProviders: SafeProvider[] = [
ApiServiceAbstraction,
PinServiceAbstraction,
CryptoServiceAbstraction,
EncryptService,
CryptoFunctionServiceAbstraction,
CollectionServiceAbstraction,
KdfConfigServiceAbstraction,

View File

@ -329,6 +329,11 @@ export class AddEditComponent implements OnInit, OnDestroy {
this.cipher.card.expYear = normalizeExpiryYearFormat(this.cipher.card.expYear);
}
// trim whitespace from the TOTP field
if (this.cipher.type === this.cipherType.Login && this.cipher.login.totp) {
this.cipher.login.totp = this.cipher.login.totp.trim();
}
if (this.cipher.name == null || this.cipher.name === "") {
this.platformUtilsService.showToast(
"error",

View File

@ -6,6 +6,7 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -40,6 +41,7 @@ export class AttachmentsComponent implements OnInit {
protected cipherService: CipherService,
protected i18nService: I18nService,
protected cryptoService: CryptoService,
protected encryptService: EncryptService,
protected platformUtilsService: PlatformUtilsService,
protected apiService: ApiService,
protected win: Window,
@ -178,7 +180,7 @@ export class AttachmentsComponent implements OnInit {
attachment.key != null
? attachment.key
: await this.cryptoService.getOrgKey(this.cipher.organizationId);
const decBuf = await this.cryptoService.decryptFromBytes(encBuf, key);
const decBuf = await this.encryptService.decryptToBytes(encBuf, key);
this.fileDownloadService.download({
fileName: attachment.fileName,
blobData: decBuf,
@ -249,7 +251,7 @@ export class AttachmentsComponent implements OnInit {
attachment.key != null
? attachment.key
: await this.cryptoService.getOrgKey(this.cipher.organizationId);
const decBuf = await this.cryptoService.decryptFromBytes(encBuf, key);
const decBuf = await this.encryptService.decryptToBytes(encBuf, key);
const activeUserId = await firstValueFrom(
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
);

View File

@ -1,6 +1,9 @@
import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core";
import { Validators, FormBuilder } from "@angular/forms";
import { firstValueFrom } from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.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";
@ -29,6 +32,8 @@ export class FolderAddEditComponent implements OnInit {
constructor(
protected folderService: FolderService,
protected folderApiService: FolderApiServiceAbstraction,
protected accountService: AccountService,
protected cryptoService: CryptoService,
protected i18nService: I18nService,
protected platformUtilsService: PlatformUtilsService,
protected logService: LogService,
@ -52,7 +57,9 @@ export class FolderAddEditComponent implements OnInit {
}
try {
const folder = await this.folderService.encrypt(this.folder);
const activeAccountId = await firstValueFrom(this.accountService.activeAccount$);
const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeAccountId.id);
const folder = await this.folderService.encrypt(this.folder, userKey);
this.formPromise = this.folderApiService.save(folder);
await this.formPromise;
this.platformUtilsService.showToast(

View File

@ -21,6 +21,7 @@ import { EventType } from "@bitwarden/common/enums";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@ -87,6 +88,7 @@ export class ViewComponent implements OnDestroy, OnInit {
protected tokenService: TokenService,
protected i18nService: I18nService,
protected cryptoService: CryptoService,
protected encryptService: EncryptService,
protected platformUtilsService: PlatformUtilsService,
protected auditService: AuditService,
protected win: Window,
@ -442,7 +444,7 @@ export class ViewComponent implements OnDestroy, OnInit {
attachment.key != null
? attachment.key
: await this.cryptoService.getOrgKey(this.cipher.organizationId);
const decBuf = await this.cryptoService.decryptFromBytes(encBuf, key);
const decBuf = await this.encryptService.decryptToBytes(encBuf, key);
this.fileDownloadService.download({
fileName: attachment.fileName,
blobData: decBuf,

View File

@ -12,6 +12,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -37,6 +38,7 @@ describe("AuthRequestLoginStrategy", () => {
let cache: AuthRequestLoginStrategyData;
let cryptoService: MockProxy<CryptoService>;
let encryptService: MockProxy<EncryptService>;
let apiService: MockProxy<ApiService>;
let tokenService: MockProxy<TokenService>;
let appIdService: MockProxy<AppIdService>;
@ -101,6 +103,7 @@ describe("AuthRequestLoginStrategy", () => {
accountService,
masterPasswordService,
cryptoService,
encryptService,
apiService,
tokenService,
appIdService,

View File

@ -22,6 +22,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -104,6 +105,7 @@ describe("LoginStrategy", () => {
let loginStrategyService: MockProxy<LoginStrategyServiceAbstraction>;
let cryptoService: MockProxy<CryptoService>;
let encryptService: MockProxy<EncryptService>;
let apiService: MockProxy<ApiService>;
let tokenService: MockProxy<TokenService>;
let appIdService: MockProxy<AppIdService>;
@ -128,6 +130,7 @@ describe("LoginStrategy", () => {
loginStrategyService = mock<LoginStrategyServiceAbstraction>();
cryptoService = mock<CryptoService>();
encryptService = mock<EncryptService>();
apiService = mock<ApiService>();
tokenService = mock<TokenService>();
appIdService = mock<AppIdService>();
@ -156,6 +159,7 @@ describe("LoginStrategy", () => {
accountService,
masterPasswordService,
cryptoService,
encryptService,
apiService,
tokenService,
appIdService,
@ -467,6 +471,7 @@ describe("LoginStrategy", () => {
accountService,
masterPasswordService,
cryptoService,
encryptService,
apiService,
tokenService,
appIdService,

View File

@ -26,6 +26,7 @@ import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action
import { KeysRequest } from "@bitwarden/common/models/request/keys.request";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -66,6 +67,7 @@ export abstract class LoginStrategy {
protected accountService: AccountService,
protected masterPasswordService: InternalMasterPasswordServiceAbstraction,
protected cryptoService: CryptoService,
protected encryptService: EncryptService,
protected apiService: ApiService,
protected tokenService: TokenService,
protected appIdService: AppIdService,

View File

@ -16,6 +16,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -63,6 +64,7 @@ describe("PasswordLoginStrategy", () => {
let loginStrategyService: MockProxy<LoginStrategyServiceAbstraction>;
let cryptoService: MockProxy<CryptoService>;
let encryptService: MockProxy<EncryptService>;
let apiService: MockProxy<ApiService>;
let tokenService: MockProxy<TokenService>;
let appIdService: MockProxy<AppIdService>;
@ -88,6 +90,7 @@ describe("PasswordLoginStrategy", () => {
loginStrategyService = mock<LoginStrategyServiceAbstraction>();
cryptoService = mock<CryptoService>();
encryptService = mock<EncryptService>();
apiService = mock<ApiService>();
tokenService = mock<TokenService>();
appIdService = mock<AppIdService>();
@ -127,6 +130,7 @@ describe("PasswordLoginStrategy", () => {
accountService,
masterPasswordService,
cryptoService,
encryptService,
apiService,
tokenService,
appIdService,

View File

@ -17,6 +17,7 @@ import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@ -44,6 +45,7 @@ describe("SsoLoginStrategy", () => {
let masterPasswordService: FakeMasterPasswordService;
let cryptoService: MockProxy<CryptoService>;
let encryptService: MockProxy<EncryptService>;
let apiService: MockProxy<ApiService>;
let tokenService: MockProxy<TokenService>;
let appIdService: MockProxy<AppIdService>;
@ -78,6 +80,7 @@ describe("SsoLoginStrategy", () => {
masterPasswordService = new FakeMasterPasswordService();
cryptoService = mock<CryptoService>();
encryptService = mock<EncryptService>();
apiService = mock<ApiService>();
tokenService = mock<TokenService>();
appIdService = mock<AppIdService>();
@ -125,6 +128,7 @@ describe("SsoLoginStrategy", () => {
accountService,
masterPasswordService,
cryptoService,
encryptService,
apiService,
tokenService,
appIdService,

View File

@ -11,6 +11,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import {
Environment,
EnvironmentService,
@ -39,6 +40,7 @@ describe("UserApiLoginStrategy", () => {
let masterPasswordService: FakeMasterPasswordService;
let cryptoService: MockProxy<CryptoService>;
let encryptService: MockProxy<EncryptService>;
let apiService: MockProxy<ApiService>;
let tokenService: MockProxy<TokenService>;
let appIdService: MockProxy<AppIdService>;
@ -99,6 +101,7 @@ describe("UserApiLoginStrategy", () => {
accountService,
masterPasswordService,
cryptoService,
encryptService,
apiService,
tokenService,
appIdService,

View File

@ -14,6 +14,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs
import { VaultTimeoutAction } from "@bitwarden/common/enums/vault-timeout-action.enum";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -37,6 +38,7 @@ describe("WebAuthnLoginStrategy", () => {
let masterPasswordService: FakeMasterPasswordService;
let cryptoService!: MockProxy<CryptoService>;
let encryptService!: MockProxy<EncryptService>;
let apiService!: MockProxy<ApiService>;
let tokenService!: MockProxy<TokenService>;
let appIdService!: MockProxy<AppIdService>;
@ -79,6 +81,7 @@ describe("WebAuthnLoginStrategy", () => {
masterPasswordService = new FakeMasterPasswordService();
cryptoService = mock<CryptoService>();
encryptService = mock<EncryptService>();
apiService = mock<ApiService>();
tokenService = mock<TokenService>();
appIdService = mock<AppIdService>();
@ -103,6 +106,7 @@ describe("WebAuthnLoginStrategy", () => {
accountService,
masterPasswordService,
cryptoService,
encryptService,
apiService,
tokenService,
appIdService,
@ -221,7 +225,7 @@ describe("WebAuthnLoginStrategy", () => {
const mockUserKeyArray: Uint8Array = randomBytes(32);
const mockUserKey = new SymmetricCryptoKey(mockUserKeyArray) as UserKey;
cryptoService.decryptToBytes.mockResolvedValue(mockPrfPrivateKey);
encryptService.decryptToBytes.mockResolvedValue(mockPrfPrivateKey);
cryptoService.rsaDecrypt.mockResolvedValue(mockUserKeyArray);
// Act
@ -235,8 +239,8 @@ describe("WebAuthnLoginStrategy", () => {
userId,
);
expect(cryptoService.decryptToBytes).toHaveBeenCalledTimes(1);
expect(cryptoService.decryptToBytes).toHaveBeenCalledWith(
expect(encryptService.decryptToBytes).toHaveBeenCalledTimes(1);
expect(encryptService.decryptToBytes).toHaveBeenCalledWith(
idTokenResponse.userDecryptionOptions.webAuthnPrfOption.encryptedPrivateKey,
webAuthnCredentials.prfKey,
);
@ -268,7 +272,7 @@ describe("WebAuthnLoginStrategy", () => {
await webAuthnLoginStrategy.logIn(webAuthnCredentials);
// Assert
expect(cryptoService.decryptToBytes).not.toHaveBeenCalled();
expect(encryptService.decryptToBytes).not.toHaveBeenCalled();
expect(cryptoService.rsaDecrypt).not.toHaveBeenCalled();
expect(cryptoService.setUserKey).not.toHaveBeenCalled();
});
@ -303,7 +307,7 @@ describe("WebAuthnLoginStrategy", () => {
apiService.postIdentityToken.mockResolvedValue(idTokenResponse);
cryptoService.decryptToBytes.mockResolvedValue(null);
encryptService.decryptToBytes.mockResolvedValue(null);
// Act
await webAuthnLoginStrategy.logIn(webAuthnCredentials);

View File

@ -80,7 +80,7 @@ export class WebAuthnLoginStrategy extends LoginStrategy {
}
// decrypt prf encrypted private key
const privateKey = await this.cryptoService.decryptToBytes(
const privateKey = await this.encryptService.decryptToBytes(
webAuthnPrfOption.encryptedPrivateKey,
credentials.prfKey,
);

View File

@ -317,6 +317,7 @@ export class LoginStrategyService implements LoginStrategyServiceAbstraction {
this.accountService,
this.masterPasswordService,
this.cryptoService,
this.encryptService,
this.apiService,
this.tokenService,
this.appIdService,

View File

@ -15,7 +15,6 @@ import {
UserPublicKey,
} from "../../types/key";
import { KeySuffixOptions, HashPurpose } from "../enums";
import { EncArrayBuffer } from "../models/domain/enc-array-buffer";
import { EncString } from "../models/domain/enc-string";
import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key";
@ -373,37 +372,6 @@ export abstract class CryptoService {
* @param userId The desired user
*/
abstract clearDeprecatedKeys(keySuffix: KeySuffixOptions, userId?: string): Promise<void>;
/**
* @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey)
* and then call encryptService.encrypt
*/
abstract encrypt(plainValue: string | Uint8Array, key?: SymmetricCryptoKey): Promise<EncString>;
/**
* @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey)
* and then call encryptService.encryptToBytes
*/
abstract encryptToBytes(
plainValue: Uint8Array,
key?: SymmetricCryptoKey,
): Promise<EncArrayBuffer>;
/**
* @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey)
* and then call encryptService.decryptToBytes
*/
abstract decryptToBytes(encString: EncString, key?: SymmetricCryptoKey): Promise<Uint8Array>;
/**
* @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey)
* and then call encryptService.decryptToUtf8
*/
abstract decryptToUtf8(encString: EncString, key?: SymmetricCryptoKey): Promise<string>;
/**
* @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey)
* and then call encryptService.decryptToBytes
*/
abstract decryptFromBytes(
encBuffer: EncArrayBuffer,
key: SymmetricCryptoKey,
): Promise<Uint8Array>;
/**
* Retrieves all the keys needed for decrypting Ciphers

View File

@ -48,7 +48,6 @@ import { StateService } from "../abstractions/state.service";
import { KeySuffixOptions, HashPurpose, EncryptionType } from "../enums";
import { convertValues } from "../misc/convert-values";
import { EFFLongWordList } from "../misc/wordlist";
import { EncArrayBuffer } from "../models/domain/enc-array-buffer";
import { EncString, EncryptedString } from "../models/domain/enc-string";
import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key";
import { ActiveUserState, StateProvider } from "../state";
@ -859,58 +858,6 @@ export class CryptoService implements CryptoServiceAbstraction {
}
}
// --DEPRECATED METHODS--
/**
* @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey)
* and then call encryptService.encrypt
*/
async encrypt(plainValue: string | Uint8Array, key?: SymmetricCryptoKey): Promise<EncString> {
key ||= await this.getUserKeyWithLegacySupport();
return await this.encryptService.encrypt(plainValue, key);
}
/**
* @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey)
* and then call encryptService.encryptToBytes
*/
async encryptToBytes(plainValue: Uint8Array, key?: SymmetricCryptoKey): Promise<EncArrayBuffer> {
key ||= await this.getUserKeyWithLegacySupport();
return this.encryptService.encryptToBytes(plainValue, key);
}
/**
* @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey)
* and then call encryptService.decryptToBytes
*/
async decryptToBytes(encString: EncString, key?: SymmetricCryptoKey): Promise<Uint8Array> {
key ||= await this.getUserKeyWithLegacySupport();
return this.encryptService.decryptToBytes(encString, key);
}
/**
* @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey)
* and then call encryptService.decryptToUtf8
*/
async decryptToUtf8(encString: EncString, key?: SymmetricCryptoKey): Promise<string> {
key ||= await this.getUserKeyWithLegacySupport();
return await this.encryptService.decryptToUtf8(encString, key);
}
/**
* @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey)
* and then call encryptService.decryptToBytes
*/
async decryptFromBytes(encBuffer: EncArrayBuffer, key: SymmetricCryptoKey): Promise<Uint8Array> {
if (encBuffer == null) {
throw new Error("No buffer provided for decryption.");
}
key ||= await this.getUserKeyWithLegacySupport();
return this.encryptService.decryptToBytes(encBuffer, key);
}
userKey$(userId: UserId): Observable<UserKey> {
return this.stateProvider.getUser(userId, USER_KEY).state$;
}

View File

@ -1,5 +1,8 @@
import { mock } from "jest-mock-extended";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { UserKey } from "@bitwarden/common/types/key";
import { makeStaticByteArray, mockEnc } from "../../../../../spec";
import { CryptoService } from "../../../../platform/abstractions/crypto.service";
import { EncryptService } from "../../../../platform/abstractions/encrypt.service";
@ -89,6 +92,7 @@ describe("Send", () => {
it("Decrypt", async () => {
const text = mock<SendText>();
text.decrypt.mockResolvedValue("textView" as any);
const userKey = new SymmetricCryptoKey(new Uint8Array(32)) as UserKey;
const send = new Send();
send.id = "id";
@ -106,13 +110,13 @@ describe("Send", () => {
send.disabled = false;
send.hideEmail = true;
const encryptService = mock<EncryptService>();
const cryptoService = mock<CryptoService>();
cryptoService.decryptToBytes
.calledWith(send.key, null)
encryptService.decryptToBytes
.calledWith(send.key, userKey)
.mockResolvedValue(makeStaticByteArray(32));
cryptoService.makeSendKey.mockResolvedValue("cryptoKey" as any);
const encryptService = mock<EncryptService>();
cryptoService.getUserKey.mockResolvedValue(userKey);
(window as any).bitwardenContainerService = new ContainerService(cryptoService, encryptService);

View File

@ -73,9 +73,11 @@ export class Send extends Domain {
const model = new SendView(this);
const cryptoService = Utils.getContainerService().getCryptoService();
const encryptService = Utils.getContainerService().getEncryptService();
try {
model.key = await cryptoService.decryptToBytes(this.key, null);
const sendKeyEncryptionKey = await cryptoService.getUserKey();
model.key = await encryptService.decryptToBytes(this.key, sendKeyEncryptionKey);
model.cryptoKey = await cryptoService.makeSendKey(model.key);
} catch (e) {
// TODO: error?

View File

@ -15,7 +15,7 @@ export abstract class FolderService implements UserKeyRotationDataProvider<Folde
folderViews$: Observable<FolderView[]>;
clearCache: () => Promise<void>;
encrypt: (model: FolderView, key?: SymmetricCryptoKey) => Promise<Folder>;
encrypt: (model: FolderView, key: SymmetricCryptoKey) => Promise<Folder>;
get: (id: string) => Promise<Folder>;
getDecrypted$: (id: string) => Observable<FolderView | undefined>;
getAllFromState: () => Promise<Folder[]>;

View File

@ -145,6 +145,7 @@ describe("Cipher Service", () => {
cipherFileUploadService,
configService,
stateProvider,
accountService,
);
cipherObj = new Cipher(cipherData);
@ -273,7 +274,7 @@ describe("Cipher Service", () => {
cryptoService.makeCipherKey.mockReturnValue(
Promise.resolve(new SymmetricCryptoKey(makeStaticByteArray(64)) as CipherKey),
);
cryptoService.encrypt.mockImplementation(encryptText);
encryptService.encrypt.mockImplementation(encryptText);
jest.spyOn(cipherService as any, "getAutofillOnPageLoadDefault").mockResolvedValue(true);
});
@ -285,6 +286,10 @@ describe("Cipher Service", () => {
{ uri: "uri", match: UriMatchStrategy.RegularExpression } as LoginUriView,
];
cryptoService.getOrgKey.mockReturnValue(
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
);
const domain = await cipherService.encrypt(cipherView, userId);
expect(domain.login.uris).toEqual([
@ -301,6 +306,9 @@ describe("Cipher Service", () => {
it("is null when feature flag is false", async () => {
configService.getFeatureFlag.mockResolvedValue(false);
cryptoService.getOrgKey.mockReturnValue(
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
);
const cipher = await cipherService.encrypt(cipherView, userId);
expect(cipher.key).toBeNull();
@ -322,6 +330,9 @@ describe("Cipher Service", () => {
it("is not called when feature flag is false", async () => {
configService.getFeatureFlag.mockResolvedValue(false);
cryptoService.getOrgKey.mockReturnValue(
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
);
await cipherService.encrypt(cipherView, userId);
@ -330,6 +341,9 @@ describe("Cipher Service", () => {
it("is called when feature flag is true", async () => {
configService.getFeatureFlag.mockResolvedValue(true);
cryptoService.getOrgKey.mockReturnValue(
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
);
await cipherService.encrypt(cipherView, userId);

View File

@ -1,6 +1,7 @@
import { firstValueFrom, map, Observable, skipWhile, switchMap } from "rxjs";
import { SemVer } from "semver";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { BulkEncryptService } from "@bitwarden/common/platform/abstractions/bulk-encrypt.service";
@ -108,6 +109,7 @@ export class CipherService implements CipherServiceAbstraction {
private cipherFileUploadService: CipherFileUploadService,
private configService: ConfigService,
private stateProvider: StateProvider,
private accountService: AccountService,
) {
this.localDataState = this.stateProvider.getActive(LOCAL_DATA_KEY);
this.encryptedCiphersState = this.stateProvider.getActive(ENCRYPTED_CIPHERS);
@ -165,7 +167,7 @@ export class CipherService implements CipherServiceAbstraction {
async encrypt(
model: CipherView,
userId: UserId,
keyForEncryption?: SymmetricCryptoKey,
keyForCipherEncryption?: SymmetricCryptoKey,
keyForCipherKeyDecryption?: SymmetricCryptoKey,
originalCipher: Cipher = null,
): Promise<Cipher> {
@ -195,26 +197,21 @@ export class CipherService implements CipherServiceAbstraction {
const userOrOrgKey = await this.getKeyForCipherKeyDecryption(cipher, userId);
// The keyForEncryption is only used for encrypting the cipher key, not the cipher itself, since cipher key encryption is enabled.
// If the caller has provided a key for cipher key encryption, use it. Otherwise, use the user or org key.
keyForEncryption ||= userOrOrgKey;
keyForCipherEncryption ||= userOrOrgKey;
// If the caller has provided a key for cipher key decryption, use it. Otherwise, use the user or org key.
keyForCipherKeyDecryption ||= userOrOrgKey;
return this.encryptCipherWithCipherKey(
model,
cipher,
keyForEncryption,
keyForCipherEncryption,
keyForCipherKeyDecryption,
);
} else {
if (keyForEncryption == null && cipher.organizationId != null) {
keyForEncryption = await this.cryptoService.getOrgKey(cipher.organizationId);
if (keyForEncryption == null) {
throw new Error("Cannot encrypt cipher for organization. No key.");
}
}
keyForCipherEncryption ||= await this.getKeyForCipherKeyDecryption(cipher, userId);
// We want to ensure that the cipher key is null if cipher key encryption is disabled
// so that decryption uses the proper key.
cipher.key = null;
return this.encryptCipher(model, cipher, keyForEncryption);
return this.encryptCipher(model, cipher, keyForCipherEncryption);
}
}
@ -243,7 +240,7 @@ export class CipherService implements CipherServiceAbstraction {
key,
).then(async () => {
if (model.key != null) {
attachment.key = await this.cryptoService.encrypt(model.key.key, key);
attachment.key = await this.encryptService.encrypt(model.key.key, key);
}
encAttachments.push(attachment);
});
@ -1348,7 +1345,9 @@ export class CipherService implements CipherServiceAbstraction {
}
const encBuf = await EncArrayBuffer.fromResponse(attachmentResponse);
const decBuf = await this.cryptoService.decryptFromBytes(encBuf, null);
const activeUserId = await firstValueFrom(this.accountService.activeAccount$);
const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeUserId.id);
const decBuf = await this.encryptService.decryptToBytes(encBuf, userKey);
let encKey: UserKey | OrgKey;
encKey = await this.cryptoService.getOrgKey(organizationId);
@ -1412,7 +1411,7 @@ export class CipherService implements CipherServiceAbstraction {
.then(() => {
const modelProp = (model as any)[map[theProp] || theProp];
if (modelProp && modelProp !== "") {
return self.cryptoService.encrypt(modelProp, key);
return self.encryptService.encrypt(modelProp, key);
}
return null;
})
@ -1458,7 +1457,7 @@ export class CipherService implements CipherServiceAbstraction {
key,
);
const uriHash = await this.encryptService.hash(model.login.uris[i].uri, "sha256");
loginUri.uriChecksum = await this.cryptoService.encrypt(uriHash, key);
loginUri.uriChecksum = await this.encryptService.encrypt(uriHash, key);
cipher.login.uris.push(loginUri);
}
}
@ -1485,8 +1484,8 @@ export class CipherService implements CipherServiceAbstraction {
},
key,
);
domainKey.counter = await this.cryptoService.encrypt(String(viewKey.counter), key);
domainKey.discoverable = await this.cryptoService.encrypt(
domainKey.counter = await this.encryptService.encrypt(String(viewKey.counter), key);
domainKey.discoverable = await this.encryptService.encrypt(
String(viewKey.discoverable),
key,
);
@ -1605,11 +1604,23 @@ export class CipherService implements CipherServiceAbstraction {
this.sortedCiphersCache.clear();
}
/**
* Encrypts a cipher object.
* @param model The cipher view model.
* @param cipher The cipher object.
* @param key The encryption key to encrypt with. This can be the org key, user key or cipher key, but must never be null
*/
private async encryptCipher(
model: CipherView,
cipher: Cipher,
key: SymmetricCryptoKey,
): Promise<Cipher> {
if (key == null) {
throw new Error(
"Key to encrypt cipher must not be null. Use the org key, user key or cipher key.",
);
}
await Promise.all([
this.encryptObjProperty(
model,

View File

@ -1,6 +1,8 @@
import { firstValueFrom, map, Observable } from "rxjs";
import { Jsonify } from "type-fest";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { CryptoService } from "../../platform/abstractions/crypto.service";
import { I18nService } from "../../platform/abstractions/i18n.service";
import { Utils } from "../../platform/misc/utils";
@ -61,6 +63,7 @@ export class CollectionService implements CollectionServiceAbstraction {
constructor(
private cryptoService: CryptoService,
private encryptService: EncryptService,
private i18nService: I18nService,
protected stateProvider: StateProvider,
) {
@ -101,7 +104,7 @@ export class CollectionService implements CollectionServiceAbstraction {
collection.organizationId = model.organizationId;
collection.readOnly = model.readOnly;
collection.externalId = model.externalId;
collection.name = await this.cryptoService.encrypt(model.name, key);
collection.name = await this.encryptService.encrypt(model.name, key);
return collection;
}

View File

@ -49,7 +49,13 @@ describe("Folder Service", () => {
);
encryptService.decryptToUtf8.mockResolvedValue("DEC");
folderService = new FolderService(cryptoService, i18nService, cipherService, stateProvider);
folderService = new FolderService(
cryptoService,
encryptService,
i18nService,
cipherService,
stateProvider,
);
folderState = stateProvider.activeUser.getFake(FOLDER_ENCRYPTED_FOLDERS);
@ -62,9 +68,9 @@ describe("Folder Service", () => {
model.id = "2";
model.name = "Test Folder";
cryptoService.encrypt.mockResolvedValue(new EncString("ENC"));
encryptService.encrypt.mockResolvedValue(new EncString("ENC"));
const result = await folderService.encrypt(model);
const result = await folderService.encrypt(model, null);
expect(result).toEqual({
id: "2",
@ -185,7 +191,7 @@ describe("Folder Service", () => {
beforeEach(() => {
encryptedKey = new EncString("Re-encrypted Folder");
cryptoService.encrypt.mockResolvedValue(encryptedKey);
encryptService.encrypt.mockResolvedValue(encryptedKey);
});
it("returns re-encrypted user folders", async () => {

View File

@ -1,5 +1,7 @@
import { Observable, firstValueFrom, map, shareReplay } from "rxjs";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { CryptoService } from "../../../platform/abstractions/crypto.service";
import { I18nService } from "../../../platform/abstractions/i18n.service";
import { Utils } from "../../../platform/misc/utils";
@ -25,6 +27,7 @@ export class FolderService implements InternalFolderServiceAbstraction {
constructor(
private cryptoService: CryptoService,
private encryptService: EncryptService,
private i18nService: I18nService,
private cipherService: CipherService,
private stateProvider: StateProvider,
@ -48,10 +51,10 @@ export class FolderService implements InternalFolderServiceAbstraction {
}
// TODO: This should be moved to EncryptService or something
async encrypt(model: FolderView, key?: SymmetricCryptoKey): Promise<Folder> {
async encrypt(model: FolderView, key: SymmetricCryptoKey): Promise<Folder> {
const folder = new Folder();
folder.id = model.id;
folder.name = await this.cryptoService.encrypt(model.name, key);
folder.name = await this.encryptService.encrypt(model.name, key);
return folder;
}

View File

@ -3,6 +3,7 @@ import { mock, MockProxy } from "jest-mock-extended";
import { PinServiceAbstraction } from "@bitwarden/auth/common";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { KdfType } from "@bitwarden/common/platform/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils";
@ -19,6 +20,7 @@ import { emptyUnencryptedExport } from "./test-data/bitwarden-json/unencrypted.j
describe("BitwardenPasswordProtectedImporter", () => {
let importer: BitwardenPasswordProtectedImporter;
let cryptoService: MockProxy<CryptoService>;
let encryptService: MockProxy<EncryptService>;
let i18nService: MockProxy<I18nService>;
let cipherService: MockProxy<CipherService>;
let pinService: MockProxy<PinServiceAbstraction>;
@ -30,6 +32,7 @@ describe("BitwardenPasswordProtectedImporter", () => {
beforeEach(() => {
cryptoService = mock<CryptoService>();
encryptService = mock<EncryptService>();
i18nService = mock<I18nService>();
cipherService = mock<CipherService>();
pinService = mock<PinServiceAbstraction>();
@ -37,6 +40,7 @@ describe("BitwardenPasswordProtectedImporter", () => {
importer = new BitwardenPasswordProtectedImporter(
cryptoService,
encryptService,
i18nService,
cipherService,
pinService,
@ -91,7 +95,7 @@ describe("BitwardenPasswordProtectedImporter", () => {
});
it("succeeds with default jdoc", async () => {
cryptoService.decryptToUtf8.mockReturnValue(Promise.resolve(emptyUnencryptedExport));
encryptService.decryptToUtf8.mockReturnValue(Promise.resolve(emptyUnencryptedExport));
expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(true);
});

View File

@ -30,6 +30,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { ClientType } from "@bitwarden/common/enums";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.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";
@ -89,6 +90,7 @@ const safeProviders: SafeProvider[] = [
I18nService,
CollectionService,
CryptoService,
EncryptService,
PinServiceAbstraction,
AccountService,
],

View File

@ -8,8 +8,10 @@ import {
FolderWithIdExport,
} from "@bitwarden/common/models/export";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { OrganizationId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
@ -31,6 +33,7 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
protected constructor(
protected cryptoService: CryptoService,
protected encryptService: EncryptService,
protected i18nService: I18nService,
protected cipherService: CipherService,
protected pinService: PinServiceAbstraction,
@ -60,11 +63,16 @@ export class BitwardenJsonImporter extends BaseImporter implements Importer {
results: BitwardenEncryptedIndividualJsonExport | BitwardenEncryptedOrgJsonExport,
) {
if (results.encKeyValidation_DO_NOT_EDIT != null) {
const orgKey = await this.cryptoService.getOrgKey(this.organizationId);
let keyForDecryption: SymmetricCryptoKey = await this.cryptoService.getOrgKey(
this.organizationId,
);
if (keyForDecryption == null) {
keyForDecryption = await this.cryptoService.getUserKeyWithLegacySupport();
}
const encKeyValidation = new EncString(results.encKeyValidation_DO_NOT_EDIT);
const encKeyValidationDecrypt = await this.cryptoService.decryptToUtf8(
const encKeyValidationDecrypt = await this.encryptService.decryptToUtf8(
encKeyValidation,
orgKey,
keyForDecryption,
);
if (encKeyValidationDecrypt === null) {
this.result.success = false;

View File

@ -6,6 +6,7 @@ import {
PBKDF2KdfConfig,
} from "@bitwarden/common/auth/models/domain/kdf-config";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { KdfType } from "@bitwarden/common/platform/enums";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
@ -23,13 +24,14 @@ export class BitwardenPasswordProtectedImporter extends BitwardenJsonImporter im
constructor(
cryptoService: CryptoService,
encryptService: EncryptService,
i18nService: I18nService,
cipherService: CipherService,
pinService: PinServiceAbstraction,
accountService: AccountService,
private promptForPassword_callback: () => Promise<string>,
) {
super(cryptoService, i18nService, cipherService, pinService, accountService);
super(cryptoService, encryptService, i18nService, cipherService, pinService, accountService);
}
async parse(data: string): Promise<ImportResult> {
@ -65,7 +67,7 @@ export class BitwardenPasswordProtectedImporter extends BitwardenJsonImporter im
}
const encData = new EncString(parsedData.data);
const clearTextData = await this.cryptoService.decryptToUtf8(encData, this.key);
const clearTextData = await this.encryptService.decryptToUtf8(encData, this.key);
return await super.parse(clearTextData);
}
@ -86,7 +88,7 @@ export class BitwardenPasswordProtectedImporter extends BitwardenJsonImporter im
const encKeyValidation = new EncString(jdoc.encKeyValidation_DO_NOT_EDIT);
const encKeyValidationDecrypt = await this.cryptoService.decryptToUtf8(
const encKeyValidationDecrypt = await this.encryptService.decryptToUtf8(
encKeyValidation,
this.key,
);

View File

@ -3,6 +3,7 @@ import { mock, MockProxy } from "jest-mock-extended";
import { PinServiceAbstraction } from "@bitwarden/auth/common";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
@ -27,6 +28,7 @@ describe("ImportService", () => {
let i18nService: MockProxy<I18nService>;
let collectionService: MockProxy<CollectionService>;
let cryptoService: MockProxy<CryptoService>;
let encryptService: MockProxy<EncryptService>;
let pinService: MockProxy<PinServiceAbstraction>;
let accountService: MockProxy<AccountService>;
@ -37,6 +39,7 @@ describe("ImportService", () => {
i18nService = mock<I18nService>();
collectionService = mock<CollectionService>();
cryptoService = mock<CryptoService>();
encryptService = mock<EncryptService>();
pinService = mock<PinServiceAbstraction>();
importService = new ImportService(
@ -46,6 +49,7 @@ describe("ImportService", () => {
i18nService,
collectionService,
cryptoService,
encryptService,
pinService,
accountService,
);

View File

@ -7,6 +7,7 @@ import { ImportOrganizationCiphersRequest } from "@bitwarden/common/models/reque
import { KvpRequest } from "@bitwarden/common/models/request/kvp.request";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
@ -104,6 +105,7 @@ export class ImportService implements ImportServiceAbstraction {
private i18nService: I18nService,
private collectionService: CollectionService,
private cryptoService: CryptoService,
private encryptService: EncryptService,
private pinService: PinServiceAbstraction,
private accountService: AccountService,
) {}
@ -207,6 +209,7 @@ export class ImportService implements ImportServiceAbstraction {
case "bitwardenpasswordprotected":
return new BitwardenPasswordProtectedImporter(
this.cryptoService,
this.encryptService,
this.i18nService,
this.cipherService,
this.pinService,
@ -344,9 +347,10 @@ export class ImportService implements ImportServiceAbstraction {
const c = await this.cipherService.encrypt(importResult.ciphers[i], activeUserId);
request.ciphers.push(new CipherRequest(c));
}
const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeUserId);
if (importResult.folders != null) {
for (let i = 0; i < importResult.folders.length; i++) {
const f = await this.folderService.encrypt(importResult.folders[i]);
const f = await this.folderService.encrypt(importResult.folders[i], userKey);
request.folders.push(new FolderWithIdRequest(f));
}
}

View File

@ -2,7 +2,7 @@ import { PinServiceAbstraction } from "@bitwarden/auth/common";
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { KdfType } from "@bitwarden/common/platform/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { CipherType } from "@bitwarden/common/vault/enums";
@ -12,7 +12,7 @@ import { BitwardenCsvExportType, BitwardenPasswordProtectedFileFormat } from "..
export class BaseVaultExportService {
constructor(
protected pinService: PinServiceAbstraction,
protected cryptoService: CryptoService,
protected encryptService: EncryptService,
private cryptoFunctionService: CryptoFunctionService,
private kdfConfigService: KdfConfigService,
) {}
@ -23,8 +23,8 @@ export class BaseVaultExportService {
const salt = Utils.fromBufferToB64(await this.cryptoFunctionService.randomBytes(16));
const key = await this.pinService.makePinKey(password, salt, kdfConfig);
const encKeyValidation = await this.cryptoService.encrypt(Utils.newGuid(), key);
const encText = await this.cryptoService.encrypt(clearText, key);
const encKeyValidation = await this.encryptService.encrypt(Utils.newGuid(), key);
const encText = await this.encryptService.encrypt(clearText, key);
const jsonDoc: BitwardenPasswordProtectedFileFormat = {
encrypted: true,

View File

@ -1,6 +1,8 @@
import { mock, MockProxy } from "jest-mock-extended";
import { BehaviorSubject } from "rxjs";
import { PinServiceAbstraction } from "@bitwarden/auth/common";
import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import {
DEFAULT_KDF_CONFIG,
@ -9,9 +11,11 @@ import {
import { CipherWithIdExport } from "@bitwarden/common/models/export/cipher-with-ids.export";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { KdfType } from "@bitwarden/common/platform/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { UserId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
import { CipherType } from "@bitwarden/common/vault/enums";
@ -149,7 +153,9 @@ describe("VaultExportService", () => {
let pinService: MockProxy<PinServiceAbstraction>;
let folderService: MockProxy<FolderService>;
let cryptoService: MockProxy<CryptoService>;
let encryptService: MockProxy<EncryptService>;
let kdfConfigService: MockProxy<KdfConfigService>;
let accountService: MockProxy<AccountService>;
beforeEach(() => {
cryptoFunctionService = mock<CryptoFunctionService>();
@ -157,20 +163,35 @@ describe("VaultExportService", () => {
pinService = mock<PinServiceAbstraction>();
folderService = mock<FolderService>();
cryptoService = mock<CryptoService>();
encryptService = mock<EncryptService>();
kdfConfigService = mock<KdfConfigService>();
accountService = mock<AccountService>();
cryptoService.userKey$.mockReturnValue(new BehaviorSubject("mockOriginalUserKey" as any));
const userId = "" as UserId;
const accountInfo: AccountInfo = {
email: "",
emailVerified: true,
name: undefined,
};
const activeAccount = { id: userId, ...accountInfo };
accountService.activeAccount$ = new BehaviorSubject(activeAccount);
folderService.getAllDecryptedFromState.mockResolvedValue(UserFolderViews);
folderService.getAllFromState.mockResolvedValue(UserFolders);
kdfConfigService.getKdfConfig.mockResolvedValue(DEFAULT_KDF_CONFIG);
cryptoService.encrypt.mockResolvedValue(new EncString("encrypted"));
encryptService.encrypt.mockResolvedValue(new EncString("encrypted"));
exportService = new IndividualVaultExportService(
folderService,
cipherService,
pinService,
cryptoService,
encryptService,
cryptoFunctionService,
kdfConfigService,
accountService,
);
});
@ -250,7 +271,7 @@ describe("VaultExportService", () => {
});
it("has a mac property", async () => {
cryptoService.encrypt.mockResolvedValue(mac);
encryptService.encrypt.mockResolvedValue(mac);
exportString = await exportService.getPasswordProtectedExport(password);
exportObject = JSON.parse(exportString);
@ -258,7 +279,7 @@ describe("VaultExportService", () => {
});
it("has data property", async () => {
cryptoService.encrypt.mockResolvedValue(data);
encryptService.encrypt.mockResolvedValue(data);
exportString = await exportService.getPasswordProtectedExport(password);
exportObject = JSON.parse(exportString);

View File

@ -1,10 +1,13 @@
import * as papa from "papaparse";
import { firstValueFrom, map } from "rxjs";
import { PinServiceAbstraction } from "@bitwarden/auth/common";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import { CipherWithIdExport, FolderWithIdExport } from "@bitwarden/common/models/export";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
@ -32,11 +35,13 @@ export class IndividualVaultExportService
private folderService: FolderService,
private cipherService: CipherService,
pinService: PinServiceAbstraction,
cryptoService: CryptoService,
private cryptoService: CryptoService,
encryptService: EncryptService,
cryptoFunctionService: CryptoFunctionService,
kdfConfigService: KdfConfigService,
private accountService: AccountService,
) {
super(pinService, cryptoService, cryptoFunctionService, kdfConfigService);
super(pinService, encryptService, cryptoFunctionService, kdfConfigService);
}
async getExport(format: ExportFormat = "csv"): Promise<string> {
@ -96,7 +101,11 @@ export class IndividualVaultExportService
await Promise.all(promises);
const encKeyValidation = await this.cryptoService.encrypt(Utils.newGuid());
const activeUserId = await firstValueFrom(
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
);
const userKey = await this.cryptoService.getUserKeyWithLegacySupport(activeUserId);
const encKeyValidation = await this.encryptService.encrypt(Utils.newGuid(), userKey);
const jsonDoc: BitwardenEncryptedIndividualJsonExport = {
encrypted: true,

View File

@ -8,6 +8,7 @@ import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config
import { CipherWithIdExport, CollectionWithIdExport } from "@bitwarden/common/models/export";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { OrganizationId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
@ -39,13 +40,14 @@ export class OrganizationVaultExportService
private cipherService: CipherService,
private apiService: ApiService,
pinService: PinServiceAbstraction,
cryptoService: CryptoService,
private cryptoService: CryptoService,
encryptService: EncryptService,
cryptoFunctionService: CryptoFunctionService,
private collectionService: CollectionService,
kdfConfigService: KdfConfigService,
private accountService: AccountService,
) {
super(pinService, cryptoService, cryptoFunctionService, kdfConfigService);
super(pinService, encryptService, cryptoFunctionService, kdfConfigService);
}
async getPasswordProtectedExport(
@ -242,7 +244,7 @@ export class OrganizationVaultExportService
ciphers: Cipher[],
): Promise<string> {
const orgKey = await this.cryptoService.getOrgKey(organizationId);
const encKeyValidation = await this.cryptoService.encrypt(Utils.newGuid(), orgKey);
const encKeyValidation = await this.encryptService.encrypt(Utils.newGuid(), orgKey);
const jsonDoc: BitwardenEncryptedOrgJsonExport = {
encrypted: true,

View File

@ -1,6 +1,8 @@
import { mock, MockProxy } from "jest-mock-extended";
import { BehaviorSubject } from "rxjs";
import { PinServiceAbstraction } from "@bitwarden/auth/common";
import { AccountInfo, AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
import {
DEFAULT_KDF_CONFIG,
@ -9,9 +11,11 @@ import {
import { CipherWithIdExport } from "@bitwarden/common/models/export/cipher-with-ids.export";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { KdfType } from "@bitwarden/common/platform/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { UserId } from "@bitwarden/common/types/guid";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
import { CipherType } from "@bitwarden/common/vault/enums";
@ -149,6 +153,8 @@ describe("VaultExportService", () => {
let pinService: MockProxy<PinServiceAbstraction>;
let folderService: MockProxy<FolderService>;
let cryptoService: MockProxy<CryptoService>;
let encryptService: MockProxy<EncryptService>;
let accountService: MockProxy<AccountService>;
let kdfConfigService: MockProxy<KdfConfigService>;
beforeEach(() => {
@ -157,20 +163,34 @@ describe("VaultExportService", () => {
pinService = mock<PinServiceAbstraction>();
folderService = mock<FolderService>();
cryptoService = mock<CryptoService>();
encryptService = mock<EncryptService>();
accountService = mock<AccountService>();
kdfConfigService = mock<KdfConfigService>();
folderService.getAllDecryptedFromState.mockResolvedValue(UserFolderViews);
folderService.getAllFromState.mockResolvedValue(UserFolders);
kdfConfigService.getKdfConfig.mockResolvedValue(DEFAULT_KDF_CONFIG);
cryptoService.encrypt.mockResolvedValue(new EncString("encrypted"));
encryptService.encrypt.mockResolvedValue(new EncString("encrypted"));
cryptoService.userKey$.mockReturnValue(new BehaviorSubject("mockOriginalUserKey" as any));
const userId = "" as UserId;
const accountInfo: AccountInfo = {
email: "",
emailVerified: true,
name: undefined,
};
const activeAccount = { id: userId, ...accountInfo };
accountService.activeAccount$ = new BehaviorSubject(activeAccount);
exportService = new IndividualVaultExportService(
folderService,
cipherService,
pinService,
cryptoService,
encryptService,
cryptoFunctionService,
kdfConfigService,
accountService,
);
});
@ -250,7 +270,7 @@ describe("VaultExportService", () => {
});
it("has a mac property", async () => {
cryptoService.encrypt.mockResolvedValue(mac);
encryptService.encrypt.mockResolvedValue(mac);
exportString = await exportService.getPasswordProtectedExport(password);
exportObject = JSON.parse(exportString);
@ -258,7 +278,7 @@ describe("VaultExportService", () => {
});
it("has data property", async () => {
cryptoService.encrypt.mockResolvedValue(data);
encryptService.encrypt.mockResolvedValue(data);
exportString = await exportService.getPasswordProtectedExport(password);
exportObject = JSON.parse(exportString);

View File

@ -1,6 +1,6 @@
<bit-section [formGroup]="sendOptionsForm">
<bit-section-header>
<h2 class="tw-mt-4" bitTypography="h5">{{ "additionalOptions" | i18n }}</h2>
<h2 class="tw-mt-4" bitTypography="h6">{{ "additionalOptions" | i18n }}</h2>
</bit-section-header>
<bit-card>
<bit-form-field>
@ -16,16 +16,21 @@
<bit-label *ngIf="hasPassword">{{ "newPassword" | i18n }}</bit-label>
<input bitInput type="password" formControlName="password" />
<button type="button" bitIconButton bitSuffix bitPasswordInputToggle></button>
<button type="button" bitIconButton="bwi-refresh" bitSuffix></button>
<button
type="button"
bitIconButton="bwi-generate"
bitSuffix
[appA11yTitle]="'generatePassword' | i18n"
></button>
<bit-hint>{{ "sendPasswordDescV2" | i18n }}</bit-hint>
</bit-form-field>
<bit-form-control *ngIf="!disableHideEmail">
<input bitCheckbox type="checkbox" formControlName="hideEmail" />
<bit-label>{{ "hideYourEmail" | i18n }}</bit-label>
</bit-form-control>
<bit-form-field>
<bit-form-field disableMargin>
<bit-label>{{ "privateNote" | i18n }}</bit-label>
<textarea bitInput rows="4" formControlName="notes"></textarea>
<textarea bitInput rows="3" formControlName="notes"></textarea>
</bit-form-field>
</bit-card>
</bit-section>

View File

@ -102,7 +102,7 @@ export class SendOptionsComponent implements OnInit {
this.sendOptionsForm.patchValue({
maxAccessCount: this.sendFormContainer.originalSendView.maxAccessCount,
accessCount: this.sendFormContainer.originalSendView.accessCount,
password: this.sendFormContainer.originalSendView.password,
password: null,
hideEmail: this.sendFormContainer.originalSendView.hideEmail,
notes: this.sendFormContainer.originalSendView.notes,
});

View File

@ -1,6 +1,6 @@
<bit-section [formGroup]="sendDetailsForm">
<bit-section-header class="tw-mt-4">
<h2 bitTypography="h5">{{ "sendDetails" | i18n }}</h2>
<bit-section-header class="tw-mt-2">
<h2 bitTypography="h6">{{ "sendDetails" | i18n }}</h2>
</bit-section-header>
<bit-card>
@ -34,7 +34,7 @@
></button>
</bit-form-field>
<bit-form-field>
<bit-form-field disableMargin>
<bit-label>{{ "deletionDate" | i18n }}</bit-label>
<bit-select
id="deletionDate"

View File

@ -1,20 +1,22 @@
<bit-section [formGroup]="sendFileDetailsForm">
<div *ngIf="config.mode === 'edit'">
<div class="tw-text-muted">{{ "file" | i18n }}</div>
<div bitTypography="body2" class="tw-text-muted">{{ "file" | i18n }}</div>
<div>{{ originalSendView.file.fileName }}</div>
<div class="tw-text-muted">{{ originalSendView.file.sizeName }}</div>
</div>
<bit-form-field *ngIf="config.mode !== 'edit'">
<bit-label for="file">{{ "fileToShare" | i18n }}</bit-label>
<button bitButton type="button" buttonType="primary" (click)="fileSelector.click()">
{{ "chooseFile" | i18n }}
</button>
<span
class="tw-flex tw-items-center tw-pl-3"
[ngClass]="fileName ? 'tw-text-main' : 'tw-text-muted'"
>
{{ fileName || ("noFileChosen" | i18n) }}</span
>
<div class="tw-flex tw-mt-2 tw-mb-1">
<button bitButton type="button" buttonType="secondary" (click)="fileSelector.click()">
{{ "chooseFile" | i18n }}
</button>
<span
class="tw-flex tw-items-center tw-pl-3"
[ngClass]="fileName ? 'tw-text-main' : 'tw-text-muted'"
>
{{ fileName || ("noFileChosen" | i18n) }}</span
>
</div>
<input
bitInput
#fileSelector

View File

@ -7,7 +7,12 @@ import { JslibModule } from "@bitwarden/angular/jslib.module";
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
import { SendFileView } from "@bitwarden/common/tools/send/models/view/send-file.view";
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
import { ButtonModule, FormFieldModule, SectionComponent } from "@bitwarden/components";
import {
ButtonModule,
FormFieldModule,
SectionComponent,
TypographyModule,
} from "@bitwarden/components";
import { SendFormConfig } from "../../abstractions/send-form-config.service";
import { SendFormContainer } from "../../send-form-container";
@ -24,6 +29,7 @@ import { SendFormContainer } from "../../send-form-container";
FormFieldModule,
SectionComponent,
FormsModule,
TypographyModule,
],
})
export class SendFileDetailsComponent implements OnInit {

View File

@ -16,6 +16,7 @@ import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { FormBuilder, ReactiveFormsModule } from "@angular/forms";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
import {
@ -199,6 +200,10 @@ export class SendFormComponent implements AfterViewInit, OnInit, OnChanges, Send
return;
}
if (Utils.isNullOrWhitespace(this.updatedSendView.password)) {
this.updatedSendView.password = null;
}
await this.addEditFormService.saveSend(this.updatedSendView, this.file, this.config);
this.toastService.showToast({

View File

@ -64,7 +64,7 @@ export class SendListItemsContainerComponent {
async deleteSend(s: SendView): Promise<boolean> {
const confirmed = await this.dialogService.openSimpleDialog({
title: { key: "deleteSend" },
content: { key: "deleteSendConfirmation" },
content: { key: "deleteSendPermanentConfirmation" },
type: "warning",
});

View File

@ -125,7 +125,7 @@ export class LoginDetailsSectionComponent implements OnInit {
Object.assign(cipher.login, {
username: value.username,
password: value.password,
totp: value.totp,
totp: value.totp?.trim(),
} as LoginView);
return cipher;

8
package-lock.json generated
View File

@ -192,11 +192,11 @@
},
"apps/browser": {
"name": "@bitwarden/browser",
"version": "2024.9.1"
"version": "2024.9.2"
},
"apps/cli": {
"name": "@bitwarden/cli",
"version": "2024.9.0",
"version": "2024.9.1",
"license": "SEE LICENSE IN LICENSE.txt",
"dependencies": {
"@koa/multer": "3.0.2",
@ -232,7 +232,7 @@
},
"apps/desktop": {
"name": "@bitwarden/desktop",
"version": "2024.9.1",
"version": "2024.9.2",
"hasInstallScript": true,
"license": "GPL-3.0"
},
@ -246,7 +246,7 @@
},
"apps/web": {
"name": "@bitwarden/web-vault",
"version": "2024.9.1"
"version": "2024.9.2"
},
"libs/admin-console": {
"name": "@bitwarden/admin-console",