mirror of
https://github.com/bitwarden/browser
synced 2026-02-12 06:23:38 +00:00
Merge remote-tracking branch 'origin/main' into ps/pm-15333/portable-desktop
This commit is contained in:
@@ -34,6 +34,8 @@ export class ShareCommand {
|
||||
if (req == null || req.length === 0) {
|
||||
return Response.badRequest("You must provide at least one collection id for this item.");
|
||||
}
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
return Response.badRequest("Error parsing the encoded request data.");
|
||||
}
|
||||
|
||||
@@ -165,6 +165,8 @@ export class LoginCommand {
|
||||
if (options.method != null) {
|
||||
twoFactorMethod = parseInt(options.method, null);
|
||||
}
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
return Response.error("Invalid two-step login method.");
|
||||
}
|
||||
@@ -240,6 +242,8 @@ export class LoginCommand {
|
||||
if (twoFactorMethod != null) {
|
||||
try {
|
||||
selectedProvider = twoFactorProviders.filter((p) => p.type === twoFactorMethod)[0];
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
return Response.error("Invalid two-step login method.");
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ 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";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { Folder } from "@bitwarden/common/vault/models/domain/folder";
|
||||
import { KeyService } from "@bitwarden/key-management";
|
||||
|
||||
import { OrganizationCollectionRequest } from "../admin-console/models/request/organization-collection.request";
|
||||
@@ -24,6 +25,8 @@ import { CipherResponse } from "../vault/models/cipher.response";
|
||||
import { FolderResponse } from "../vault/models/folder.response";
|
||||
|
||||
export class EditCommand {
|
||||
private activeUserId$ = this.accountService.activeAccount$.pipe(map((a) => a?.id));
|
||||
|
||||
constructor(
|
||||
private cipherService: CipherService,
|
||||
private folderService: FolderService,
|
||||
@@ -55,6 +58,8 @@ export class EditCommand {
|
||||
try {
|
||||
const reqJson = Buffer.from(requestJson, "base64").toString();
|
||||
req = JSON.parse(reqJson);
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
return Response.badRequest("Error parsing the encoded request data.");
|
||||
}
|
||||
@@ -121,12 +126,12 @@ export class EditCommand {
|
||||
|
||||
cipher.collectionIds = req;
|
||||
try {
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const updatedCipher = await this.cipherService.saveCollectionsWithServer(cipher);
|
||||
const decCipher = await updatedCipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(updatedCipher, activeUserId),
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(
|
||||
updatedCipher,
|
||||
await firstValueFrom(this.activeUserId$),
|
||||
),
|
||||
);
|
||||
const res = new CipherResponse(decCipher);
|
||||
return Response.success(res);
|
||||
@@ -136,7 +141,8 @@ export class EditCommand {
|
||||
}
|
||||
|
||||
private async editFolder(id: string, req: FolderExport) {
|
||||
const folder = await this.folderService.getFromState(id);
|
||||
const activeUserId = await firstValueFrom(this.activeUserId$);
|
||||
const folder = await this.folderService.getFromState(id, activeUserId);
|
||||
if (folder == null) {
|
||||
return Response.notFound();
|
||||
}
|
||||
@@ -144,12 +150,11 @@ export class EditCommand {
|
||||
let folderView = await folder.decrypt();
|
||||
folderView = FolderExport.toView(req, folderView);
|
||||
|
||||
const activeUserId = await firstValueFrom(this.accountService.activeAccount$);
|
||||
const userKey = await this.keyService.getUserKeyWithLegacySupport(activeUserId.id);
|
||||
const userKey = await this.keyService.getUserKeyWithLegacySupport(activeUserId);
|
||||
const encFolder = await this.folderService.encrypt(folderView, userKey);
|
||||
try {
|
||||
await this.folderApiService.save(encFolder);
|
||||
const updatedFolder = await this.folderService.get(folder.id);
|
||||
const folder = await this.folderApiService.save(encFolder, activeUserId);
|
||||
const updatedFolder = new Folder(folder);
|
||||
const decFolder = await updatedFolder.decrypt();
|
||||
const res = new FolderResponse(decFolder);
|
||||
return Response.success(res);
|
||||
|
||||
@@ -51,6 +51,8 @@ import { FolderResponse } from "../vault/models/folder.response";
|
||||
import { DownloadCommand } from "./download.command";
|
||||
|
||||
export class GetCommand extends DownloadCommand {
|
||||
private activeUserId$ = this.accountService.activeAccount$.pipe(map((a) => a?.id));
|
||||
|
||||
constructor(
|
||||
private cipherService: CipherService,
|
||||
private folderService: FolderService,
|
||||
@@ -113,10 +115,8 @@ export class GetCommand extends DownloadCommand {
|
||||
let decCipher: CipherView = null;
|
||||
if (Utils.isGuid(id)) {
|
||||
const cipher = await this.cipherService.get(id);
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
if (cipher != null) {
|
||||
const activeUserId = await firstValueFrom(this.activeUserId$);
|
||||
decCipher = await cipher.decrypt(
|
||||
await this.cipherService.getKeyForCipherKeyDecryption(cipher, activeUserId),
|
||||
);
|
||||
@@ -152,11 +152,9 @@ export class GetCommand extends DownloadCommand {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this.eventCollectionService.collect(
|
||||
await this.eventCollectionService.collect(
|
||||
EventType.Cipher_ClientViewed,
|
||||
id,
|
||||
decCipher.id,
|
||||
true,
|
||||
decCipher.organizationId,
|
||||
);
|
||||
@@ -262,8 +260,9 @@ export class GetCommand extends DownloadCommand {
|
||||
return Response.error("Couldn't generate TOTP code.");
|
||||
}
|
||||
|
||||
const account = await firstValueFrom(this.accountService.activeAccount$);
|
||||
const canAccessPremium = await firstValueFrom(
|
||||
this.accountProfileService.hasPremiumFromAnySource$,
|
||||
this.accountProfileService.hasPremiumFromAnySource$(account.id),
|
||||
);
|
||||
if (!canAccessPremium) {
|
||||
const originalCipher = await this.cipherService.get(cipher.id);
|
||||
@@ -347,8 +346,9 @@ export class GetCommand extends DownloadCommand {
|
||||
return Response.multipleResults(attachments.map((a) => a.id));
|
||||
}
|
||||
|
||||
const account = await firstValueFrom(this.accountService.activeAccount$);
|
||||
const canAccessPremium = await firstValueFrom(
|
||||
this.accountProfileService.hasPremiumFromAnySource$,
|
||||
this.accountProfileService.hasPremiumFromAnySource$(account.id),
|
||||
);
|
||||
if (!canAccessPremium) {
|
||||
const originalCipher = await this.cipherService.get(cipher.id);
|
||||
@@ -383,13 +383,14 @@ export class GetCommand extends DownloadCommand {
|
||||
|
||||
private async getFolder(id: string) {
|
||||
let decFolder: FolderView = null;
|
||||
const activeUserId = await firstValueFrom(this.activeUserId$);
|
||||
if (Utils.isGuid(id)) {
|
||||
const folder = await this.folderService.getFromState(id);
|
||||
const folder = await this.folderService.getFromState(id, activeUserId);
|
||||
if (folder != null) {
|
||||
decFolder = await folder.decrypt();
|
||||
}
|
||||
} else if (id.trim() !== "") {
|
||||
let folders = await this.folderService.getAllDecryptedFromState();
|
||||
let folders = await this.folderService.getAllDecryptedFromState(activeUserId);
|
||||
folders = CliUtils.searchFolders(folders, id);
|
||||
if (folders.length > 1) {
|
||||
return Response.multipleResults(folders.map((f) => f.id));
|
||||
@@ -551,9 +552,7 @@ export class GetCommand extends DownloadCommand {
|
||||
private async getFingerprint(id: string) {
|
||||
let fingerprint: string[] = null;
|
||||
if (id === "me") {
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const activeUserId = await firstValueFrom(this.activeUserId$);
|
||||
const publicKey = await firstValueFrom(this.keyService.userPublicKey$(activeUserId));
|
||||
fingerprint = await this.keyService.getFingerprint(activeUserId, publicKey);
|
||||
} else if (Utils.isGuid(id)) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { firstValueFrom } from "rxjs";
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
|
||||
import {
|
||||
OrganizationUserApiService,
|
||||
@@ -12,6 +12,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
import { ListResponse as ApiListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
@@ -38,6 +39,7 @@ export class ListCommand {
|
||||
private organizationUserApiService: OrganizationUserApiService,
|
||||
private apiService: ApiService,
|
||||
private eventCollectionService: EventCollectionService,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
|
||||
async run(object: string, cmdOptions: Record<string, any>): Promise<Response> {
|
||||
@@ -135,7 +137,10 @@ export class ListCommand {
|
||||
}
|
||||
|
||||
private async listFolders(options: Options) {
|
||||
let folders = await this.folderService.getAllDecryptedFromState();
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
let folders = await this.folderService.getAllDecryptedFromState(activeUserId);
|
||||
|
||||
if (options.search != null && options.search.trim() !== "") {
|
||||
folders = CliUtils.searchFolders(folders, options.search);
|
||||
|
||||
27
apps/cli/src/key-management/cli-biometrics-service.ts
Normal file
27
apps/cli/src/key-management/cli-biometrics-service.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { UserKey } from "@bitwarden/common/types/key";
|
||||
import { BiometricsService, BiometricsStatus } from "@bitwarden/key-management";
|
||||
|
||||
export class CliBiometricsService extends BiometricsService {
|
||||
async authenticateWithBiometrics(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
async getBiometricsStatus(): Promise<BiometricsStatus> {
|
||||
return BiometricsStatus.PlatformUnsupported;
|
||||
}
|
||||
|
||||
async unlockWithBiometricsForUser(userId: UserId): Promise<UserKey | null> {
|
||||
return null;
|
||||
}
|
||||
|
||||
async getBiometricsStatusForUser(userId: UserId): Promise<BiometricsStatus> {
|
||||
return BiometricsStatus.PlatformUnsupported;
|
||||
}
|
||||
|
||||
async getShouldAutopromptNow(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
async setShouldAutopromptNow(value: boolean): Promise<void> {}
|
||||
}
|
||||
@@ -76,6 +76,7 @@ export class OssServeConfigurator {
|
||||
this.serviceContainer.organizationUserApiService,
|
||||
this.serviceContainer.apiService,
|
||||
this.serviceContainer.eventCollectionService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
this.createCommand = new CreateCommand(
|
||||
this.serviceContainer.cipherService,
|
||||
@@ -115,6 +116,7 @@ export class OssServeConfigurator {
|
||||
this.serviceContainer.folderApiService,
|
||||
this.serviceContainer.billingAccountProfileStateService,
|
||||
this.serviceContainer.cipherAuthorizationService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
this.confirmCommand = new ConfirmCommand(
|
||||
this.serviceContainer.apiService,
|
||||
@@ -147,6 +149,7 @@ export class OssServeConfigurator {
|
||||
this.serviceContainer.environmentService,
|
||||
this.serviceContainer.sendApiService,
|
||||
this.serviceContainer.billingAccountProfileStateService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
this.sendDeleteCommand = new SendDeleteCommand(
|
||||
this.serviceContainer.sendService,
|
||||
@@ -164,6 +167,7 @@ export class OssServeConfigurator {
|
||||
this.sendGetCommand,
|
||||
this.serviceContainer.sendApiService,
|
||||
this.serviceContainer.billingAccountProfileStateService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
this.sendListCommand = new SendListCommand(
|
||||
this.serviceContainer.sendService,
|
||||
|
||||
@@ -7,11 +7,9 @@ import {
|
||||
} from "@bitwarden/common/platform/misc/flags";
|
||||
|
||||
// required to avoid linting errors when there are no flags
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export type Flags = {} & SharedFlags;
|
||||
|
||||
// required to avoid linting errors when there are no flags
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export type DevFlags = {} & SharedDevFlags;
|
||||
|
||||
export function flagEnabled(flag: keyof Flags): boolean {
|
||||
|
||||
@@ -87,6 +87,8 @@ export class NodeEnvSecureStorageService implements AbstractStorageService {
|
||||
}
|
||||
|
||||
return Utils.fromBufferToB64(decValue);
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
this.logService.info("Decrypt error.");
|
||||
return null;
|
||||
@@ -104,6 +106,8 @@ export class NodeEnvSecureStorageService implements AbstractStorageService {
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
this.logService.info("Session key is invalid.");
|
||||
}
|
||||
|
||||
@@ -165,6 +165,7 @@ import {
|
||||
VaultExportServiceAbstraction,
|
||||
} from "@bitwarden/vault-export-core";
|
||||
|
||||
import { CliBiometricsService } from "../key-management/cli-biometrics-service";
|
||||
import { flagEnabled } from "../platform/flags";
|
||||
import { CliPlatformUtilsService } from "../platform/services/cli-platform-utils.service";
|
||||
import { ConsoleLogService } from "../platform/services/console-log.service";
|
||||
@@ -483,7 +484,29 @@ export class ServiceContainer {
|
||||
|
||||
this.containerService = new ContainerService(this.keyService, this.encryptService);
|
||||
|
||||
this.domainSettingsService = new DefaultDomainSettingsService(this.stateProvider);
|
||||
this.configApiService = new ConfigApiService(this.apiService, this.tokenService);
|
||||
|
||||
this.authService = new AuthService(
|
||||
this.accountService,
|
||||
this.messagingService,
|
||||
this.keyService,
|
||||
this.apiService,
|
||||
this.stateService,
|
||||
this.tokenService,
|
||||
);
|
||||
|
||||
this.configService = new DefaultConfigService(
|
||||
this.configApiService,
|
||||
this.environmentService,
|
||||
this.logService,
|
||||
this.stateProvider,
|
||||
this.authService,
|
||||
);
|
||||
|
||||
this.domainSettingsService = new DefaultDomainSettingsService(
|
||||
this.stateProvider,
|
||||
this.configService,
|
||||
);
|
||||
|
||||
this.fileUploadService = new FileUploadService(this.logService, this.apiService);
|
||||
|
||||
@@ -575,29 +598,12 @@ export class ServiceContainer {
|
||||
|
||||
this.billingAccountProfileStateService = new DefaultBillingAccountProfileStateService(
|
||||
this.stateProvider,
|
||||
this.platformUtilsService,
|
||||
this.apiService,
|
||||
);
|
||||
|
||||
this.taskSchedulerService = new DefaultTaskSchedulerService(this.logService);
|
||||
|
||||
this.authService = new AuthService(
|
||||
this.accountService,
|
||||
this.messagingService,
|
||||
this.keyService,
|
||||
this.apiService,
|
||||
this.stateService,
|
||||
this.tokenService,
|
||||
);
|
||||
|
||||
this.configApiService = new ConfigApiService(this.apiService, this.tokenService);
|
||||
|
||||
this.configService = new DefaultConfigService(
|
||||
this.configApiService,
|
||||
this.environmentService,
|
||||
this.logService,
|
||||
this.stateProvider,
|
||||
this.authService,
|
||||
);
|
||||
|
||||
this.devicesApiService = new DevicesApiServiceImplementation(this.apiService);
|
||||
this.deviceTrustService = new DeviceTrustService(
|
||||
this.keyGenerationService,
|
||||
@@ -688,12 +694,12 @@ export class ServiceContainer {
|
||||
this.userVerificationApiService,
|
||||
this.userDecryptionOptionsService,
|
||||
this.pinService,
|
||||
this.logService,
|
||||
this.vaultTimeoutSettingsService,
|
||||
this.platformUtilsService,
|
||||
this.kdfConfigService,
|
||||
new CliBiometricsService(),
|
||||
);
|
||||
|
||||
const biometricService = new CliBiometricsService();
|
||||
|
||||
this.vaultTimeoutService = new VaultTimeoutService(
|
||||
this.accountService,
|
||||
this.masterPasswordService,
|
||||
@@ -709,6 +715,7 @@ export class ServiceContainer {
|
||||
this.stateEventRunnerService,
|
||||
this.taskSchedulerService,
|
||||
this.logService,
|
||||
biometricService,
|
||||
lockedCallback,
|
||||
undefined,
|
||||
);
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
|
||||
import { firstValueFrom } from "rxjs";
|
||||
import { firstValueFrom, switchMap } from "rxjs";
|
||||
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
||||
@@ -23,6 +24,7 @@ export class SendCreateCommand {
|
||||
private environmentService: EnvironmentService,
|
||||
private sendApiService: SendApiService,
|
||||
private accountProfileService: BillingAccountProfileStateService,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
|
||||
async run(requestJson: any, cmdOptions: Record<string, any>) {
|
||||
@@ -47,6 +49,8 @@ export class SendCreateCommand {
|
||||
if (req == null) {
|
||||
throw new Error("Null request");
|
||||
}
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
return Response.badRequest("Error parsing the encoded request data.");
|
||||
}
|
||||
@@ -78,6 +82,10 @@ export class SendCreateCommand {
|
||||
req.key = null;
|
||||
req.maxAccessCount = maxAccessCount;
|
||||
|
||||
const hasPremium$ = this.accountService.activeAccount$.pipe(
|
||||
switchMap(({ id }) => this.accountProfileService.hasPremiumFromAnySource$(id)),
|
||||
);
|
||||
|
||||
switch (req.type) {
|
||||
case SendType.File:
|
||||
if (process.env.BW_SERVE === "true") {
|
||||
@@ -86,7 +94,7 @@ export class SendCreateCommand {
|
||||
);
|
||||
}
|
||||
|
||||
if (!(await firstValueFrom(this.accountProfileService.hasPremiumFromAnySource$))) {
|
||||
if (!(await firstValueFrom(hasPremium$))) {
|
||||
return Response.error("Premium status is required to use this feature.");
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// @ts-strict-ignore
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
@@ -19,6 +20,7 @@ export class SendEditCommand {
|
||||
private getCommand: SendGetCommand,
|
||||
private sendApiService: SendApiService,
|
||||
private accountProfileService: BillingAccountProfileStateService,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
|
||||
async run(requestJson: string, cmdOptions: Record<string, any>): Promise<Response> {
|
||||
@@ -39,6 +41,8 @@ export class SendEditCommand {
|
||||
try {
|
||||
const reqJson = Buffer.from(requestJson, "base64").toString();
|
||||
req = SendResponse.fromJson(reqJson);
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
return Response.badRequest("Error parsing the encoded request data.");
|
||||
}
|
||||
@@ -61,8 +65,9 @@ export class SendEditCommand {
|
||||
return Response.badRequest("Cannot change a Send's type");
|
||||
}
|
||||
|
||||
const account = await firstValueFrom(this.accountService.activeAccount$);
|
||||
const canAccessPremium = await firstValueFrom(
|
||||
this.accountProfileService.hasPremiumFromAnySource$,
|
||||
this.accountProfileService.hasPremiumFromAnySource$(account.id),
|
||||
);
|
||||
if (send.type === SendType.File && !canAccessPremium) {
|
||||
return Response.error("Premium status is required to use this feature.");
|
||||
|
||||
@@ -47,6 +47,8 @@ export class SendReceiveCommand extends DownloadCommand {
|
||||
let urlObject: URL;
|
||||
try {
|
||||
urlObject = new URL(url);
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
return Response.badRequest("Failed to parse the provided Send url");
|
||||
}
|
||||
|
||||
@@ -258,6 +258,7 @@ export class SendProgram extends BaseProgram {
|
||||
getCmd,
|
||||
this.serviceContainer.sendApiService,
|
||||
this.serviceContainer.billingAccountProfileStateService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
const response = await cmd.run(encodedJson, options);
|
||||
this.processResponse(response);
|
||||
@@ -331,6 +332,7 @@ export class SendProgram extends BaseProgram {
|
||||
this.serviceContainer.environmentService,
|
||||
this.serviceContainer.sendApiService,
|
||||
this.serviceContainer.billingAccountProfileStateService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
return await cmd.run(encodedJson, options);
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ export class VaultProgram extends BaseProgram {
|
||||
this.serviceContainer.organizationUserApiService,
|
||||
this.serviceContainer.apiService,
|
||||
this.serviceContainer.eventCollectionService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
const response = await command.run(object, cmd);
|
||||
|
||||
@@ -321,6 +322,7 @@ export class VaultProgram extends BaseProgram {
|
||||
this.serviceContainer.folderApiService,
|
||||
this.serviceContainer.billingAccountProfileStateService,
|
||||
this.serviceContainer.cipherAuthorizationService,
|
||||
this.serviceContainer.accountService,
|
||||
);
|
||||
const response = await command.run(object, id, cmd);
|
||||
this.processResponse(response);
|
||||
|
||||
@@ -30,6 +30,8 @@ import { CipherResponse } from "./models/cipher.response";
|
||||
import { FolderResponse } from "./models/folder.response";
|
||||
|
||||
export class CreateCommand {
|
||||
private activeUserId$ = this.accountService.activeAccount$.pipe(map((a) => a?.id));
|
||||
|
||||
constructor(
|
||||
private cipherService: CipherService,
|
||||
private folderService: FolderService,
|
||||
@@ -64,6 +66,8 @@ export class CreateCommand {
|
||||
try {
|
||||
const reqJson = Buffer.from(requestJson, "base64").toString();
|
||||
req = JSON.parse(reqJson);
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
return Response.badRequest("Error parsing the encoded request data.");
|
||||
}
|
||||
@@ -86,9 +90,7 @@ export class CreateCommand {
|
||||
}
|
||||
|
||||
private async createCipher(req: CipherExport) {
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const activeUserId = await firstValueFrom(this.activeUserId$);
|
||||
const cipher = await this.cipherService.encrypt(CipherExport.toView(req), activeUserId);
|
||||
try {
|
||||
const newCipher = await this.cipherService.createWithServer(cipher);
|
||||
@@ -136,10 +138,13 @@ export class CreateCommand {
|
||||
return Response.notFound();
|
||||
}
|
||||
|
||||
if (
|
||||
cipher.organizationId == null &&
|
||||
!(await firstValueFrom(this.accountProfileService.hasPremiumFromAnySource$))
|
||||
) {
|
||||
const activeUserId = await firstValueFrom(this.activeUserId$);
|
||||
|
||||
const canAccessPremium = await firstValueFrom(
|
||||
this.accountProfileService.hasPremiumFromAnySource$(activeUserId),
|
||||
);
|
||||
|
||||
if (cipher.organizationId == null && !canAccessPremium) {
|
||||
return Response.error("Premium status is required to use this feature.");
|
||||
}
|
||||
|
||||
@@ -152,9 +157,6 @@ export class CreateCommand {
|
||||
}
|
||||
|
||||
try {
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const updatedCipher = await this.cipherService.saveAttachmentRawWithServer(
|
||||
cipher,
|
||||
fileName,
|
||||
@@ -171,12 +173,12 @@ export class CreateCommand {
|
||||
}
|
||||
|
||||
private async createFolder(req: FolderExport) {
|
||||
const activeAccountId = await firstValueFrom(this.accountService.activeAccount$);
|
||||
const userKey = await this.keyService.getUserKeyWithLegacySupport(activeAccountId.id);
|
||||
const activeUserId = await firstValueFrom(this.activeUserId$);
|
||||
const userKey = await this.keyService.getUserKeyWithLegacySupport(activeUserId);
|
||||
const folder = await this.folderService.encrypt(FolderExport.toView(req), userKey);
|
||||
try {
|
||||
await this.folderApiService.save(folder);
|
||||
const newFolder = await this.folderService.get(folder.id);
|
||||
await this.folderApiService.save(folder, activeUserId);
|
||||
const newFolder = await this.folderService.get(folder.id, activeUserId);
|
||||
const decFolder = await newFolder.decrypt();
|
||||
const res = new FolderResponse(decFolder);
|
||||
return Response.success(res);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { firstValueFrom } from "rxjs";
|
||||
import { firstValueFrom, map } from "rxjs";
|
||||
|
||||
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 { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
@@ -19,6 +20,7 @@ export class DeleteCommand {
|
||||
private folderApiService: FolderApiServiceAbstraction,
|
||||
private accountProfileService: BillingAccountProfileStateService,
|
||||
private cipherAuthorizationService: CipherAuthorizationService,
|
||||
private accountService: AccountService,
|
||||
) {}
|
||||
|
||||
async run(object: string, id: string, cmdOptions: Record<string, any>): Promise<Response> {
|
||||
@@ -87,8 +89,9 @@ export class DeleteCommand {
|
||||
return Response.error("Attachment `" + id + "` was not found.");
|
||||
}
|
||||
|
||||
const account = await firstValueFrom(this.accountService.activeAccount$);
|
||||
const canAccessPremium = await firstValueFrom(
|
||||
this.accountProfileService.hasPremiumFromAnySource$,
|
||||
this.accountProfileService.hasPremiumFromAnySource$(account.id),
|
||||
);
|
||||
if (cipher.organizationId == null && !canAccessPremium) {
|
||||
return Response.error("Premium status is required to use this feature.");
|
||||
@@ -103,13 +106,16 @@ export class DeleteCommand {
|
||||
}
|
||||
|
||||
private async deleteFolder(id: string) {
|
||||
const folder = await this.folderService.getFromState(id);
|
||||
const activeUserId = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(map((a) => a?.id)),
|
||||
);
|
||||
const folder = await this.folderService.getFromState(id, activeUserId);
|
||||
if (folder == null) {
|
||||
return Response.notFound();
|
||||
}
|
||||
|
||||
try {
|
||||
await this.folderApiService.delete(id);
|
||||
await this.folderApiService.delete(id, activeUserId);
|
||||
return Response.success();
|
||||
} catch (e) {
|
||||
return Response.error(e);
|
||||
|
||||
Reference in New Issue
Block a user