mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
[PM-21546] Migrate from enum to constant object (#14975)
* add generic `union-of-values` helper * migrate `GeneratorDialogAction` to a constant * migrate `VaultState` to a constant * migrate `AtRiskCarouselDialogResult` to a constant * migrate `CredentialGeneratorDialogAction` to a constant * migrate `FolderAddEditDialogResult` to a constant * migrate `ViewCipherDialogResult` to a constant * migrate `VisibleVaultBanner` to a constant * migrate `VaultFilterLabel` to a constant * migrate `WebVaultGeneratorDialogResult` to a constant * migrate `BulkDeleteDialogResult` to a constant * migrate `BulkMoveDialogResult` to a constant * migrate `AddEditCipherDialogResult` to a constant * migrate `VaultItemDialogResult` to a constant * migrate `BrowserPromptState` to a constant * migrate `NudgeType` to a constant * migrate `SecurityTaskStatus` to a constant * migrate `CipherRepromptType` to a constant * migrate `SecureNoteType` to a constant * migrate `FieldType` to a constant * migrate `LinkedIdType` to a constant * migrate `CollectionAssignmentResult` to a constant * migrate `AddEditFolderDialogResult` to a constant * migrate `AttachmentDialogResult` to a constant * fix CipherType in delete organization dialog * fix `in` statement in VaultFilter * Fix build errors across enum updates * fix two more CipherType castings * update CipherResponse `CipherType` * define type for `fieldType` parameter * refine how `cipherTypeNames` is generated and add utility function for grabbing cipher type name * use `CipherType` rather than `number` * add stricter typing for `FieldType` * add fixme for `CipherType` to be ADR-0025 compliant * remove error throw for `toCipherTypeName` and instead update typing to have `| undefined` * add helpers for CipherType conversions * prefer `undefined`
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
// FIXME: update to use a const object instead of a typescript enum
|
||||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||||
export enum CipherRepromptType {
|
||||
None = 0,
|
||||
Password = 1,
|
||||
}
|
||||
import { UnionOfValues } from "../types/union-of-values";
|
||||
|
||||
export const CipherRepromptType = {
|
||||
None: 0,
|
||||
Password: 1,
|
||||
} as const;
|
||||
|
||||
export type CipherRepromptType = UnionOfValues<typeof CipherRepromptType>;
|
||||
|
||||
66
libs/common/src/vault/enums/cipher-type.spec.ts
Normal file
66
libs/common/src/vault/enums/cipher-type.spec.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import {
|
||||
CipherType,
|
||||
cipherTypeNames,
|
||||
isCipherType,
|
||||
toCipherType,
|
||||
toCipherTypeName,
|
||||
} from "./cipher-type";
|
||||
|
||||
describe("CipherType", () => {
|
||||
describe("toCipherTypeName", () => {
|
||||
it("should map CipherType correctly", () => {
|
||||
// identity test as the value is calculated
|
||||
expect(cipherTypeNames).toEqual({
|
||||
1: "Login",
|
||||
2: "SecureNote",
|
||||
3: "Card",
|
||||
4: "Identity",
|
||||
5: "SshKey",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("toCipherTypeName", () => {
|
||||
it("returns the associated name for the cipher type", () => {
|
||||
expect(toCipherTypeName(1)).toBe("Login");
|
||||
expect(toCipherTypeName(2)).toBe("SecureNote");
|
||||
expect(toCipherTypeName(3)).toBe("Card");
|
||||
expect(toCipherTypeName(4)).toBe("Identity");
|
||||
expect(toCipherTypeName(5)).toBe("SshKey");
|
||||
});
|
||||
|
||||
it("returns undefined for an invalid cipher type", () => {
|
||||
expect(toCipherTypeName(999 as any)).toBeUndefined();
|
||||
expect(toCipherTypeName("" as any)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("isCipherType", () => {
|
||||
it("returns true for valid CipherType values", () => {
|
||||
[1, 2, 3, 4, 5].forEach((value) => {
|
||||
expect(isCipherType(value)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it("returns false for invalid CipherType values", () => {
|
||||
expect(isCipherType(999 as any)).toBe(false);
|
||||
expect(isCipherType("Login" as any)).toBe(false);
|
||||
expect(isCipherType(null)).toBe(false);
|
||||
expect(isCipherType(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("toCipherType", () => {
|
||||
it("converts valid values to CipherType", () => {
|
||||
expect(toCipherType("1")).toBe(CipherType.Login);
|
||||
expect(toCipherType("02")).toBe(CipherType.SecureNote);
|
||||
});
|
||||
|
||||
it("returns null for invalid values", () => {
|
||||
expect(toCipherType(999 as any)).toBeUndefined();
|
||||
expect(toCipherType("Login" as any)).toBeUndefined();
|
||||
expect(toCipherType(null)).toBeUndefined();
|
||||
expect(toCipherType(undefined)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,9 +1,60 @@
|
||||
// FIXME: update to use a const object instead of a typescript enum
|
||||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||||
export enum CipherType {
|
||||
Login = 1,
|
||||
SecureNote = 2,
|
||||
Card = 3,
|
||||
Identity = 4,
|
||||
SshKey = 5,
|
||||
const _CipherType = Object.freeze({
|
||||
Login: 1,
|
||||
SecureNote: 2,
|
||||
Card: 3,
|
||||
Identity: 4,
|
||||
SshKey: 5,
|
||||
} as const);
|
||||
|
||||
type _CipherType = typeof _CipherType;
|
||||
|
||||
export type CipherType = _CipherType[keyof _CipherType];
|
||||
|
||||
// FIXME: Update typing of `CipherType` to be `Record<keyof _CipherType, CipherType>` which is ADR-0025 compliant when the TypeScript version is at least 5.8.
|
||||
export const CipherType: typeof _CipherType = _CipherType;
|
||||
|
||||
/**
|
||||
* Reverse mapping of Cipher Types to their associated names.
|
||||
* Prefer using {@link toCipherTypeName} rather than accessing this object directly.
|
||||
*
|
||||
* When represented as an enum in TypeScript, this mapping was provided
|
||||
* by default. Now using a constant object it needs to be defined manually.
|
||||
*/
|
||||
export const cipherTypeNames = Object.freeze(
|
||||
Object.fromEntries(Object.entries(CipherType).map(([key, value]) => [value, key])),
|
||||
) as Readonly<Record<CipherType, keyof typeof CipherType>>;
|
||||
|
||||
/**
|
||||
* Returns the associated name for the cipher type, will throw when the name is not found.
|
||||
*/
|
||||
export function toCipherTypeName(type: CipherType): keyof typeof CipherType | undefined {
|
||||
const name = cipherTypeNames[type];
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns `true` if the value is a valid `CipherType`, `false` otherwise.
|
||||
*/
|
||||
export const isCipherType = (value: unknown): value is CipherType => {
|
||||
return Object.values(CipherType).includes(value as CipherType);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a value to a `CipherType` if it is valid, otherwise returns `null`.
|
||||
*/
|
||||
export const toCipherType = (value: unknown): CipherType | undefined => {
|
||||
if (isCipherType(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
const valueAsInt = parseInt(value, 10);
|
||||
|
||||
if (isCipherType(valueAsInt)) {
|
||||
return valueAsInt;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
// FIXME: update to use a const object instead of a typescript enum
|
||||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||||
export enum FieldType {
|
||||
Text = 0,
|
||||
Hidden = 1,
|
||||
Boolean = 2,
|
||||
Linked = 3,
|
||||
}
|
||||
const _FieldType = Object.freeze({
|
||||
Text: 0,
|
||||
Hidden: 1,
|
||||
Boolean: 2,
|
||||
Linked: 3,
|
||||
} as const);
|
||||
|
||||
type _FieldType = typeof _FieldType;
|
||||
|
||||
export type FieldType = _FieldType[keyof _FieldType];
|
||||
|
||||
export const FieldType: Record<keyof _FieldType, FieldType> = _FieldType;
|
||||
|
||||
@@ -1,46 +1,48 @@
|
||||
import { UnionOfValues } from "../types/union-of-values";
|
||||
|
||||
export type LinkedIdType = LoginLinkedId | CardLinkedId | IdentityLinkedId;
|
||||
|
||||
// LoginView
|
||||
// FIXME: update to use a const object instead of a typescript enum
|
||||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||||
export enum LoginLinkedId {
|
||||
Username = 100,
|
||||
Password = 101,
|
||||
}
|
||||
export const LoginLinkedId = {
|
||||
Username: 100,
|
||||
Password: 101,
|
||||
} as const;
|
||||
|
||||
export type LoginLinkedId = UnionOfValues<typeof LoginLinkedId>;
|
||||
|
||||
// CardView
|
||||
// FIXME: update to use a const object instead of a typescript enum
|
||||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||||
export enum CardLinkedId {
|
||||
CardholderName = 300,
|
||||
ExpMonth = 301,
|
||||
ExpYear = 302,
|
||||
Code = 303,
|
||||
Brand = 304,
|
||||
Number = 305,
|
||||
}
|
||||
export const CardLinkedId = {
|
||||
CardholderName: 300,
|
||||
ExpMonth: 301,
|
||||
ExpYear: 302,
|
||||
Code: 303,
|
||||
Brand: 304,
|
||||
Number: 305,
|
||||
} as const;
|
||||
|
||||
export type CardLinkedId = UnionOfValues<typeof CardLinkedId>;
|
||||
|
||||
// IdentityView
|
||||
// FIXME: update to use a const object instead of a typescript enum
|
||||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||||
export enum IdentityLinkedId {
|
||||
Title = 400,
|
||||
MiddleName = 401,
|
||||
Address1 = 402,
|
||||
Address2 = 403,
|
||||
Address3 = 404,
|
||||
City = 405,
|
||||
State = 406,
|
||||
PostalCode = 407,
|
||||
Country = 408,
|
||||
Company = 409,
|
||||
Email = 410,
|
||||
Phone = 411,
|
||||
Ssn = 412,
|
||||
Username = 413,
|
||||
PassportNumber = 414,
|
||||
LicenseNumber = 415,
|
||||
FirstName = 416,
|
||||
LastName = 417,
|
||||
FullName = 418,
|
||||
}
|
||||
export const IdentityLinkedId = {
|
||||
Title: 400,
|
||||
MiddleName: 401,
|
||||
Address1: 402,
|
||||
Address2: 403,
|
||||
Address3: 404,
|
||||
City: 405,
|
||||
State: 406,
|
||||
PostalCode: 407,
|
||||
Country: 408,
|
||||
Company: 409,
|
||||
Email: 410,
|
||||
Phone: 411,
|
||||
Ssn: 412,
|
||||
Username: 413,
|
||||
PassportNumber: 414,
|
||||
LicenseNumber: 415,
|
||||
FirstName: 416,
|
||||
LastName: 417,
|
||||
FullName: 418,
|
||||
} as const;
|
||||
|
||||
export type IdentityLinkedId = UnionOfValues<typeof IdentityLinkedId>;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// FIXME: update to use a const object instead of a typescript enum
|
||||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||||
export enum SecureNoteType {
|
||||
Generic = 0,
|
||||
}
|
||||
import { UnionOfValues } from "../types/union-of-values";
|
||||
|
||||
export const SecureNoteType = {
|
||||
Generic: 0,
|
||||
} as const;
|
||||
|
||||
export type SecureNoteType = UnionOfValues<typeof SecureNoteType>;
|
||||
|
||||
@@ -57,7 +57,7 @@ export class CipherData {
|
||||
this.organizationUseTotp = response.organizationUseTotp;
|
||||
this.favorite = response.favorite;
|
||||
this.revisionDate = response.revisionDate;
|
||||
this.type = response.type;
|
||||
this.type = response.type as CipherType;
|
||||
this.name = response.name;
|
||||
this.notes = response.notes;
|
||||
this.collectionIds = collectionIds != null ? collectionIds : response.collectionIds;
|
||||
|
||||
@@ -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 { CipherType } from "../../enums";
|
||||
import { CipherRepromptType } from "../../enums/cipher-reprompt-type";
|
||||
import { CardApi } from "../api/card.api";
|
||||
import { CipherPermissionsApi } from "../api/cipher-permissions.api";
|
||||
@@ -17,7 +18,7 @@ export class CipherResponse extends BaseResponse {
|
||||
id: string;
|
||||
organizationId: string;
|
||||
folderId: string;
|
||||
type: number;
|
||||
type: CipherType;
|
||||
name: string;
|
||||
notes: string;
|
||||
fields: FieldApi[];
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
// FIXME: update to use a const object instead of a typescript enum
|
||||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||||
export enum SecurityTaskStatus {
|
||||
import { UnionOfValues } from "../../types/union-of-values";
|
||||
|
||||
export const SecurityTaskStatus = {
|
||||
/**
|
||||
* Default status for newly created tasks that have not been completed.
|
||||
*/
|
||||
Pending = 0,
|
||||
Pending: 0,
|
||||
|
||||
/**
|
||||
* Status when a task is considered complete and has no remaining actions
|
||||
*/
|
||||
Completed = 1,
|
||||
}
|
||||
Completed: 1,
|
||||
} as const;
|
||||
|
||||
export type SecurityTaskStatus = UnionOfValues<typeof SecurityTaskStatus>;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// FIXME: update to use a const object instead of a typescript enum
|
||||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||||
export enum SecurityTaskType {
|
||||
import { UnionOfValues } from "../../types/union-of-values";
|
||||
|
||||
export const SecurityTaskType = {
|
||||
/**
|
||||
* Task to update a cipher's password that was found to be at-risk by an administrator
|
||||
*/
|
||||
UpdateAtRiskCredential = 0,
|
||||
}
|
||||
UpdateAtRiskCredential: 0,
|
||||
} as const;
|
||||
|
||||
export type SecurityTaskType = UnionOfValues<typeof SecurityTaskType>;
|
||||
|
||||
2
libs/common/src/vault/types/union-of-values.ts
Normal file
2
libs/common/src/vault/types/union-of-values.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
/** Creates a union type consisting of all values within the record. */
|
||||
export type UnionOfValues<T extends Record<string, unknown>> = T[keyof T];
|
||||
Reference in New Issue
Block a user