mirror of
https://github.com/bitwarden/browser
synced 2026-02-18 10:23:52 +00:00
Merge branch 'main' of github.com:bitwarden/clients into vault/pm-24978/corrupt-attachments
This commit is contained in:
@@ -121,13 +121,13 @@ export class CollectionAdminView extends CollectionView {
|
||||
try {
|
||||
view.name = await encryptService.decryptString(new EncString(view.name), orgKey);
|
||||
} catch (e) {
|
||||
view.name = "[error: cannot decrypt]";
|
||||
// Note: This should be replaced by the owning team with appropriate, domain-specific behavior.
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(
|
||||
"[CollectionAdminView/fromCollectionAccessDetails] Error decrypting collection name",
|
||||
e,
|
||||
);
|
||||
throw e;
|
||||
}
|
||||
view.assigned = collection.assigned;
|
||||
view.readOnly = collection.readOnly;
|
||||
|
||||
@@ -126,7 +126,14 @@ export class CollectionView implements View, ITreeNodeObject {
|
||||
): Promise<CollectionView> {
|
||||
const view = new CollectionView({ ...collection, name: "" });
|
||||
|
||||
view.name = await encryptService.decryptString(collection.name, key);
|
||||
try {
|
||||
view.name = await encryptService.decryptString(collection.name, key);
|
||||
} catch (e) {
|
||||
view.name = "[error: cannot decrypt]";
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("[CollectionView] Error decrypting collection name", e);
|
||||
}
|
||||
|
||||
view.assigned = true;
|
||||
view.externalId = collection.externalId;
|
||||
view.readOnly = collection.readOnly;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
export class ProviderUserConfirmRequest {
|
||||
key: string;
|
||||
protected key: string;
|
||||
|
||||
constructor(key: string) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abs
|
||||
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { LogService } from "@bitwarden/logging";
|
||||
|
||||
import { FakeAccountService, FakeStateProvider, mockAccountServiceWith } from "../../../../spec";
|
||||
import { UserId } from "../../../types/guid";
|
||||
@@ -54,6 +55,8 @@ describe("PhishingDetectionSettingsService", () => {
|
||||
usePhishingBlocker: true,
|
||||
});
|
||||
|
||||
const mockLogService = mock<LogService>();
|
||||
|
||||
const mockUserId = "mock-user-id" as UserId;
|
||||
const account = mock<Account>({ id: mockUserId });
|
||||
const accountService: FakeAccountService = mockAccountServiceWith(mockUserId);
|
||||
@@ -85,6 +88,7 @@ describe("PhishingDetectionSettingsService", () => {
|
||||
mockAccountService,
|
||||
mockBillingService,
|
||||
mockConfigService,
|
||||
mockLogService,
|
||||
mockOrganizationService,
|
||||
mockPlatformService,
|
||||
stateProvider,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { combineLatest, Observable, of, switchMap } from "rxjs";
|
||||
import { catchError, distinctUntilChanged, map, shareReplay } from "rxjs/operators";
|
||||
import { catchError, distinctUntilChanged, map, shareReplay, tap } from "rxjs/operators";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
@@ -9,6 +9,7 @@ import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { LogService } from "@bitwarden/logging";
|
||||
import { UserId } from "@bitwarden/user-core";
|
||||
|
||||
import { PHISHING_DETECTION_DISK, StateProvider, UserKeyDefinition } from "../../../platform/state";
|
||||
@@ -32,27 +33,47 @@ export class PhishingDetectionSettingsService implements PhishingDetectionSettin
|
||||
private accountService: AccountService,
|
||||
private billingService: BillingAccountProfileStateService,
|
||||
private configService: ConfigService,
|
||||
private logService: LogService,
|
||||
private organizationService: OrganizationService,
|
||||
private platformService: PlatformUtilsService,
|
||||
private stateProvider: StateProvider,
|
||||
) {
|
||||
this.logService.debug(`[PhishingDetectionSettingsService] Initializing service...`);
|
||||
this.available$ = this.buildAvailablePipeline$().pipe(
|
||||
distinctUntilChanged(),
|
||||
tap((available) =>
|
||||
this.logService.debug(
|
||||
`[PhishingDetectionSettingsService] Phishing detection available: ${available}`,
|
||||
),
|
||||
),
|
||||
shareReplay({ bufferSize: 1, refCount: true }),
|
||||
);
|
||||
this.enabled$ = this.buildEnabledPipeline$().pipe(
|
||||
distinctUntilChanged(),
|
||||
tap((enabled) =>
|
||||
this.logService.debug(
|
||||
`[PhishingDetectionSettingsService] Phishing detection enabled: ${{ enabled }}`,
|
||||
),
|
||||
),
|
||||
shareReplay({ bufferSize: 1, refCount: true }),
|
||||
);
|
||||
|
||||
this.on$ = combineLatest([this.available$, this.enabled$]).pipe(
|
||||
map(([available, enabled]) => available && enabled),
|
||||
distinctUntilChanged(),
|
||||
shareReplay({ bufferSize: 1, refCount: true }),
|
||||
tap((on) =>
|
||||
this.logService.debug(
|
||||
`[PhishingDetectionSettingsService] Phishing detection is on: ${{ on }}`,
|
||||
),
|
||||
),
|
||||
shareReplay({ bufferSize: 1, refCount: false }),
|
||||
);
|
||||
}
|
||||
|
||||
async setEnabled(userId: UserId, enabled: boolean): Promise<void> {
|
||||
this.logService.debug(
|
||||
`[PhishingDetectionSettingsService] Setting phishing detection enabled: ${{ enabled, userId }}`,
|
||||
);
|
||||
await this.stateProvider.getUser(userId, ENABLE_PHISHING_DETECTION).update(() => enabled);
|
||||
}
|
||||
|
||||
@@ -64,6 +85,9 @@ export class PhishingDetectionSettingsService implements PhishingDetectionSettin
|
||||
private buildAvailablePipeline$(): Observable<boolean> {
|
||||
// Phishing detection is unavailable on Safari due to platform limitations.
|
||||
if (this.platformService.isSafari()) {
|
||||
this.logService.warning(
|
||||
`[PhishingDetectionSettingsService] Phishing detection is unavailable on Safari due to platform limitations`,
|
||||
);
|
||||
return of(false);
|
||||
}
|
||||
|
||||
@@ -97,6 +121,9 @@ export class PhishingDetectionSettingsService implements PhishingDetectionSettin
|
||||
if (!account) {
|
||||
return of(false);
|
||||
}
|
||||
this.logService.debug(
|
||||
`[PhishingDetectionSettingsService] Refreshing phishing detection enabled state`,
|
||||
);
|
||||
return this.stateProvider.getUserState$(ENABLE_PHISHING_DETECTION, account.id);
|
||||
}),
|
||||
map((enabled) => enabled ?? true),
|
||||
|
||||
@@ -14,6 +14,7 @@ export enum FeatureFlag {
|
||||
AutoConfirm = "pm-19934-auto-confirm-organization-users",
|
||||
BlockClaimedDomainAccountCreation = "pm-28297-block-uninvited-claimed-domain-registration",
|
||||
IncreaseBulkReinviteLimitForCloud = "pm-28251-increase-bulk-reinvite-limit-for-cloud",
|
||||
MembersComponentRefactor = "pm-29503-refactor-members-inheritance",
|
||||
|
||||
/* Auth */
|
||||
PM23801_PrefetchPasswordPrelogin = "pm-23801-prefetch-password-prelogin",
|
||||
@@ -22,6 +23,7 @@ export enum FeatureFlag {
|
||||
MacOsNativeCredentialSync = "macos-native-credential-sync",
|
||||
WindowsDesktopAutotype = "windows-desktop-autotype",
|
||||
WindowsDesktopAutotypeGA = "windows-desktop-autotype-ga",
|
||||
SSHAgentV2 = "ssh-agent-v2",
|
||||
|
||||
/* Billing */
|
||||
TrialPaymentOptional = "PM-8163-trial-payment",
|
||||
@@ -45,6 +47,7 @@ export enum FeatureFlag {
|
||||
ConsolidatedSessionTimeoutComponent = "pm-26056-consolidated-session-timeout-component",
|
||||
PM27279_V2RegistrationTdeJit = "pm-27279-v2-registration-tde-jit",
|
||||
EnableAccountEncryptionV2KeyConnectorRegistration = "enable-account-encryption-v2-key-connector-registration",
|
||||
EnableAccountEncryptionV2JitPasswordRegistration = "enable-account-encryption-v2-jit-password-registration",
|
||||
|
||||
/* Tools */
|
||||
UseSdkPasswordGenerators = "pm-19976-use-sdk-password-generators",
|
||||
@@ -74,6 +77,7 @@ export enum FeatureFlag {
|
||||
|
||||
/* Desktop */
|
||||
DesktopUiMigrationMilestone1 = "desktop-ui-migration-milestone-1",
|
||||
DesktopUiMigrationMilestone2 = "desktop-ui-migration-milestone-2",
|
||||
|
||||
/* UIF */
|
||||
RouterFocusManagement = "router-focus-management",
|
||||
@@ -100,11 +104,13 @@ export const DefaultFeatureFlagValue = {
|
||||
[FeatureFlag.AutoConfirm]: FALSE,
|
||||
[FeatureFlag.BlockClaimedDomainAccountCreation]: FALSE,
|
||||
[FeatureFlag.IncreaseBulkReinviteLimitForCloud]: FALSE,
|
||||
[FeatureFlag.MembersComponentRefactor]: FALSE,
|
||||
|
||||
/* Autofill */
|
||||
[FeatureFlag.MacOsNativeCredentialSync]: FALSE,
|
||||
[FeatureFlag.WindowsDesktopAutotype]: FALSE,
|
||||
[FeatureFlag.WindowsDesktopAutotypeGA]: FALSE,
|
||||
[FeatureFlag.SSHAgentV2]: FALSE,
|
||||
|
||||
/* Tools */
|
||||
[FeatureFlag.UseSdkPasswordGenerators]: FALSE,
|
||||
@@ -151,6 +157,7 @@ export const DefaultFeatureFlagValue = {
|
||||
[FeatureFlag.ConsolidatedSessionTimeoutComponent]: FALSE,
|
||||
[FeatureFlag.PM27279_V2RegistrationTdeJit]: FALSE,
|
||||
[FeatureFlag.EnableAccountEncryptionV2KeyConnectorRegistration]: FALSE,
|
||||
[FeatureFlag.EnableAccountEncryptionV2JitPasswordRegistration]: FALSE,
|
||||
|
||||
/* Platform */
|
||||
[FeatureFlag.IpcChannelFramework]: FALSE,
|
||||
@@ -160,6 +167,7 @@ export const DefaultFeatureFlagValue = {
|
||||
|
||||
/* Desktop */
|
||||
[FeatureFlag.DesktopUiMigrationMilestone1]: FALSE,
|
||||
[FeatureFlag.DesktopUiMigrationMilestone2]: FALSE,
|
||||
|
||||
/* UIF */
|
||||
[FeatureFlag.RouterFocusManagement]: FALSE,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { AuthType } from "../../types/auth-type";
|
||||
import { SendType } from "../../types/send-type";
|
||||
import { SendResponse } from "../response/send.response";
|
||||
|
||||
@@ -10,6 +11,7 @@ export class SendData {
|
||||
id: string;
|
||||
accessId: string;
|
||||
type: SendType;
|
||||
authType: AuthType;
|
||||
name: string;
|
||||
notes: string;
|
||||
file: SendFileData;
|
||||
@@ -33,6 +35,7 @@ export class SendData {
|
||||
this.id = response.id;
|
||||
this.accessId = response.accessId;
|
||||
this.type = response.type;
|
||||
this.authType = response.authType;
|
||||
this.name = response.name;
|
||||
this.notes = response.notes;
|
||||
this.key = response.key;
|
||||
|
||||
@@ -11,6 +11,7 @@ import { EncryptService } from "../../../../key-management/crypto/abstractions/e
|
||||
import { SymmetricCryptoKey } from "../../../../platform/models/domain/symmetric-crypto-key";
|
||||
import { ContainerService } from "../../../../platform/services/container.service";
|
||||
import { UserKey } from "../../../../types/key";
|
||||
import { AuthType } from "../../types/auth-type";
|
||||
import { SendType } from "../../types/send-type";
|
||||
import { SendData } from "../data/send.data";
|
||||
|
||||
@@ -25,6 +26,7 @@ describe("Send", () => {
|
||||
id: "id",
|
||||
accessId: "accessId",
|
||||
type: SendType.Text,
|
||||
authType: AuthType.None,
|
||||
name: "encName",
|
||||
notes: "encNotes",
|
||||
text: {
|
||||
@@ -55,6 +57,7 @@ describe("Send", () => {
|
||||
id: null,
|
||||
accessId: null,
|
||||
type: undefined,
|
||||
authType: undefined,
|
||||
name: null,
|
||||
notes: null,
|
||||
text: undefined,
|
||||
@@ -78,6 +81,7 @@ describe("Send", () => {
|
||||
id: "id",
|
||||
accessId: "accessId",
|
||||
type: SendType.Text,
|
||||
authType: AuthType.None,
|
||||
name: { encryptedString: "encName", encryptionType: 0 },
|
||||
notes: { encryptedString: "encNotes", encryptionType: 0 },
|
||||
text: {
|
||||
@@ -107,6 +111,7 @@ describe("Send", () => {
|
||||
send.id = "id";
|
||||
send.accessId = "accessId";
|
||||
send.type = SendType.Text;
|
||||
send.authType = AuthType.None;
|
||||
send.name = mockEnc("name");
|
||||
send.notes = mockEnc("notes");
|
||||
send.text = text;
|
||||
@@ -145,6 +150,7 @@ describe("Send", () => {
|
||||
name: "name",
|
||||
notes: "notes",
|
||||
type: 0,
|
||||
authType: 2,
|
||||
key: expect.anything(),
|
||||
cryptoKey: "cryptoKey",
|
||||
file: expect.anything(),
|
||||
|
||||
@@ -8,6 +8,7 @@ import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { EncString } from "../../../../key-management/crypto/models/enc-string";
|
||||
import { Utils } from "../../../../platform/misc/utils";
|
||||
import Domain from "../../../../platform/models/domain/domain-base";
|
||||
import { AuthType } from "../../types/auth-type";
|
||||
import { SendType } from "../../types/send-type";
|
||||
import { SendData } from "../data/send.data";
|
||||
import { SendView } from "../view/send.view";
|
||||
@@ -19,6 +20,7 @@ export class Send extends Domain {
|
||||
id: string;
|
||||
accessId: string;
|
||||
type: SendType;
|
||||
authType: AuthType;
|
||||
name: EncString;
|
||||
notes: EncString;
|
||||
file: SendFile;
|
||||
@@ -54,6 +56,7 @@ export class Send extends Domain {
|
||||
);
|
||||
|
||||
this.type = obj.type;
|
||||
this.authType = obj.authType;
|
||||
this.maxAccessCount = obj.maxAccessCount;
|
||||
this.accessCount = obj.accessCount;
|
||||
this.password = obj.password;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { BaseResponse } from "../../../../models/response/base.response";
|
||||
import { AuthType } from "../../types/auth-type";
|
||||
import { SendType } from "../../types/send-type";
|
||||
import { SendFileApi } from "../api/send-file.api";
|
||||
import { SendTextApi } from "../api/send-text.api";
|
||||
@@ -9,6 +10,7 @@ export class SendResponse extends BaseResponse {
|
||||
id: string;
|
||||
accessId: string;
|
||||
type: SendType;
|
||||
authType: AuthType;
|
||||
name: string;
|
||||
notes: string;
|
||||
file: SendFileApi;
|
||||
@@ -29,6 +31,7 @@ export class SendResponse extends BaseResponse {
|
||||
this.id = this.getResponseProperty("Id");
|
||||
this.accessId = this.getResponseProperty("AccessId");
|
||||
this.type = this.getResponseProperty("Type");
|
||||
this.authType = this.getResponseProperty("AuthType");
|
||||
this.name = this.getResponseProperty("Name");
|
||||
this.notes = this.getResponseProperty("Notes");
|
||||
this.key = this.getResponseProperty("Key");
|
||||
|
||||
@@ -4,6 +4,7 @@ import { View } from "../../../../models/view/view";
|
||||
import { Utils } from "../../../../platform/misc/utils";
|
||||
import { SymmetricCryptoKey } from "../../../../platform/models/domain/symmetric-crypto-key";
|
||||
import { DeepJsonify } from "../../../../types/deep-jsonify";
|
||||
import { AuthType } from "../../types/auth-type";
|
||||
import { SendType } from "../../types/send-type";
|
||||
import { Send } from "../domain/send";
|
||||
|
||||
@@ -18,6 +19,7 @@ export class SendView implements View {
|
||||
key: Uint8Array;
|
||||
cryptoKey: SymmetricCryptoKey;
|
||||
type: SendType = null;
|
||||
authType: AuthType = null;
|
||||
text = new SendTextView();
|
||||
file = new SendFileView();
|
||||
maxAccessCount?: number = null;
|
||||
@@ -38,6 +40,7 @@ export class SendView implements View {
|
||||
this.id = s.id;
|
||||
this.accessId = s.accessId;
|
||||
this.type = s.type;
|
||||
this.authType = s.authType;
|
||||
this.maxAccessCount = s.maxAccessCount;
|
||||
this.accessCount = s.accessCount;
|
||||
this.revisionDate = s.revisionDate;
|
||||
|
||||
12
libs/common/src/tools/send/types/auth-type.ts
Normal file
12
libs/common/src/tools/send/types/auth-type.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/** An type of auth necessary to access a Send */
|
||||
export const AuthType = Object.freeze({
|
||||
/** Send requires email OTP verification */
|
||||
Email: 0,
|
||||
/** Send requires a password */
|
||||
Password: 1,
|
||||
/** Send requires no auth */
|
||||
None: 2,
|
||||
} as const);
|
||||
|
||||
/** An type of auth necessary to access a Send */
|
||||
export type AuthType = (typeof AuthType)[keyof typeof AuthType];
|
||||
Reference in New Issue
Block a user