From baf38f6cbc11417eb2c7d56fde6d878ddccc7f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9C=A8=20Audrey=20=E2=9C=A8?= Date: Fri, 27 Dec 2024 11:53:13 -0500 Subject: [PATCH] consistency updates --- .../src/tools/extension/data/addy-io.ts | 2 +- .../src/tools/extension/data/duck-duck-go.ts | 2 +- .../src/tools/extension/data/fastmail.ts | 3 +- .../src/tools/extension/data/forward-email.ts | 2 +- .../src/tools/extension/data/mozilla.ts | 2 +- .../src/tools/extension/data/simple-login.ts | 2 +- .../default-extension-registry.ts | 56 +++++++++---------- .../extension-registry.abstraction.ts | 39 +++++++------ .../src/tools/extension/extension.service.ts | 4 +- libs/common/src/tools/extension/factory.ts | 36 ++++++++++++ .../src/tools/extension/metadata/factory.ts | 36 ------------ .../src/tools/extension/metadata/type.ts | 30 +++++----- 12 files changed, 106 insertions(+), 108 deletions(-) rename libs/common/src/tools/extension/{metadata => }/default-extension-registry.ts (67%) rename libs/common/src/tools/extension/{metadata => }/extension-registry.abstraction.ts (65%) create mode 100644 libs/common/src/tools/extension/factory.ts delete mode 100644 libs/common/src/tools/extension/metadata/factory.ts diff --git a/libs/common/src/tools/extension/data/addy-io.ts b/libs/common/src/tools/extension/data/addy-io.ts index 4fb72ef2cf8..d1b7d21af8d 100644 --- a/libs/common/src/tools/extension/data/addy-io.ts +++ b/libs/common/src/tools/extension/data/addy-io.ts @@ -7,7 +7,7 @@ export const AddyIo = { name: "Addy.io", }; -export const AddyIoIntegrations: ExtensionMetadata[] = [ +export const AddyIoExtensions: ExtensionMetadata[] = [ { site: Extension.forwarder, product: { diff --git a/libs/common/src/tools/extension/data/duck-duck-go.ts b/libs/common/src/tools/extension/data/duck-duck-go.ts index 231e0ba50f3..ce3d5ffa545 100644 --- a/libs/common/src/tools/extension/data/duck-duck-go.ts +++ b/libs/common/src/tools/extension/data/duck-duck-go.ts @@ -7,7 +7,7 @@ export const DuckDuckGo = { name: "DuckDuckGo", }; -export const DuckDuckGoIntegrations: ExtensionMetadata[] = [ +export const DuckDuckGoExtensions: ExtensionMetadata[] = [ { site: Extension.forwarder, product: { diff --git a/libs/common/src/tools/extension/data/fastmail.ts b/libs/common/src/tools/extension/data/fastmail.ts index 65e6bd163ea..c7a0cf22c3a 100644 --- a/libs/common/src/tools/extension/data/fastmail.ts +++ b/libs/common/src/tools/extension/data/fastmail.ts @@ -7,8 +7,7 @@ export const Fastmail = { name: "Fastmail", }; -// integration-wide configuration -export const FastmailIntegrations: ExtensionMetadata[] = [ +export const FastmailExtensions: ExtensionMetadata[] = [ { site: Extension.forwarder, product: { diff --git a/libs/common/src/tools/extension/data/forward-email.ts b/libs/common/src/tools/extension/data/forward-email.ts index b7e1085fb80..35b827ca1a5 100644 --- a/libs/common/src/tools/extension/data/forward-email.ts +++ b/libs/common/src/tools/extension/data/forward-email.ts @@ -7,7 +7,7 @@ export const ForwardEmail = { name: "Forward Email", }; -export const ForwardEmailIntegrations: ExtensionMetadata[] = [ +export const ForwardEmailExtensions: ExtensionMetadata[] = [ { site: Extension.forwarder, product: { diff --git a/libs/common/src/tools/extension/data/mozilla.ts b/libs/common/src/tools/extension/data/mozilla.ts index 2c3f394743e..682c3ab19d4 100644 --- a/libs/common/src/tools/extension/data/mozilla.ts +++ b/libs/common/src/tools/extension/data/mozilla.ts @@ -7,7 +7,7 @@ export const Mozilla = { name: "Mozilla", }; -export const MozillaIntegrations: ExtensionMetadata[] = [ +export const MozillaExtensions: ExtensionMetadata[] = [ { site: Extension.forwarder, product: { diff --git a/libs/common/src/tools/extension/data/simple-login.ts b/libs/common/src/tools/extension/data/simple-login.ts index bb0684b2e50..174c9668bd0 100644 --- a/libs/common/src/tools/extension/data/simple-login.ts +++ b/libs/common/src/tools/extension/data/simple-login.ts @@ -7,7 +7,7 @@ export const SimpleLogin: VendorMetadata = { name: "SimpleLogin", }; -export const SimpleLoginIntegrations: ExtensionMetadata[] = [ +export const SimpleLoginExtensions: ExtensionMetadata[] = [ { site: Extension.forwarder, product: { diff --git a/libs/common/src/tools/extension/metadata/default-extension-registry.ts b/libs/common/src/tools/extension/default-extension-registry.ts similarity index 67% rename from libs/common/src/tools/extension/metadata/default-extension-registry.ts rename to libs/common/src/tools/extension/default-extension-registry.ts index d2e695c41f7..43e989b2ec9 100644 --- a/libs/common/src/tools/extension/metadata/default-extension-registry.ts +++ b/libs/common/src/tools/extension/default-extension-registry.ts @@ -1,6 +1,5 @@ -import { ExtensionSite } from "../extension-site"; - import { ExtensionPermission, ExtensionRegistry } from "./extension-registry.abstraction"; +import { ExtensionSite } from "./extension-site"; import { SiteMetadata, SiteId, @@ -8,21 +7,20 @@ import { ExtensionSet, VendorId, VendorMetadata, -} from "./type"; +} from "./metadata/type"; -/** Tracks extension points and the integrations that extend them. */ -export class DefaultIntegrationRegistry implements ExtensionRegistry { +/** Tracks extension sites and the vendors that extend them. */ +export class DefaultExtensionRegistry implements ExtensionRegistry { private allRule: ExtensionPermission = "default"; private siteRegistrations = new Map(); - private siteRules = new Map(); + private sitePermissions = new Map(); private vendorRegistrations = new Map(); - private vendorRules = new Map(); + private vendorPermissions = new Map(); - private integrations = new Array(); - private siteIntegrationsByVendor = new Map>(); - private vendorIntegrationsBySite = new Map>(); + private extensions = new Array(); + private vendorExtensionsBySite = new Map>(); registerSite(meta: SiteMetadata): this { if (!this.siteRegistrations.has(meta.id)) { @@ -37,7 +35,7 @@ export class DefaultIntegrationRegistry implements ExtensionRegistry { for (const [k, site] of this.siteRegistrations.entries()) { const s: (typeof sites)[number] = { site }; - const permission = this.siteRules.get(k); + const permission = this.sitePermissions.get(k); if (permission) { s.permission = permission; } @@ -61,7 +59,7 @@ export class DefaultIntegrationRegistry implements ExtensionRegistry { for (const [k, vendor] of this.vendorRegistrations.entries()) { const s: (typeof vendors)[number] = { vendor }; - const permission = this.vendorRules.get(k); + const permission = this.vendorPermissions.get(k); if (permission) { s.permission = permission; } @@ -76,11 +74,11 @@ export class DefaultIntegrationRegistry implements ExtensionRegistry { if ("all" in set && set.all) { this.allRule = permission; } else if ("vendor" in set) { - this.vendorRules.set(set.vendor, permission); + this.vendorPermissions.set(set.vendor, permission); } else if ("site" in set) { - this.siteRules.set(set.site, permission); + this.sitePermissions.set(set.site, permission); } else { - throw new Error(`Unrecognized integration set received: ${JSON.stringify(set)}.`); + throw new Error(`Unrecognized extension set received: ${JSON.stringify(set)}.`); } return this; @@ -90,9 +88,9 @@ export class DefaultIntegrationRegistry implements ExtensionRegistry { if ("all" in set && set.all) { return this.allRule; } else if ("vendor" in set) { - return this.vendorRules.get(set.vendor); + return this.vendorPermissions.get(set.vendor); } else if ("site" in set) { - return this.siteRules.get(set.site); + return this.sitePermissions.get(set.site); } else { return undefined; } @@ -102,11 +100,11 @@ export class DefaultIntegrationRegistry implements ExtensionRegistry { const rules: { set: ExtensionSet; permission: ExtensionPermission }[] = []; rules.push({ set: { all: true }, permission: this.allRule }); - for (const [site, permission] of this.siteRules.entries()) { + for (const [site, permission] of this.sitePermissions.entries()) { rules.push({ set: { site }, permission }); } - for (const [vendor, permission] of this.vendorRules.entries()) { + for (const [vendor, permission] of this.vendorPermissions.entries()) { rules.push({ set: { vendor }, permission }); } @@ -120,19 +118,15 @@ export class DefaultIntegrationRegistry implements ExtensionRegistry { throw new Error(`Unrecognized vendor: ${meta.product.vendor.id}`); } - // is the integration registered? - const vendorMap = - this.vendorIntegrationsBySite.get(meta.site.id) ?? new Map(); + // is the extension registered? + const vendorMap = this.vendorExtensionsBySite.get(meta.site.id) ?? new Map(); if (vendorMap.has(meta.product.vendor.id)) { return; } // if not, register it - const siteMap = - this.siteIntegrationsByVendor.get(meta.product.vendor.id) ?? new Map(); - const index = this.integrations.push(meta) - 1; + const index = this.extensions.push(meta) - 1; vendorMap.set(meta.product.vendor.id, index); - siteMap.set(meta.site.id, index); return this; } @@ -148,22 +142,22 @@ export class DefaultIntegrationRegistry implements ExtensionRegistry { } const extensions = new Map(); - const entries = this.vendorIntegrationsBySite.get(id)?.entries() ?? ([] as const); + const entries = this.vendorExtensionsBySite.get(id)?.entries() ?? ([] as const); for (const [vendor, maybeIndex] of entries) { // prepare rules - const vendorRule = this.vendorRules.get(vendor) ?? this.allRule; - const siteRule = this.siteRules.get(id) ?? this.allRule; + const vendorRule = this.vendorPermissions.get(vendor) ?? this.allRule; + const siteRule = this.sitePermissions.get(id) ?? this.allRule; const rules = [vendorRule, siteRule, this.allRule]; // evaluate rules const extension = rules.includes("deny") ? undefined : rules.includes("allow") - ? this.integrations[maybeIndex] + ? this.extensions[maybeIndex] : rules.includes("none") ? undefined : rules.includes("default") - ? this.integrations[maybeIndex] + ? this.extensions[maybeIndex] : undefined; // the presence of an extension indicates it's accessible diff --git a/libs/common/src/tools/extension/metadata/extension-registry.abstraction.ts b/libs/common/src/tools/extension/extension-registry.abstraction.ts similarity index 65% rename from libs/common/src/tools/extension/metadata/extension-registry.abstraction.ts rename to libs/common/src/tools/extension/extension-registry.abstraction.ts index 50d267d4214..9ea317f1585 100644 --- a/libs/common/src/tools/extension/metadata/extension-registry.abstraction.ts +++ b/libs/common/src/tools/extension/extension-registry.abstraction.ts @@ -1,13 +1,18 @@ -import { ExtensionSite } from "../extension-site"; - -import { SiteMetadata, ExtensionMetadata, ExtensionSet, VendorMetadata, SiteId } from "./type"; +import { ExtensionSite } from "./extension-site"; +import { + SiteMetadata, + ExtensionMetadata, + ExtensionSet, + VendorMetadata, + SiteId, +} from "./metadata/type"; /** Permission levels for metadata. * * default - unless a rule denies access, allow it. This is the * default permission. * * none - unless a rule allows access, deny it. - * * allow - access is explicitly granted to use an integration. - * * deny - access is explicitly prohibited for this integration. This + * * allow - access is explicitly granted to use an extension. + * * deny - access is explicitly prohibited for this extension. This * rule overrides allow rules. */ export type ExtensionPermission = "default" | "none" | "allow" | "deny"; @@ -20,49 +25,49 @@ export abstract class ExtensionRegistry { */ registerSite: (meta: SiteMetadata) => this; - /** List all registered extension sites with their integration rule, if any. + /** List all registered extension sites with their extension rule, if any. * @returns a list of all extension sites. `rule` is defined when the site - * is associated with an integration rule. + * is associated with an extension rule. */ sites: () => { site: SiteMetadata; permission?: ExtensionPermission }[]; - /** Registers a vendor providing an integration + /** Registers a vendor providing an extension * @param site - identifies the site being extended * @param meta - configures the extension site * @return self for method chaining. */ registerVendor: (meta: VendorMetadata) => this; - /** List all registered vendors with their integration rule, if any. + /** List all registered vendors with their extension rule, if any. * @returns a list of all extension sites. `rule` is defined when the site - * is associated with an integration rule. + * is associated with an extension rule. */ vendors: () => { vendor: VendorMetadata; permission?: ExtensionPermission }[]; - /** Registers an integration provided by a vendor to an extension site. - * The vendor and site MUST be registered before the integration. + /** Registers an extension provided by a vendor to an extension site. + * The vendor and site MUST be registered before the extension. * @param site - identifies the site being extended * @param meta - configures the extension site * @return self for method chaining. */ registerExtension: (meta: ExtensionMetadata) => this; - /** Registers a rule. Only 1 rule can be registered for each integration set. + /** Registers a rule. Only 1 rule can be registered for each extension set. * The last-registered rule wins. - * @param set the collection of integrations affected by the rule + * @param set the collection of extensions affected by the rule * @param permission the permission for the collection * @return self for method chaining. */ setPermission: (set: ExtensionSet, permission: ExtensionPermission) => this; - /** Retrieves the current rule for the given integration set or undefined if a rule + /** Retrieves the current rule for the given extension set or undefined if a rule * doesn't exist. */ permission: (set: ExtensionSet) => ExtensionPermission | undefined; - /** Returns all registered integration rules. */ + /** Returns all registered extension rules. */ permissions: () => { set: ExtensionSet; permission: ExtensionPermission }[]; - /** Creates a point-in-time snapshot of the registry's contents with integration + /** Creates a point-in-time snapshot of the registry's contents with extension * permissions applied for the provided SiteId. * @returns the extension site, or `undefined` if the site is not registered. */ diff --git a/libs/common/src/tools/extension/extension.service.ts b/libs/common/src/tools/extension/extension.service.ts index cadb2a7926b..e9a33b76e9e 100644 --- a/libs/common/src/tools/extension/extension.service.ts +++ b/libs/common/src/tools/extension/extension.service.ts @@ -2,11 +2,11 @@ import { StateProvider } from "@bitwarden/common/platform/state"; import { LegacyEncryptorProvider } from "../cryptography/legacy-encryptor-provider"; -import { DefaultIntegrationRegistry } from "./metadata/default-extension-registry"; +import { DefaultExtensionRegistry } from "./default-extension-registry"; export class ExtensionService { constructor( - private readonly registry: DefaultIntegrationRegistry, + private readonly registry: DefaultExtensionRegistry, private readonly stateProvider: StateProvider, private readonly encryptorProvider: LegacyEncryptorProvider, ) {} diff --git a/libs/common/src/tools/extension/factory.ts b/libs/common/src/tools/extension/factory.ts new file mode 100644 index 00000000000..87c7a012056 --- /dev/null +++ b/libs/common/src/tools/extension/factory.ts @@ -0,0 +1,36 @@ +import { AddyIo, AddyIoExtensions } from "./data/addy-io"; +import { DuckDuckGo, DuckDuckGoExtensions } from "./data/duck-duck-go"; +import { Fastmail, FastmailExtensions } from "./data/fastmail"; +import { ForwardEmail, ForwardEmailExtensions } from "./data/forward-email"; +import { Mozilla, MozillaExtensions } from "./data/mozilla"; +import { SimpleLogin, SimpleLoginExtensions } from "./data/simple-login"; +import { DefaultExtensionRegistry } from "./default-extension-registry"; +import { Extension } from "./metadata/extension"; +import { ExtensionMetadata, VendorMetadata } from "./metadata/type"; + +// FIXME: find a better way to build the registry than a hard-coded factory function + +/** Constructs the extension registry */ +export function buildRegistry() { + function registerAll(vendor: VendorMetadata, extensions: ExtensionMetadata[]) { + registry.registerVendor(vendor); + for (const extension of extensions) { + registry.registerExtension(extension); + } + } + + const registry = new DefaultExtensionRegistry(); + + for (const site of Reflect.ownKeys(Extension) as string[]) { + registry.registerSite(Extension[site]); + } + + registerAll(AddyIo, AddyIoExtensions); + registerAll(DuckDuckGo, DuckDuckGoExtensions); + registerAll(Fastmail, FastmailExtensions); + registerAll(ForwardEmail, ForwardEmailExtensions); + registerAll(Mozilla, MozillaExtensions); + registerAll(SimpleLogin, SimpleLoginExtensions); + + return registry; +} diff --git a/libs/common/src/tools/extension/metadata/factory.ts b/libs/common/src/tools/extension/metadata/factory.ts deleted file mode 100644 index bb83ce3b9e9..00000000000 --- a/libs/common/src/tools/extension/metadata/factory.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { AddyIo, AddyIoIntegrations } from "../data/addy-io"; -import { DuckDuckGo, DuckDuckGoIntegrations } from "../data/duck-duck-go"; -import { Fastmail, FastmailIntegrations } from "../data/fastmail"; -import { ForwardEmail, ForwardEmailIntegrations } from "../data/forward-email"; -import { Mozilla, MozillaIntegrations } from "../data/mozilla"; -import { SimpleLogin, SimpleLoginIntegrations } from "../data/simple-login"; - -import { DefaultIntegrationRegistry } from "./default-extension-registry"; -import { Extension } from "./extension"; -import { ExtensionMetadata, VendorMetadata } from "./type"; - -/** Constructs the integration registry */ -export function buildRegistry() { - // FIXME: find a better way to build the registry than a hard-coded factory function - function registerAll(vendor: VendorMetadata, integrations: ExtensionMetadata[]) { - registry.registerVendor(vendor); - for (const integration of integrations) { - registry.registerExtension(integration); - } - } - - const registry = new DefaultIntegrationRegistry(); - - for (const site of Reflect.ownKeys(Extension) as string[]) { - registry.registerSite(Extension[site]); - } - - registerAll(AddyIo, AddyIoIntegrations); - registerAll(DuckDuckGo, DuckDuckGoIntegrations); - registerAll(Fastmail, FastmailIntegrations); - registerAll(ForwardEmail, ForwardEmailIntegrations); - registerAll(Mozilla, MozillaIntegrations); - registerAll(SimpleLogin, SimpleLoginIntegrations); - - return registry; -} diff --git a/libs/common/src/tools/extension/metadata/type.ts b/libs/common/src/tools/extension/metadata/type.ts index 616febe9ca6..d319d6e2aed 100644 --- a/libs/common/src/tools/extension/metadata/type.ts +++ b/libs/common/src/tools/extension/metadata/type.ts @@ -1,17 +1,17 @@ import { FieldsBySite, Site, VendorsByExtension } from "./data"; -/** well-known name for a feature extensible through an integration. */ +/** well-known name for a feature extensible through an extension. */ export type SiteId = keyof typeof Site; /** well-known name for a field surfaced from an extension site to a vendor. */ export type DisclosedField = (typeof FieldsBySite)[SiteId][number]; -/** Identifies a vendor integrated into bitwarden */ +/** Identifies a vendor extending bitwarden */ export type VendorId = (typeof VendorsByExtension)[SiteId][number]; -/** The capabilities and descriptive content for an integration */ +/** The capabilities and descriptive content for an extension */ export type SiteMetadata = { - /** Uniquely identifies the integrator. */ + /** Uniquely identifies the extension site. */ id: SiteId; /** Lists the fields disclosed by the extension to the vendor */ @@ -33,7 +33,7 @@ type TokenHeader = authorization: "bearer" | "token" | "basic-username"; }; -/** Catalogues an integration's hosting status. +/** Catalogues an extension's hosting status. * selfHost: "never" always uses the service's base URL * selfHost: "maybe" allows the user to override the service's * base URL with their own. @@ -46,16 +46,16 @@ export type ApiHost = TokenHeader & | { selfHost: "always" } ); -/** The capabilities and descriptive content for an integration */ +/** The capabilities and descriptive content for an extension */ export type VendorMetadata = { - /** Uniquely identifies the integrator. */ + /** Uniquely identifies the vendor. */ id: VendorId; - /** Brand name of the integrator. */ + /** Brand name of the service providing the extension. */ name: string; }; -/** Describes an integration provided by a vendor */ +/** Describes an extension provided by a vendor */ export type ExtensionMetadata = { /** The part of Bitwarden extended by the vendor's services */ site: SiteMetadata; @@ -69,7 +69,7 @@ export type ExtensionMetadata = { name?: string; }; - /** Hosting provider capabilities required by the integration */ + /** Hosting provider capabilities required by the extension */ host: ApiHost; /** Lists the fields disclosed by the extension to the vendor. @@ -79,20 +79,20 @@ export type ExtensionMetadata = { requestedFields: DisclosedField[]; }; -/** Identifies a collection of integrations. +/** Identifies a collection of extensions. */ export type ExtensionSet = | { - /** A set of integrations sharing an extension point */ + /** A set of extensions sharing an extension point */ site: SiteId; } | { - /** A set of integrations sharing a vendor */ + /** A set of extensions sharing a vendor */ vendor: VendorId; } | { - /** The total set of integrations. This is used to set a categorical - * rule affecting all integrations. + /** The total set of extensions. This is used to set a categorical + * rule affecting all extensions. */ all: true; };