mirror of
https://github.com/bitwarden/browser
synced 2025-12-23 19:53:43 +00:00
refactor: introduce @bitwarden/state and other common libs (#15772)
* refactor: introduce @bitwarden/serialization * refactor: introduce @bitwarden/guid * refactor: introduce @bitwaren/client-type * refactor: introduce @bitwarden/core-test-utils * refactor: introduce @bitwarden/state and @bitwarden/state-test-utils Creates initial project structure for centralized application state management. Part of modularization effort to extract state code from common. * Added state provider documentation to README. * Changed callouts to Github format. * Fixed linting on file name. * Forced git to accept rename --------- Co-authored-by: Todd Martin <tmartin@bitwarden.com>
This commit is contained in:
@@ -0,0 +1,247 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { KeyDefinitionLike, MigrationHelper } from "../migration-helper";
|
||||
import { Migrator } from "../migrator";
|
||||
|
||||
/** settings targeted by migrator */
|
||||
export type AccountType = {
|
||||
settings?: {
|
||||
usernameGenerationOptions?: ExpectedOptions;
|
||||
};
|
||||
};
|
||||
|
||||
/** username generation options prior to refactoring */
|
||||
export type ExpectedOptions = {
|
||||
type?: "word" | "subaddress" | "catchall" | "forwarded";
|
||||
wordCapitalize?: boolean;
|
||||
wordIncludeNumber?: boolean;
|
||||
subaddressType?: "random" | "website-name";
|
||||
subaddressEmail?: string;
|
||||
catchallType?: "random" | "website-name";
|
||||
catchallDomain?: string;
|
||||
forwardedService?: string;
|
||||
forwardedAnonAddyApiToken?: string;
|
||||
forwardedAnonAddyDomain?: string;
|
||||
forwardedAnonAddyBaseUrl?: string;
|
||||
forwardedDuckDuckGoToken?: string;
|
||||
forwardedFirefoxApiToken?: string;
|
||||
forwardedFastmailApiToken?: string;
|
||||
forwardedForwardEmailApiToken?: string;
|
||||
forwardedForwardEmailDomain?: string;
|
||||
forwardedSimpleLoginApiKey?: string;
|
||||
forwardedSimpleLoginBaseUrl?: string;
|
||||
};
|
||||
|
||||
/** username generation options after refactoring */
|
||||
type ConvertedOptions = {
|
||||
generator: GeneratorNavigation;
|
||||
algorithms: {
|
||||
catchall: CatchallGenerationOptions;
|
||||
effUsername: EffUsernameGenerationOptions;
|
||||
subaddress: SubaddressGenerationOptions;
|
||||
};
|
||||
forwarders: {
|
||||
addyIo: SelfHostedApiOptions & EmailDomainOptions;
|
||||
duckDuckGo: ApiOptions;
|
||||
fastmail: ApiOptions;
|
||||
firefoxRelay: ApiOptions;
|
||||
forwardEmail: ApiOptions & EmailDomainOptions;
|
||||
simpleLogin: SelfHostedApiOptions;
|
||||
};
|
||||
};
|
||||
|
||||
export const NAVIGATION: KeyDefinitionLike = {
|
||||
stateDefinition: {
|
||||
name: "generator",
|
||||
},
|
||||
key: "generatorSettings",
|
||||
};
|
||||
|
||||
export const CATCHALL: KeyDefinitionLike = {
|
||||
stateDefinition: {
|
||||
name: "generator",
|
||||
},
|
||||
key: "catchallGeneratorSettings",
|
||||
};
|
||||
|
||||
export const EFF_USERNAME: KeyDefinitionLike = {
|
||||
stateDefinition: {
|
||||
name: "generator",
|
||||
},
|
||||
key: "effUsernameGeneratorSettings",
|
||||
};
|
||||
|
||||
export const SUBADDRESS: KeyDefinitionLike = {
|
||||
stateDefinition: {
|
||||
name: "generator",
|
||||
},
|
||||
key: "subaddressGeneratorSettings",
|
||||
};
|
||||
|
||||
export const ADDY_IO: KeyDefinitionLike = {
|
||||
stateDefinition: {
|
||||
name: "generator",
|
||||
},
|
||||
key: "addyIoBuffer",
|
||||
};
|
||||
|
||||
export const DUCK_DUCK_GO: KeyDefinitionLike = {
|
||||
stateDefinition: {
|
||||
name: "generator",
|
||||
},
|
||||
key: "duckDuckGoBuffer",
|
||||
};
|
||||
|
||||
export const FASTMAIL: KeyDefinitionLike = {
|
||||
stateDefinition: {
|
||||
name: "generator",
|
||||
},
|
||||
key: "fastmailBuffer",
|
||||
};
|
||||
|
||||
export const FIREFOX_RELAY: KeyDefinitionLike = {
|
||||
stateDefinition: {
|
||||
name: "generator",
|
||||
},
|
||||
key: "firefoxRelayBuffer",
|
||||
};
|
||||
|
||||
export const FORWARD_EMAIL: KeyDefinitionLike = {
|
||||
stateDefinition: {
|
||||
name: "generator",
|
||||
},
|
||||
key: "forwardEmailBuffer",
|
||||
};
|
||||
|
||||
export const SIMPLE_LOGIN: KeyDefinitionLike = {
|
||||
stateDefinition: {
|
||||
name: "generator",
|
||||
},
|
||||
key: "simpleLoginBuffer",
|
||||
};
|
||||
|
||||
export type GeneratorNavigation = {
|
||||
type?: string;
|
||||
username?: string;
|
||||
forwarder?: string;
|
||||
};
|
||||
|
||||
type UsernameGenerationMode = "random" | "website-name";
|
||||
|
||||
type CatchallGenerationOptions = {
|
||||
catchallType?: UsernameGenerationMode;
|
||||
catchallDomain?: string;
|
||||
};
|
||||
|
||||
type EffUsernameGenerationOptions = {
|
||||
wordCapitalize?: boolean;
|
||||
wordIncludeNumber?: boolean;
|
||||
};
|
||||
|
||||
type SubaddressGenerationOptions = {
|
||||
subaddressType?: UsernameGenerationMode;
|
||||
subaddressEmail?: string;
|
||||
};
|
||||
|
||||
type ApiOptions = {
|
||||
token?: string;
|
||||
};
|
||||
|
||||
type SelfHostedApiOptions = ApiOptions & {
|
||||
baseUrl: string;
|
||||
};
|
||||
|
||||
type EmailDomainOptions = {
|
||||
domain: string;
|
||||
};
|
||||
|
||||
export class ForwarderOptionsMigrator extends Migrator<64, 65> {
|
||||
async migrate(helper: MigrationHelper): Promise<void> {
|
||||
const accounts = await helper.getAccounts<AccountType>();
|
||||
|
||||
async function migrateAccount(userId: string, account: AccountType) {
|
||||
const legacyOptions = account?.settings?.usernameGenerationOptions;
|
||||
|
||||
if (legacyOptions) {
|
||||
const converted = convertSettings(legacyOptions);
|
||||
await storeSettings(helper, userId, converted);
|
||||
await deleteSettings(helper, userId, account);
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||||
}
|
||||
|
||||
async rollback(helper: MigrationHelper): Promise<void> {
|
||||
// not supported
|
||||
}
|
||||
}
|
||||
|
||||
function convertSettings(options: ExpectedOptions): ConvertedOptions {
|
||||
const forwarders = {
|
||||
addyIo: {
|
||||
baseUrl: options.forwardedAnonAddyBaseUrl,
|
||||
token: options.forwardedAnonAddyApiToken,
|
||||
domain: options.forwardedAnonAddyDomain,
|
||||
},
|
||||
duckDuckGo: {
|
||||
token: options.forwardedDuckDuckGoToken,
|
||||
},
|
||||
fastmail: {
|
||||
token: options.forwardedFastmailApiToken,
|
||||
},
|
||||
firefoxRelay: {
|
||||
token: options.forwardedFirefoxApiToken,
|
||||
},
|
||||
forwardEmail: {
|
||||
token: options.forwardedForwardEmailApiToken,
|
||||
domain: options.forwardedForwardEmailDomain,
|
||||
},
|
||||
simpleLogin: {
|
||||
token: options.forwardedSimpleLoginApiKey,
|
||||
baseUrl: options.forwardedSimpleLoginBaseUrl,
|
||||
},
|
||||
};
|
||||
|
||||
const generator = {
|
||||
username: options.type,
|
||||
forwarder: options.forwardedService,
|
||||
};
|
||||
|
||||
const algorithms = {
|
||||
effUsername: {
|
||||
wordCapitalize: options.wordCapitalize,
|
||||
wordIncludeNumber: options.wordIncludeNumber,
|
||||
},
|
||||
subaddress: {
|
||||
subaddressType: options.subaddressType,
|
||||
subaddressEmail: options.subaddressEmail,
|
||||
},
|
||||
catchall: {
|
||||
catchallType: options.catchallType,
|
||||
catchallDomain: options.catchallDomain,
|
||||
},
|
||||
};
|
||||
|
||||
return { generator, algorithms, forwarders };
|
||||
}
|
||||
|
||||
async function storeSettings(helper: MigrationHelper, userId: string, converted: ConvertedOptions) {
|
||||
await Promise.all([
|
||||
helper.setToUser(userId, NAVIGATION, converted.generator),
|
||||
helper.setToUser(userId, CATCHALL, converted.algorithms.catchall),
|
||||
helper.setToUser(userId, EFF_USERNAME, converted.algorithms.effUsername),
|
||||
helper.setToUser(userId, SUBADDRESS, converted.algorithms.subaddress),
|
||||
helper.setToUser(userId, ADDY_IO, converted.forwarders.addyIo),
|
||||
helper.setToUser(userId, DUCK_DUCK_GO, converted.forwarders.duckDuckGo),
|
||||
helper.setToUser(userId, FASTMAIL, converted.forwarders.fastmail),
|
||||
helper.setToUser(userId, FIREFOX_RELAY, converted.forwarders.firefoxRelay),
|
||||
helper.setToUser(userId, FORWARD_EMAIL, converted.forwarders.forwardEmail),
|
||||
helper.setToUser(userId, SIMPLE_LOGIN, converted.forwarders.simpleLogin),
|
||||
]);
|
||||
}
|
||||
|
||||
async function deleteSettings(helper: MigrationHelper, userId: string, account: AccountType) {
|
||||
delete account?.settings?.usernameGenerationOptions;
|
||||
await helper.set(userId, account);
|
||||
}
|
||||
Reference in New Issue
Block a user