1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-18 01:03:35 +00:00

[SG-515] add fastmail integration for generator (#3318)

* add fastmail integration for generator

* prettier

* introduce forwarder interface and implementations
This commit is contained in:
Kyle Spearrin
2022-08-19 14:52:14 -04:00
committed by GitHub
parent d8cb543645
commit 2a49824581
15 changed files with 356 additions and 160 deletions

View File

@@ -2,6 +2,13 @@ import { ApiService } from "../abstractions/api.service";
import { CryptoService } from "../abstractions/crypto.service";
import { StateService } from "../abstractions/state.service";
import { UsernameGenerationService as BaseUsernameGenerationService } from "../abstractions/usernameGeneration.service";
import { AnonAddyForwarder } from "../emailForwarders/anonAddyForwarder";
import { DuckDuckGoForwarder } from "../emailForwarders/duckDuckGoForwarder";
import { FastmailForwarder } from "../emailForwarders/fastmailForwarder";
import { FirefoxRelayForwarder } from "../emailForwarders/firefoxRelayForwarder";
import { Forwarder } from "../emailForwarders/forwarder";
import { ForwarderOptions } from "../emailForwarders/forwarderOptions";
import { SimpleLoginForwarder } from "../emailForwarders/simpleLoginForwarder";
import { EEFLongWordList } from "../misc/wordlist";
const DefaultOptions = {
@@ -108,38 +115,33 @@ export class UsernameGenerationService implements BaseUsernameGenerationService
return null;
}
let forwarder: Forwarder = null;
const forwarderOptions = new ForwarderOptions();
forwarderOptions.website = o.website;
if (o.forwardedService === "simplelogin") {
if (o.forwardedSimpleLoginApiKey == null || o.forwardedSimpleLoginApiKey === "") {
return null;
}
return this.generateSimpleLoginAlias(o.forwardedSimpleLoginApiKey, o.website);
forwarder = new SimpleLoginForwarder();
forwarderOptions.apiKey = o.forwardedSimpleLoginApiKey;
} else if (o.forwardedService === "anonaddy") {
if (
o.forwardedAnonAddyApiToken == null ||
o.forwardedAnonAddyApiToken === "" ||
o.forwardedAnonAddyDomain == null ||
o.forwardedAnonAddyDomain == ""
) {
return null;
}
return this.generateAnonAddyAlias(
o.forwardedAnonAddyApiToken,
o.forwardedAnonAddyDomain,
o.website
);
forwarder = new AnonAddyForwarder();
forwarderOptions.apiKey = o.forwardedAnonAddyApiToken;
forwarderOptions.anonaddy.domain = o.forwardedAnonAddyDomain;
} else if (o.forwardedService === "firefoxrelay") {
if (o.forwardedFirefoxApiToken == null || o.forwardedFirefoxApiToken === "") {
return null;
}
return this.generateFirefoxRelayAlias(o.forwardedFirefoxApiToken, o.website);
forwarder = new FirefoxRelayForwarder();
forwarderOptions.apiKey = o.forwardedFirefoxApiToken;
} else if (o.forwardedService === "fastmail") {
forwarder = new FastmailForwarder();
forwarderOptions.apiKey = o.forwardedFastmailApiToken;
forwarderOptions.fastmail.accountId = o.forwardedFastmailAccountId;
} else if (o.forwardedService === "duckduckgo") {
if (o.forwardedDuckDuckGoToken == null || o.forwardedDuckDuckGoToken === "") {
return null;
}
return this.generateDuckDuckGoAlias(o.forwardedDuckDuckGoToken);
forwarder = new DuckDuckGoForwarder();
forwarderOptions.apiKey = o.forwardedDuckDuckGoToken;
}
return null;
if (forwarder == null) {
return null;
}
return forwarder.generate(this.apiService, forwarderOptions);
}
async getOptions(): Promise<any> {
@@ -173,137 +175,4 @@ export class UsernameGenerationService implements BaseUsernameGenerationService
? number
: new Array(width - number.length + 1).join("0") + number;
}
private async generateSimpleLoginAlias(apiKey: string, website: string): Promise<string> {
if (apiKey == null || apiKey === "") {
throw "Invalid SimpleLogin API key.";
}
const requestInit: RequestInit = {
redirect: "manual",
cache: "no-store",
method: "POST",
headers: new Headers({
Authentication: apiKey,
"Content-Type": "application/json",
}),
};
let url = "https://app.simplelogin.io/api/alias/random/new";
if (website != null) {
url += "?hostname=" + website;
}
requestInit.body = JSON.stringify({
note: (website != null ? "Website: " + website + ". " : "") + "Generated by Bitwarden.",
});
const request = new Request(url, requestInit);
const response = await this.apiService.nativeFetch(request);
if (response.status === 200 || response.status === 201) {
const json = await response.json();
return json.alias;
}
if (response.status === 401) {
throw "Invalid SimpleLogin API key.";
}
try {
const json = await response.json();
if (json?.error != null) {
throw "SimpleLogin error:" + json.error;
}
} catch {
// Do nothing...
}
throw "Unknown SimpleLogin error occurred.";
}
private async generateAnonAddyAlias(
apiToken: string,
domain: string,
websiteNote: string
): Promise<string> {
if (apiToken == null || apiToken === "") {
throw "Invalid AnonAddy API token.";
}
const requestInit: RequestInit = {
redirect: "manual",
cache: "no-store",
method: "POST",
headers: new Headers({
Authorization: "Bearer " + apiToken,
"Content-Type": "application/json",
}),
};
const url = "https://app.anonaddy.com/api/v1/aliases";
requestInit.body = JSON.stringify({
domain: domain,
description:
(websiteNote != null ? "Website: " + websiteNote + ". " : "") + "Generated by Bitwarden.",
});
const request = new Request(url, requestInit);
const response = await this.apiService.nativeFetch(request);
if (response.status === 200 || response.status === 201) {
const json = await response.json();
return json?.data?.email;
}
if (response.status === 401) {
throw "Invalid AnonAddy API token.";
}
throw "Unknown AnonAddy error occurred.";
}
private async generateFirefoxRelayAlias(apiToken: string, website: string): Promise<string> {
if (apiToken == null || apiToken === "") {
throw "Invalid Firefox Relay API token.";
}
const requestInit: RequestInit = {
redirect: "manual",
cache: "no-store",
method: "POST",
headers: new Headers({
Authorization: "Token " + apiToken,
"Content-Type": "application/json",
}),
};
const url = "https://relay.firefox.com/api/v1/relayaddresses/";
requestInit.body = JSON.stringify({
enabled: true,
generated_for: website,
description: (website != null ? website + " - " : "") + "Generated by Bitwarden.",
});
const request = new Request(url, requestInit);
const response = await this.apiService.nativeFetch(request);
if (response.status === 200 || response.status === 201) {
const json = await response.json();
return json?.full_address;
}
if (response.status === 401) {
throw "Invalid Firefox Relay API token.";
}
throw "Unknown Firefox Relay error occurred.";
}
private async generateDuckDuckGoAlias(apiToken: string): Promise<string> {
if (apiToken == null || apiToken === "") {
throw "Invalid DuckDuckGo API token.";
}
const requestInit: RequestInit = {
redirect: "manual",
cache: "no-store",
method: "POST",
headers: new Headers({
Authorization: "Bearer " + apiToken,
"Content-Type": "application/json",
}),
};
const url = "https://quack.duckduckgo.com/api/email/addresses";
const request = new Request(url, requestInit);
const response = await this.apiService.nativeFetch(request);
if (response.status === 200 || response.status === 201) {
const json = await response.json();
if (json.address) {
return `${json.address}@duck.com`;
}
} else if (response.status === 401) {
throw "Invalid DuckDuckGo API token.";
}
throw "Unknown DuckDuckGo error occurred.";
}
}