mirror of
https://github.com/bitwarden/browser
synced 2025-12-20 18:23:31 +00:00
[PM-7289] implement generator libraries (#9549)
This is a copy of the files. The source in `@bitwarden/common` will be deleted once all of the applications have been ported to the library.
This commit is contained in:
110
libs/tools/generator/extensions/src/legacy-username/factory.ts
Normal file
110
libs/tools/generator/extensions/src/legacy-username/factory.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { StateProvider } from "@bitwarden/common/platform/state";
|
||||
import { engine, services, strategies } from "@bitwarden/generator-core";
|
||||
|
||||
import { DefaultGeneratorNavigationService } from "../navigation";
|
||||
|
||||
import { LegacyUsernameGenerationService } from "./legacy-username-generation.service";
|
||||
import { UsernameGenerationServiceAbstraction } from "./username-generation.service.abstraction";
|
||||
|
||||
const DefaultGeneratorService = services.DefaultGeneratorService;
|
||||
const CryptoServiceRandomizer = engine.CryptoServiceRandomizer;
|
||||
const CatchallGeneratorStrategy = strategies.CatchallGeneratorStrategy;
|
||||
const SubaddressGeneratorStrategy = strategies.SubaddressGeneratorStrategy;
|
||||
const EffUsernameGeneratorStrategy = strategies.EffUsernameGeneratorStrategy;
|
||||
const AddyIoForwarder = strategies.AddyIoForwarder;
|
||||
const DuckDuckGoForwarder = strategies.DuckDuckGoForwarder;
|
||||
const FastmailForwarder = strategies.FastmailForwarder;
|
||||
const FirefoxRelayForwarder = strategies.FirefoxRelayForwarder;
|
||||
const ForwardEmailForwarder = strategies.ForwardEmailForwarder;
|
||||
const SimpleLoginForwarder = strategies.SimpleLoginForwarder;
|
||||
|
||||
export function legacyUsernameGenerationServiceFactory(
|
||||
apiService: ApiService,
|
||||
i18nService: I18nService,
|
||||
cryptoService: CryptoService,
|
||||
encryptService: EncryptService,
|
||||
policyService: PolicyService,
|
||||
accountService: AccountService,
|
||||
stateProvider: StateProvider,
|
||||
): UsernameGenerationServiceAbstraction {
|
||||
const randomizer = new CryptoServiceRandomizer(cryptoService);
|
||||
|
||||
const effUsername = new DefaultGeneratorService(
|
||||
new EffUsernameGeneratorStrategy(randomizer, stateProvider),
|
||||
policyService,
|
||||
);
|
||||
|
||||
const subaddress = new DefaultGeneratorService(
|
||||
new SubaddressGeneratorStrategy(randomizer, stateProvider),
|
||||
policyService,
|
||||
);
|
||||
|
||||
const catchall = new DefaultGeneratorService(
|
||||
new CatchallGeneratorStrategy(randomizer, stateProvider),
|
||||
policyService,
|
||||
);
|
||||
|
||||
const addyIo = new DefaultGeneratorService(
|
||||
new AddyIoForwarder(apiService, i18nService, encryptService, cryptoService, stateProvider),
|
||||
policyService,
|
||||
);
|
||||
|
||||
const duckDuckGo = new DefaultGeneratorService(
|
||||
new DuckDuckGoForwarder(apiService, i18nService, encryptService, cryptoService, stateProvider),
|
||||
policyService,
|
||||
);
|
||||
|
||||
const fastmail = new DefaultGeneratorService(
|
||||
new FastmailForwarder(apiService, i18nService, encryptService, cryptoService, stateProvider),
|
||||
policyService,
|
||||
);
|
||||
|
||||
const firefoxRelay = new DefaultGeneratorService(
|
||||
new FirefoxRelayForwarder(
|
||||
apiService,
|
||||
i18nService,
|
||||
encryptService,
|
||||
cryptoService,
|
||||
stateProvider,
|
||||
),
|
||||
policyService,
|
||||
);
|
||||
|
||||
const forwardEmail = new DefaultGeneratorService(
|
||||
new ForwardEmailForwarder(
|
||||
apiService,
|
||||
i18nService,
|
||||
encryptService,
|
||||
cryptoService,
|
||||
stateProvider,
|
||||
),
|
||||
policyService,
|
||||
);
|
||||
|
||||
const simpleLogin = new DefaultGeneratorService(
|
||||
new SimpleLoginForwarder(apiService, i18nService, encryptService, cryptoService, stateProvider),
|
||||
policyService,
|
||||
);
|
||||
|
||||
const navigation = new DefaultGeneratorNavigationService(stateProvider, policyService);
|
||||
|
||||
return new LegacyUsernameGenerationService(
|
||||
accountService,
|
||||
navigation,
|
||||
catchall,
|
||||
effUsername,
|
||||
subaddress,
|
||||
addyIo,
|
||||
duckDuckGo,
|
||||
fastmail,
|
||||
firefoxRelay,
|
||||
forwardEmail,
|
||||
simpleLogin,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from "./username-generation.service.abstraction";
|
||||
export * from "./factory";
|
||||
export * from "./username-generation-options";
|
||||
@@ -0,0 +1,749 @@
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { of } from "rxjs";
|
||||
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import {
|
||||
ApiOptions,
|
||||
EmailDomainOptions,
|
||||
EmailPrefixOptions,
|
||||
SelfHostedApiOptions,
|
||||
GeneratorService,
|
||||
NoPolicy,
|
||||
CatchallGenerationOptions,
|
||||
DefaultCatchallOptions,
|
||||
DefaultEffUsernameOptions,
|
||||
EffUsernameGenerationOptions,
|
||||
DefaultAddyIoOptions,
|
||||
DefaultDuckDuckGoOptions,
|
||||
DefaultFastmailOptions,
|
||||
DefaultFirefoxRelayOptions,
|
||||
DefaultForwardEmailOptions,
|
||||
DefaultSimpleLoginOptions,
|
||||
Forwarders,
|
||||
DefaultSubaddressOptions,
|
||||
SubaddressGenerationOptions,
|
||||
policies,
|
||||
} from "@bitwarden/generator-core";
|
||||
|
||||
import { mockAccountServiceWith } from "../../../../../common/spec";
|
||||
import {
|
||||
GeneratorNavigationPolicy,
|
||||
GeneratorNavigationEvaluator,
|
||||
DefaultGeneratorNavigation,
|
||||
GeneratorNavigation,
|
||||
GeneratorNavigationService,
|
||||
} from "../navigation";
|
||||
|
||||
import { LegacyUsernameGenerationService } from "./legacy-username-generation.service";
|
||||
import { UsernameGeneratorOptions } from "./username-generation-options";
|
||||
|
||||
const DefaultPolicyEvaluator = policies.DefaultPolicyEvaluator;
|
||||
|
||||
const SomeUser = "userId" as UserId;
|
||||
|
||||
function createGenerator<Options>(options: Options, defaults: Options) {
|
||||
let savedOptions = options;
|
||||
const generator = mock<GeneratorService<Options, NoPolicy>>({
|
||||
evaluator$(id: UserId) {
|
||||
const evaluator = new DefaultPolicyEvaluator<Options>();
|
||||
return of(evaluator);
|
||||
},
|
||||
options$(id: UserId) {
|
||||
return of(savedOptions);
|
||||
},
|
||||
defaults$(id: UserId) {
|
||||
return of(defaults);
|
||||
},
|
||||
saveOptions: jest.fn((userId, options) => {
|
||||
savedOptions = options;
|
||||
return Promise.resolve();
|
||||
}),
|
||||
});
|
||||
|
||||
return generator;
|
||||
}
|
||||
|
||||
function createNavigationGenerator(
|
||||
options: GeneratorNavigation = {},
|
||||
policy: GeneratorNavigationPolicy = {},
|
||||
) {
|
||||
let savedOptions = options;
|
||||
const generator = mock<GeneratorNavigationService>({
|
||||
evaluator$(id: UserId) {
|
||||
const evaluator = new GeneratorNavigationEvaluator(policy);
|
||||
return of(evaluator);
|
||||
},
|
||||
options$(id: UserId) {
|
||||
return of(savedOptions);
|
||||
},
|
||||
defaults$(id: UserId) {
|
||||
return of(DefaultGeneratorNavigation);
|
||||
},
|
||||
saveOptions: jest.fn((userId, options) => {
|
||||
savedOptions = options;
|
||||
return Promise.resolve();
|
||||
}),
|
||||
});
|
||||
|
||||
return generator;
|
||||
}
|
||||
|
||||
describe("LegacyUsernameGenerationService", () => {
|
||||
// NOTE: in all tests, `null` constructor arguments are not used by the test.
|
||||
// They're set to `null` to avoid setting up unnecessary mocks.
|
||||
describe("generateUserName", () => {
|
||||
it("should generate a catchall username", async () => {
|
||||
const options = { type: "catchall" } as UsernameGeneratorOptions;
|
||||
const catchall = createGenerator<CatchallGenerationOptions>(null, null);
|
||||
catchall.generate.mockResolvedValue("catchall@example.com");
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
null,
|
||||
null,
|
||||
catchall,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
const result = await generator.generateUsername(options);
|
||||
|
||||
expect(catchall.generate).toHaveBeenCalledWith(options);
|
||||
expect(result).toBe("catchall@example.com");
|
||||
});
|
||||
|
||||
it("should generate an EFF word username", async () => {
|
||||
const options = { type: "word" } as UsernameGeneratorOptions;
|
||||
const effWord = createGenerator<EffUsernameGenerationOptions>(null, null);
|
||||
effWord.generate.mockResolvedValue("eff word");
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
effWord,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
const result = await generator.generateUsername(options);
|
||||
|
||||
expect(effWord.generate).toHaveBeenCalledWith(options);
|
||||
expect(result).toBe("eff word");
|
||||
});
|
||||
|
||||
it("should generate a subaddress username", async () => {
|
||||
const options = { type: "subaddress" } as UsernameGeneratorOptions;
|
||||
const subaddress = createGenerator<SubaddressGenerationOptions>(null, null);
|
||||
subaddress.generate.mockResolvedValue("subaddress@example.com");
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
subaddress,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
const result = await generator.generateUsername(options);
|
||||
|
||||
expect(subaddress.generate).toHaveBeenCalledWith(options);
|
||||
expect(result).toBe("subaddress@example.com");
|
||||
});
|
||||
|
||||
it("should generate a forwarder username", async () => {
|
||||
// set up an arbitrary forwarder for the username test; all forwarders tested in their own tests
|
||||
const options = {
|
||||
type: "forwarded",
|
||||
forwardedService: Forwarders.AddyIo.id,
|
||||
} as UsernameGeneratorOptions;
|
||||
const addyIo = createGenerator<SelfHostedApiOptions & EmailDomainOptions>(null, null);
|
||||
addyIo.generate.mockResolvedValue("addyio@example.com");
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
addyIo,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
const result = await generator.generateUsername(options);
|
||||
|
||||
expect(addyIo.generate).toHaveBeenCalledWith({});
|
||||
expect(result).toBe("addyio@example.com");
|
||||
});
|
||||
});
|
||||
|
||||
describe("generateCatchall", () => {
|
||||
it("should generate a catchall username", async () => {
|
||||
const options = { type: "catchall" } as UsernameGeneratorOptions;
|
||||
const catchall = createGenerator<CatchallGenerationOptions>(null, null);
|
||||
catchall.generate.mockResolvedValue("catchall@example.com");
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
null,
|
||||
null,
|
||||
catchall,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
const result = await generator.generateCatchall(options);
|
||||
|
||||
expect(catchall.generate).toHaveBeenCalledWith(options);
|
||||
expect(result).toBe("catchall@example.com");
|
||||
});
|
||||
});
|
||||
|
||||
describe("generateSubaddress", () => {
|
||||
it("should generate a subaddress username", async () => {
|
||||
const options = { type: "subaddress" } as UsernameGeneratorOptions;
|
||||
const subaddress = createGenerator<SubaddressGenerationOptions>(null, null);
|
||||
subaddress.generate.mockResolvedValue("subaddress@example.com");
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
subaddress,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
const result = await generator.generateSubaddress(options);
|
||||
|
||||
expect(subaddress.generate).toHaveBeenCalledWith(options);
|
||||
expect(result).toBe("subaddress@example.com");
|
||||
});
|
||||
});
|
||||
|
||||
describe("generateForwarded", () => {
|
||||
it("should generate a AddyIo username", async () => {
|
||||
const options = {
|
||||
forwardedService: Forwarders.AddyIo.id,
|
||||
forwardedAnonAddyApiToken: "token",
|
||||
forwardedAnonAddyBaseUrl: "https://example.com",
|
||||
forwardedAnonAddyDomain: "example.com",
|
||||
website: "example.com",
|
||||
} as UsernameGeneratorOptions;
|
||||
const addyIo = createGenerator<SelfHostedApiOptions & EmailDomainOptions>(null, null);
|
||||
addyIo.generate.mockResolvedValue("addyio@example.com");
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
addyIo,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
const result = await generator.generateForwarded(options);
|
||||
|
||||
expect(addyIo.generate).toHaveBeenCalledWith({
|
||||
token: "token",
|
||||
baseUrl: "https://example.com",
|
||||
domain: "example.com",
|
||||
website: "example.com",
|
||||
});
|
||||
expect(result).toBe("addyio@example.com");
|
||||
});
|
||||
|
||||
it("should generate a DuckDuckGo username", async () => {
|
||||
const options = {
|
||||
forwardedService: Forwarders.DuckDuckGo.id,
|
||||
forwardedDuckDuckGoToken: "token",
|
||||
website: "example.com",
|
||||
} as UsernameGeneratorOptions;
|
||||
const duckDuckGo = createGenerator<ApiOptions>(null, null);
|
||||
duckDuckGo.generate.mockResolvedValue("ddg@example.com");
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
duckDuckGo,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
const result = await generator.generateForwarded(options);
|
||||
|
||||
expect(duckDuckGo.generate).toHaveBeenCalledWith({
|
||||
token: "token",
|
||||
website: "example.com",
|
||||
});
|
||||
expect(result).toBe("ddg@example.com");
|
||||
});
|
||||
|
||||
it("should generate a Fastmail username", async () => {
|
||||
const options = {
|
||||
forwardedService: Forwarders.Fastmail.id,
|
||||
forwardedFastmailApiToken: "token",
|
||||
website: "example.com",
|
||||
} as UsernameGeneratorOptions;
|
||||
const fastmail = createGenerator<ApiOptions & EmailPrefixOptions>(null, null);
|
||||
fastmail.generate.mockResolvedValue("fastmail@example.com");
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
fastmail,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
const result = await generator.generateForwarded(options);
|
||||
|
||||
expect(fastmail.generate).toHaveBeenCalledWith({
|
||||
token: "token",
|
||||
website: "example.com",
|
||||
});
|
||||
expect(result).toBe("fastmail@example.com");
|
||||
});
|
||||
|
||||
it("should generate a FirefoxRelay username", async () => {
|
||||
const options = {
|
||||
forwardedService: Forwarders.FirefoxRelay.id,
|
||||
forwardedFirefoxApiToken: "token",
|
||||
website: "example.com",
|
||||
} as UsernameGeneratorOptions;
|
||||
const firefoxRelay = createGenerator<ApiOptions>(null, null);
|
||||
firefoxRelay.generate.mockResolvedValue("firefoxrelay@example.com");
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
firefoxRelay,
|
||||
null,
|
||||
null,
|
||||
);
|
||||
|
||||
const result = await generator.generateForwarded(options);
|
||||
|
||||
expect(firefoxRelay.generate).toHaveBeenCalledWith({
|
||||
token: "token",
|
||||
website: "example.com",
|
||||
});
|
||||
expect(result).toBe("firefoxrelay@example.com");
|
||||
});
|
||||
|
||||
it("should generate a ForwardEmail username", async () => {
|
||||
const options = {
|
||||
forwardedService: Forwarders.ForwardEmail.id,
|
||||
forwardedForwardEmailApiToken: "token",
|
||||
forwardedForwardEmailDomain: "example.com",
|
||||
website: "example.com",
|
||||
} as UsernameGeneratorOptions;
|
||||
const forwardEmail = createGenerator<ApiOptions & EmailDomainOptions>(null, null);
|
||||
forwardEmail.generate.mockResolvedValue("forwardemail@example.com");
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
forwardEmail,
|
||||
null,
|
||||
);
|
||||
|
||||
const result = await generator.generateForwarded(options);
|
||||
|
||||
expect(forwardEmail.generate).toHaveBeenCalledWith({
|
||||
token: "token",
|
||||
domain: "example.com",
|
||||
website: "example.com",
|
||||
});
|
||||
expect(result).toBe("forwardemail@example.com");
|
||||
});
|
||||
|
||||
it("should generate a SimpleLogin username", async () => {
|
||||
const options = {
|
||||
forwardedService: Forwarders.SimpleLogin.id,
|
||||
forwardedSimpleLoginApiKey: "token",
|
||||
forwardedSimpleLoginBaseUrl: "https://example.com",
|
||||
website: "example.com",
|
||||
} as UsernameGeneratorOptions;
|
||||
const simpleLogin = createGenerator<SelfHostedApiOptions>(null, null);
|
||||
simpleLogin.generate.mockResolvedValue("simplelogin@example.com");
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
simpleLogin,
|
||||
);
|
||||
|
||||
const result = await generator.generateForwarded(options);
|
||||
|
||||
expect(simpleLogin.generate).toHaveBeenCalledWith({
|
||||
token: "token",
|
||||
baseUrl: "https://example.com",
|
||||
website: "example.com",
|
||||
});
|
||||
expect(result).toBe("simplelogin@example.com");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getOptions", () => {
|
||||
it("combines options from its inner generators", async () => {
|
||||
const account = mockAccountServiceWith(SomeUser);
|
||||
|
||||
const navigation = createNavigationGenerator({
|
||||
type: "username",
|
||||
username: "catchall",
|
||||
forwarder: Forwarders.AddyIo.id,
|
||||
});
|
||||
|
||||
const catchall = createGenerator<CatchallGenerationOptions>(
|
||||
{
|
||||
catchallDomain: "example.com",
|
||||
catchallType: "random",
|
||||
website: null,
|
||||
},
|
||||
null,
|
||||
);
|
||||
|
||||
const effUsername = createGenerator<EffUsernameGenerationOptions>(
|
||||
{
|
||||
wordCapitalize: true,
|
||||
wordIncludeNumber: false,
|
||||
website: null,
|
||||
},
|
||||
null,
|
||||
);
|
||||
|
||||
const subaddress = createGenerator<SubaddressGenerationOptions>(
|
||||
{
|
||||
subaddressType: "random",
|
||||
subaddressEmail: "foo@example.com",
|
||||
website: null,
|
||||
},
|
||||
null,
|
||||
);
|
||||
|
||||
const addyIo = createGenerator<SelfHostedApiOptions & EmailDomainOptions>(
|
||||
{
|
||||
token: "addyIoToken",
|
||||
domain: "addyio.example.com",
|
||||
baseUrl: "https://addyio.api.example.com",
|
||||
website: null,
|
||||
},
|
||||
null,
|
||||
);
|
||||
|
||||
const duckDuckGo = createGenerator<ApiOptions>(
|
||||
{
|
||||
token: "ddgToken",
|
||||
website: null,
|
||||
},
|
||||
null,
|
||||
);
|
||||
|
||||
const fastmail = createGenerator<ApiOptions & EmailPrefixOptions>(
|
||||
{
|
||||
token: "fastmailToken",
|
||||
domain: "fastmail.example.com",
|
||||
prefix: "foo",
|
||||
website: null,
|
||||
},
|
||||
null,
|
||||
);
|
||||
|
||||
const firefoxRelay = createGenerator<ApiOptions>(
|
||||
{
|
||||
token: "firefoxToken",
|
||||
website: null,
|
||||
},
|
||||
null,
|
||||
);
|
||||
|
||||
const forwardEmail = createGenerator<ApiOptions & EmailDomainOptions>(
|
||||
{
|
||||
token: "forwardEmailToken",
|
||||
domain: "example.com",
|
||||
website: null,
|
||||
},
|
||||
null,
|
||||
);
|
||||
|
||||
const simpleLogin = createGenerator<SelfHostedApiOptions>(
|
||||
{
|
||||
token: "simpleLoginToken",
|
||||
baseUrl: "https://simplelogin.api.example.com",
|
||||
website: null,
|
||||
},
|
||||
null,
|
||||
);
|
||||
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
account,
|
||||
navigation,
|
||||
catchall,
|
||||
effUsername,
|
||||
subaddress,
|
||||
addyIo,
|
||||
duckDuckGo,
|
||||
fastmail,
|
||||
firefoxRelay,
|
||||
forwardEmail,
|
||||
simpleLogin,
|
||||
);
|
||||
|
||||
const result = await generator.getOptions();
|
||||
|
||||
expect(result).toEqual({
|
||||
type: "catchall",
|
||||
wordCapitalize: true,
|
||||
wordIncludeNumber: false,
|
||||
subaddressType: "random",
|
||||
subaddressEmail: "foo@example.com",
|
||||
catchallType: "random",
|
||||
catchallDomain: "example.com",
|
||||
forwardedService: Forwarders.AddyIo.id,
|
||||
forwardedAnonAddyApiToken: "addyIoToken",
|
||||
forwardedAnonAddyDomain: "addyio.example.com",
|
||||
forwardedAnonAddyBaseUrl: "https://addyio.api.example.com",
|
||||
forwardedDuckDuckGoToken: "ddgToken",
|
||||
forwardedFirefoxApiToken: "firefoxToken",
|
||||
forwardedFastmailApiToken: "fastmailToken",
|
||||
forwardedForwardEmailApiToken: "forwardEmailToken",
|
||||
forwardedForwardEmailDomain: "example.com",
|
||||
forwardedSimpleLoginApiKey: "simpleLoginToken",
|
||||
forwardedSimpleLoginBaseUrl: "https://simplelogin.api.example.com",
|
||||
});
|
||||
});
|
||||
|
||||
it("sets default options when an inner service lacks a value", async () => {
|
||||
const account = mockAccountServiceWith(SomeUser);
|
||||
const navigation = createNavigationGenerator(null);
|
||||
const catchall = createGenerator<CatchallGenerationOptions>(null, DefaultCatchallOptions);
|
||||
const effUsername = createGenerator<EffUsernameGenerationOptions>(
|
||||
null,
|
||||
DefaultEffUsernameOptions,
|
||||
);
|
||||
const subaddress = createGenerator<SubaddressGenerationOptions>(
|
||||
null,
|
||||
DefaultSubaddressOptions,
|
||||
);
|
||||
const addyIo = createGenerator<SelfHostedApiOptions & EmailDomainOptions>(
|
||||
null,
|
||||
DefaultAddyIoOptions,
|
||||
);
|
||||
const duckDuckGo = createGenerator<ApiOptions>(null, DefaultDuckDuckGoOptions);
|
||||
const fastmail = createGenerator<ApiOptions & EmailPrefixOptions>(
|
||||
null,
|
||||
DefaultFastmailOptions,
|
||||
);
|
||||
const firefoxRelay = createGenerator<ApiOptions>(null, DefaultFirefoxRelayOptions);
|
||||
const forwardEmail = createGenerator<ApiOptions & EmailDomainOptions>(
|
||||
null,
|
||||
DefaultForwardEmailOptions,
|
||||
);
|
||||
const simpleLogin = createGenerator<SelfHostedApiOptions>(null, DefaultSimpleLoginOptions);
|
||||
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
account,
|
||||
navigation,
|
||||
catchall,
|
||||
effUsername,
|
||||
subaddress,
|
||||
addyIo,
|
||||
duckDuckGo,
|
||||
fastmail,
|
||||
firefoxRelay,
|
||||
forwardEmail,
|
||||
simpleLogin,
|
||||
);
|
||||
|
||||
const result = await generator.getOptions();
|
||||
|
||||
expect(result).toEqual({
|
||||
type: DefaultGeneratorNavigation.username,
|
||||
catchallType: DefaultCatchallOptions.catchallType,
|
||||
catchallDomain: DefaultCatchallOptions.catchallDomain,
|
||||
wordCapitalize: DefaultEffUsernameOptions.wordCapitalize,
|
||||
wordIncludeNumber: DefaultEffUsernameOptions.wordIncludeNumber,
|
||||
subaddressType: DefaultSubaddressOptions.subaddressType,
|
||||
subaddressEmail: DefaultSubaddressOptions.subaddressEmail,
|
||||
forwardedService: DefaultGeneratorNavigation.forwarder,
|
||||
forwardedAnonAddyApiToken: DefaultAddyIoOptions.token,
|
||||
forwardedAnonAddyDomain: DefaultAddyIoOptions.domain,
|
||||
forwardedAnonAddyBaseUrl: DefaultAddyIoOptions.baseUrl,
|
||||
forwardedDuckDuckGoToken: DefaultDuckDuckGoOptions.token,
|
||||
forwardedFastmailApiToken: DefaultFastmailOptions.token,
|
||||
forwardedFirefoxApiToken: DefaultFirefoxRelayOptions.token,
|
||||
forwardedForwardEmailApiToken: DefaultForwardEmailOptions.token,
|
||||
forwardedForwardEmailDomain: DefaultForwardEmailOptions.domain,
|
||||
forwardedSimpleLoginApiKey: DefaultSimpleLoginOptions.token,
|
||||
forwardedSimpleLoginBaseUrl: DefaultSimpleLoginOptions.baseUrl,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("saveOptions", () => {
|
||||
it("saves option sets to its inner generators", async () => {
|
||||
const account = mockAccountServiceWith(SomeUser);
|
||||
const navigation = createNavigationGenerator({ type: "password" });
|
||||
const catchall = createGenerator<CatchallGenerationOptions>(null, null);
|
||||
const effUsername = createGenerator<EffUsernameGenerationOptions>(null, null);
|
||||
const subaddress = createGenerator<SubaddressGenerationOptions>(null, null);
|
||||
const addyIo = createGenerator<SelfHostedApiOptions & EmailDomainOptions>(null, null);
|
||||
const duckDuckGo = createGenerator<ApiOptions>(null, null);
|
||||
const fastmail = createGenerator<ApiOptions & EmailPrefixOptions>(null, null);
|
||||
const firefoxRelay = createGenerator<ApiOptions>(null, null);
|
||||
const forwardEmail = createGenerator<ApiOptions & EmailDomainOptions>(null, null);
|
||||
const simpleLogin = createGenerator<SelfHostedApiOptions>(null, null);
|
||||
|
||||
const generator = new LegacyUsernameGenerationService(
|
||||
account,
|
||||
navigation,
|
||||
catchall,
|
||||
effUsername,
|
||||
subaddress,
|
||||
addyIo,
|
||||
duckDuckGo,
|
||||
fastmail,
|
||||
firefoxRelay,
|
||||
forwardEmail,
|
||||
simpleLogin,
|
||||
);
|
||||
|
||||
await generator.saveOptions({
|
||||
type: "catchall",
|
||||
wordCapitalize: true,
|
||||
wordIncludeNumber: false,
|
||||
subaddressType: "random",
|
||||
subaddressEmail: "foo@example.com",
|
||||
catchallType: "random",
|
||||
catchallDomain: "example.com",
|
||||
forwardedService: Forwarders.AddyIo.id,
|
||||
forwardedAnonAddyApiToken: "addyIoToken",
|
||||
forwardedAnonAddyDomain: "addyio.example.com",
|
||||
forwardedAnonAddyBaseUrl: "https://addyio.api.example.com",
|
||||
forwardedDuckDuckGoToken: "ddgToken",
|
||||
forwardedFirefoxApiToken: "firefoxToken",
|
||||
forwardedFastmailApiToken: "fastmailToken",
|
||||
forwardedForwardEmailApiToken: "forwardEmailToken",
|
||||
forwardedForwardEmailDomain: "example.com",
|
||||
forwardedSimpleLoginApiKey: "simpleLoginToken",
|
||||
forwardedSimpleLoginBaseUrl: "https://simplelogin.api.example.com",
|
||||
website: null,
|
||||
});
|
||||
|
||||
expect(navigation.saveOptions).toHaveBeenCalledWith(SomeUser, {
|
||||
type: "password",
|
||||
username: "catchall",
|
||||
forwarder: Forwarders.AddyIo.id,
|
||||
});
|
||||
|
||||
expect(catchall.saveOptions).toHaveBeenCalledWith(SomeUser, {
|
||||
catchallDomain: "example.com",
|
||||
catchallType: "random",
|
||||
website: null,
|
||||
});
|
||||
|
||||
expect(effUsername.saveOptions).toHaveBeenCalledWith(SomeUser, {
|
||||
wordCapitalize: true,
|
||||
wordIncludeNumber: false,
|
||||
website: null,
|
||||
});
|
||||
|
||||
expect(subaddress.saveOptions).toHaveBeenCalledWith(SomeUser, {
|
||||
subaddressType: "random",
|
||||
subaddressEmail: "foo@example.com",
|
||||
website: null,
|
||||
});
|
||||
|
||||
expect(addyIo.saveOptions).toHaveBeenCalledWith(SomeUser, {
|
||||
token: "addyIoToken",
|
||||
domain: "addyio.example.com",
|
||||
baseUrl: "https://addyio.api.example.com",
|
||||
website: null,
|
||||
});
|
||||
|
||||
expect(duckDuckGo.saveOptions).toHaveBeenCalledWith(SomeUser, {
|
||||
token: "ddgToken",
|
||||
website: null,
|
||||
});
|
||||
|
||||
expect(fastmail.saveOptions).toHaveBeenCalledWith(SomeUser, {
|
||||
token: "fastmailToken",
|
||||
website: null,
|
||||
});
|
||||
|
||||
expect(firefoxRelay.saveOptions).toHaveBeenCalledWith(SomeUser, {
|
||||
token: "firefoxToken",
|
||||
website: null,
|
||||
});
|
||||
|
||||
expect(forwardEmail.saveOptions).toHaveBeenCalledWith(SomeUser, {
|
||||
token: "forwardEmailToken",
|
||||
domain: "example.com",
|
||||
website: null,
|
||||
});
|
||||
|
||||
expect(simpleLogin.saveOptions).toHaveBeenCalledWith(SomeUser, {
|
||||
token: "simpleLoginToken",
|
||||
baseUrl: "https://simplelogin.api.example.com",
|
||||
website: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,286 @@
|
||||
import { zip, firstValueFrom, map, concatMap, combineLatest } from "rxjs";
|
||||
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import {
|
||||
ApiOptions,
|
||||
EmailDomainOptions,
|
||||
EmailPrefixOptions,
|
||||
RequestOptions,
|
||||
SelfHostedApiOptions,
|
||||
NoPolicy,
|
||||
GeneratorService,
|
||||
CatchallGenerationOptions,
|
||||
EffUsernameGenerationOptions,
|
||||
Forwarders,
|
||||
SubaddressGenerationOptions,
|
||||
} from "@bitwarden/generator-core";
|
||||
|
||||
import { GeneratorNavigationService, GeneratorNavigation } from "../navigation";
|
||||
|
||||
import { UsernameGeneratorOptions } from "./username-generation-options";
|
||||
import { UsernameGenerationServiceAbstraction } from "./username-generation.service.abstraction";
|
||||
|
||||
type MappedOptions = {
|
||||
generator: GeneratorNavigation;
|
||||
algorithms: {
|
||||
catchall: CatchallGenerationOptions;
|
||||
effUsername: EffUsernameGenerationOptions;
|
||||
subaddress: SubaddressGenerationOptions;
|
||||
};
|
||||
forwarders: {
|
||||
addyIo: SelfHostedApiOptions & EmailDomainOptions & RequestOptions;
|
||||
duckDuckGo: ApiOptions & RequestOptions;
|
||||
fastmail: ApiOptions & EmailPrefixOptions & RequestOptions;
|
||||
firefoxRelay: ApiOptions & RequestOptions;
|
||||
forwardEmail: ApiOptions & EmailDomainOptions & RequestOptions;
|
||||
simpleLogin: SelfHostedApiOptions & RequestOptions;
|
||||
};
|
||||
};
|
||||
|
||||
/** Adapts the generator 2.0 design to 1.0 angular services. */
|
||||
export class LegacyUsernameGenerationService implements UsernameGenerationServiceAbstraction {
|
||||
constructor(
|
||||
private readonly accountService: AccountService,
|
||||
private readonly navigation: GeneratorNavigationService,
|
||||
private readonly catchall: GeneratorService<CatchallGenerationOptions, NoPolicy>,
|
||||
private readonly effUsername: GeneratorService<EffUsernameGenerationOptions, NoPolicy>,
|
||||
private readonly subaddress: GeneratorService<SubaddressGenerationOptions, NoPolicy>,
|
||||
private readonly addyIo: GeneratorService<SelfHostedApiOptions & EmailDomainOptions, NoPolicy>,
|
||||
private readonly duckDuckGo: GeneratorService<ApiOptions, NoPolicy>,
|
||||
private readonly fastmail: GeneratorService<ApiOptions & EmailPrefixOptions, NoPolicy>,
|
||||
private readonly firefoxRelay: GeneratorService<ApiOptions, NoPolicy>,
|
||||
private readonly forwardEmail: GeneratorService<ApiOptions & EmailDomainOptions, NoPolicy>,
|
||||
private readonly simpleLogin: GeneratorService<SelfHostedApiOptions, NoPolicy>,
|
||||
) {}
|
||||
|
||||
generateUsername(options: UsernameGeneratorOptions) {
|
||||
if (options.type === "catchall") {
|
||||
return this.generateCatchall(options);
|
||||
} else if (options.type === "subaddress") {
|
||||
return this.generateSubaddress(options);
|
||||
} else if (options.type === "forwarded") {
|
||||
return this.generateForwarded(options);
|
||||
} else {
|
||||
return this.generateWord(options);
|
||||
}
|
||||
}
|
||||
|
||||
generateWord(options: UsernameGeneratorOptions) {
|
||||
return this.effUsername.generate(options);
|
||||
}
|
||||
|
||||
generateSubaddress(options: UsernameGeneratorOptions) {
|
||||
return this.subaddress.generate(options);
|
||||
}
|
||||
|
||||
generateCatchall(options: UsernameGeneratorOptions) {
|
||||
return this.catchall.generate(options);
|
||||
}
|
||||
|
||||
generateForwarded(options: UsernameGeneratorOptions) {
|
||||
if (!options.forwardedService) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const stored = this.toStoredOptions(options);
|
||||
switch (options.forwardedService) {
|
||||
case Forwarders.AddyIo.id:
|
||||
return this.addyIo.generate(stored.forwarders.addyIo);
|
||||
case Forwarders.DuckDuckGo.id:
|
||||
return this.duckDuckGo.generate(stored.forwarders.duckDuckGo);
|
||||
case Forwarders.Fastmail.id:
|
||||
return this.fastmail.generate(stored.forwarders.fastmail);
|
||||
case Forwarders.FirefoxRelay.id:
|
||||
return this.firefoxRelay.generate(stored.forwarders.firefoxRelay);
|
||||
case Forwarders.ForwardEmail.id:
|
||||
return this.forwardEmail.generate(stored.forwarders.forwardEmail);
|
||||
case Forwarders.SimpleLogin.id:
|
||||
return this.simpleLogin.generate(stored.forwarders.simpleLogin);
|
||||
}
|
||||
}
|
||||
|
||||
getOptions$() {
|
||||
// look upon my works, ye mighty, and despair!
|
||||
const options$ = this.accountService.activeAccount$.pipe(
|
||||
concatMap((account) =>
|
||||
combineLatest([
|
||||
this.navigation.options$(account.id),
|
||||
this.navigation.defaults$(account.id),
|
||||
this.catchall.options$(account.id),
|
||||
this.catchall.defaults$(account.id),
|
||||
this.effUsername.options$(account.id),
|
||||
this.effUsername.defaults$(account.id),
|
||||
this.subaddress.options$(account.id),
|
||||
this.subaddress.defaults$(account.id),
|
||||
this.addyIo.options$(account.id),
|
||||
this.addyIo.defaults$(account.id),
|
||||
this.duckDuckGo.options$(account.id),
|
||||
this.duckDuckGo.defaults$(account.id),
|
||||
this.fastmail.options$(account.id),
|
||||
this.fastmail.defaults$(account.id),
|
||||
this.firefoxRelay.options$(account.id),
|
||||
this.firefoxRelay.defaults$(account.id),
|
||||
this.forwardEmail.options$(account.id),
|
||||
this.forwardEmail.defaults$(account.id),
|
||||
this.simpleLogin.options$(account.id),
|
||||
this.simpleLogin.defaults$(account.id),
|
||||
]),
|
||||
),
|
||||
map(
|
||||
([
|
||||
generatorOptions,
|
||||
generatorDefaults,
|
||||
catchallOptions,
|
||||
catchallDefaults,
|
||||
effUsernameOptions,
|
||||
effUsernameDefaults,
|
||||
subaddressOptions,
|
||||
subaddressDefaults,
|
||||
addyIoOptions,
|
||||
addyIoDefaults,
|
||||
duckDuckGoOptions,
|
||||
duckDuckGoDefaults,
|
||||
fastmailOptions,
|
||||
fastmailDefaults,
|
||||
firefoxRelayOptions,
|
||||
firefoxRelayDefaults,
|
||||
forwardEmailOptions,
|
||||
forwardEmailDefaults,
|
||||
simpleLoginOptions,
|
||||
simpleLoginDefaults,
|
||||
]) =>
|
||||
this.toUsernameOptions({
|
||||
generator: generatorOptions ?? generatorDefaults,
|
||||
algorithms: {
|
||||
catchall: catchallOptions ?? catchallDefaults,
|
||||
effUsername: effUsernameOptions ?? effUsernameDefaults,
|
||||
subaddress: subaddressOptions ?? subaddressDefaults,
|
||||
},
|
||||
forwarders: {
|
||||
addyIo: addyIoOptions ?? addyIoDefaults,
|
||||
duckDuckGo: duckDuckGoOptions ?? duckDuckGoDefaults,
|
||||
fastmail: fastmailOptions ?? fastmailDefaults,
|
||||
firefoxRelay: firefoxRelayOptions ?? firefoxRelayDefaults,
|
||||
forwardEmail: forwardEmailOptions ?? forwardEmailDefaults,
|
||||
simpleLogin: simpleLoginOptions ?? simpleLoginDefaults,
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return options$;
|
||||
}
|
||||
|
||||
getOptions() {
|
||||
return firstValueFrom(this.getOptions$());
|
||||
}
|
||||
|
||||
async saveOptions(options: UsernameGeneratorOptions) {
|
||||
const stored = this.toStoredOptions(options);
|
||||
const activeAccount = await firstValueFrom(this.accountService.activeAccount$);
|
||||
|
||||
// generator settings needs to preserve whether password or passphrase is selected,
|
||||
// so `navigationOptions` is mutated.
|
||||
const navigationOptions$ = zip(
|
||||
this.navigation.options$(activeAccount.id),
|
||||
this.navigation.defaults$(activeAccount.id),
|
||||
).pipe(map(([options, defaults]) => options ?? defaults));
|
||||
let navigationOptions = await firstValueFrom(navigationOptions$);
|
||||
navigationOptions = Object.assign(navigationOptions, stored.generator);
|
||||
await this.navigation.saveOptions(activeAccount.id, navigationOptions);
|
||||
|
||||
// overwrite all other settings with latest values
|
||||
await Promise.all([
|
||||
this.catchall.saveOptions(activeAccount.id, stored.algorithms.catchall),
|
||||
this.effUsername.saveOptions(activeAccount.id, stored.algorithms.effUsername),
|
||||
this.subaddress.saveOptions(activeAccount.id, stored.algorithms.subaddress),
|
||||
this.addyIo.saveOptions(activeAccount.id, stored.forwarders.addyIo),
|
||||
this.duckDuckGo.saveOptions(activeAccount.id, stored.forwarders.duckDuckGo),
|
||||
this.fastmail.saveOptions(activeAccount.id, stored.forwarders.fastmail),
|
||||
this.firefoxRelay.saveOptions(activeAccount.id, stored.forwarders.firefoxRelay),
|
||||
this.forwardEmail.saveOptions(activeAccount.id, stored.forwarders.forwardEmail),
|
||||
this.simpleLogin.saveOptions(activeAccount.id, stored.forwarders.simpleLogin),
|
||||
]);
|
||||
}
|
||||
|
||||
private toStoredOptions(options: UsernameGeneratorOptions) {
|
||||
const forwarders = {
|
||||
addyIo: {
|
||||
baseUrl: options.forwardedAnonAddyBaseUrl,
|
||||
token: options.forwardedAnonAddyApiToken,
|
||||
domain: options.forwardedAnonAddyDomain,
|
||||
website: options.website,
|
||||
},
|
||||
duckDuckGo: {
|
||||
token: options.forwardedDuckDuckGoToken,
|
||||
website: options.website,
|
||||
},
|
||||
fastmail: {
|
||||
token: options.forwardedFastmailApiToken,
|
||||
website: options.website,
|
||||
},
|
||||
firefoxRelay: {
|
||||
token: options.forwardedFirefoxApiToken,
|
||||
website: options.website,
|
||||
},
|
||||
forwardEmail: {
|
||||
token: options.forwardedForwardEmailApiToken,
|
||||
domain: options.forwardedForwardEmailDomain,
|
||||
website: options.website,
|
||||
},
|
||||
simpleLogin: {
|
||||
token: options.forwardedSimpleLoginApiKey,
|
||||
baseUrl: options.forwardedSimpleLoginBaseUrl,
|
||||
website: options.website,
|
||||
},
|
||||
};
|
||||
|
||||
const generator = {
|
||||
username: options.type,
|
||||
forwarder: options.forwardedService,
|
||||
};
|
||||
|
||||
const algorithms = {
|
||||
effUsername: {
|
||||
wordCapitalize: options.wordCapitalize,
|
||||
wordIncludeNumber: options.wordIncludeNumber,
|
||||
website: options.website,
|
||||
},
|
||||
subaddress: {
|
||||
subaddressType: options.subaddressType,
|
||||
subaddressEmail: options.subaddressEmail,
|
||||
website: options.website,
|
||||
},
|
||||
catchall: {
|
||||
catchallType: options.catchallType,
|
||||
catchallDomain: options.catchallDomain,
|
||||
website: options.website,
|
||||
},
|
||||
};
|
||||
|
||||
return { generator, algorithms, forwarders } as MappedOptions;
|
||||
}
|
||||
|
||||
private toUsernameOptions(options: MappedOptions) {
|
||||
return {
|
||||
type: options.generator.username,
|
||||
wordCapitalize: options.algorithms.effUsername.wordCapitalize,
|
||||
wordIncludeNumber: options.algorithms.effUsername.wordIncludeNumber,
|
||||
subaddressType: options.algorithms.subaddress.subaddressType,
|
||||
subaddressEmail: options.algorithms.subaddress.subaddressEmail,
|
||||
catchallType: options.algorithms.catchall.catchallType,
|
||||
catchallDomain: options.algorithms.catchall.catchallDomain,
|
||||
forwardedService: options.generator.forwarder,
|
||||
forwardedAnonAddyApiToken: options.forwarders.addyIo.token,
|
||||
forwardedAnonAddyDomain: options.forwarders.addyIo.domain,
|
||||
forwardedAnonAddyBaseUrl: options.forwarders.addyIo.baseUrl,
|
||||
forwardedDuckDuckGoToken: options.forwarders.duckDuckGo.token,
|
||||
forwardedFirefoxApiToken: options.forwarders.firefoxRelay.token,
|
||||
forwardedFastmailApiToken: options.forwarders.fastmail.token,
|
||||
forwardedForwardEmailApiToken: options.forwarders.forwardEmail.token,
|
||||
forwardedForwardEmailDomain: options.forwarders.forwardEmail.domain,
|
||||
forwardedSimpleLoginApiKey: options.forwarders.simpleLogin.token,
|
||||
forwardedSimpleLoginBaseUrl: options.forwarders.simpleLogin.baseUrl,
|
||||
} as UsernameGeneratorOptions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import {
|
||||
ForwarderId,
|
||||
RequestOptions,
|
||||
CatchallGenerationOptions,
|
||||
EffUsernameGenerationOptions,
|
||||
SubaddressGenerationOptions,
|
||||
UsernameGeneratorType,
|
||||
} from "@bitwarden/generator-core";
|
||||
|
||||
export type UsernameGeneratorOptions = EffUsernameGenerationOptions &
|
||||
SubaddressGenerationOptions &
|
||||
CatchallGenerationOptions &
|
||||
RequestOptions & {
|
||||
type?: UsernameGeneratorType;
|
||||
forwardedService?: ForwarderId | "";
|
||||
forwardedAnonAddyApiToken?: string;
|
||||
forwardedAnonAddyDomain?: string;
|
||||
forwardedAnonAddyBaseUrl?: string;
|
||||
forwardedDuckDuckGoToken?: string;
|
||||
forwardedFirefoxApiToken?: string;
|
||||
forwardedFastmailApiToken?: string;
|
||||
forwardedForwardEmailApiToken?: string;
|
||||
forwardedForwardEmailDomain?: string;
|
||||
forwardedSimpleLoginApiKey?: string;
|
||||
forwardedSimpleLoginBaseUrl?: string;
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
import { UsernameGeneratorOptions } from "./username-generation-options";
|
||||
|
||||
/** @deprecated Use {@link GeneratorService} with a username {@link GeneratorStrategy} instead. */
|
||||
export abstract class UsernameGenerationServiceAbstraction {
|
||||
generateUsername: (options: UsernameGeneratorOptions) => Promise<string>;
|
||||
generateWord: (options: UsernameGeneratorOptions) => Promise<string>;
|
||||
generateSubaddress: (options: UsernameGeneratorOptions) => Promise<string>;
|
||||
generateCatchall: (options: UsernameGeneratorOptions) => Promise<string>;
|
||||
generateForwarded: (options: UsernameGeneratorOptions) => Promise<string>;
|
||||
getOptions: () => Promise<UsernameGeneratorOptions>;
|
||||
getOptions$: () => Observable<UsernameGeneratorOptions>;
|
||||
saveOptions: (options: UsernameGeneratorOptions) => Promise<void>;
|
||||
}
|
||||
Reference in New Issue
Block a user