1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-01-10 19:38:11 +01:00

[PS-1878] Feature/selfhost anonaddy (#4056)

* Add selfhosted anonaddy url

* Remove newlines

* Add serverurl field to web

* Show anonaddy api errors

* Add forwardedAnonAddyBaseUrl prop to UsernameGeneratorOptions type

* Use Alias Domain instead of just Domain name

This is easier to distinguish between domain and server url

* Only show Server Url on web if on selfhosted bitwarden

---------

Co-authored-by: Daniel James Smith <djsmith@web.de>
Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
This commit is contained in:
David Claybourne 2023-09-26 15:34:34 +02:00 committed by GitHub
parent 5616e69e10
commit abd3e66e20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 66 additions and 8 deletions

View File

@ -2407,6 +2407,9 @@
"message": "Toggle collapse", "message": "Toggle collapse",
"description": "Toggling an expand/collapse state." "description": "Toggling an expand/collapse state."
}, },
"aliasDomain": {
"message": "Alias domain"
},
"passwordRepromptDisabledAutofillOnPageLoad": { "passwordRepromptDisabledAutofillOnPageLoad": {
"message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.", "message": "Items with master password re-prompt cannot be auto-filled on page load. Auto-fill on page load turned off.",
"description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load." "description": "Toast message for describing that master password re-prompt cannot be auto-filled on page load."

View File

@ -378,7 +378,7 @@
/> />
</div> </div>
<div class="box-content-row" appBoxRow> <div class="box-content-row" appBoxRow>
<label for="anonaddy-domain">{{ "domainName" | i18n }}</label> <label for="anonaddy-domain">{{ "aliasDomain" | i18n }}</label>
<input <input
id="anonaddy-domain" id="anonaddy-domain"
type="text" type="text"
@ -387,6 +387,16 @@
(blur)="saveUsernameOptions()" (blur)="saveUsernameOptions()"
/> />
</div> </div>
<div class="box-content-row" appBoxRow>
<label for="anonaddy-baseUrl">{{ "baseUrl" | i18n }}</label>
<input
id="anonaddy-baseUrl"
type="text"
name="AnonAddyDomain"
[(ngModel)]="usernameOptions.forwardedAnonAddyBaseUrl"
(blur)="saveUsernameOptions()"
/>
</div>
</ng-container> </ng-container>
<ng-container *ngIf="usernameOptions.forwardedService === 'firefoxrelay'"> <ng-container *ngIf="usernameOptions.forwardedService === 'firefoxrelay'">
<div class="box-content-row" appBoxRow> <div class="box-content-row" appBoxRow>
@ -424,7 +434,7 @@
/> />
</div> </div>
<div class="box-content-row" appBoxRow> <div class="box-content-row" appBoxRow>
<label for="forwardemail-domain">{{ "domainName" | i18n }}</label> <label for="forwardemail-domain">{{ "aliasDomain" | i18n }}</label>
<input <input
id="forwardemail-domain" id="forwardemail-domain"
type="text" type="text"

View File

@ -405,7 +405,7 @@
/> />
</div> </div>
<div class="box-content-row" appBoxRow> <div class="box-content-row" appBoxRow>
<label for="anonaddy-domain">{{ "domainName" | i18n }}</label> <label for="anonaddy-domain">{{ "aliasDomain" | i18n }}</label>
<input <input
id="anonaddy-domain" id="anonaddy-domain"
type="text" type="text"
@ -414,6 +414,16 @@
(blur)="saveUsernameOptions()" (blur)="saveUsernameOptions()"
/> />
</div> </div>
<div class="box-content-row" appBoxRow>
<label for="anonaddy-baseUrl">{{ "baseUrl" | i18n }}</label>
<input
id="anonaddy-baseUrl"
type="text"
name="AnonAddyDomain"
[(ngModel)]="usernameOptions.forwardedAnonAddyBaseUrl"
(blur)="saveUsernameOptions()"
/>
</div>
</ng-container> </ng-container>
<ng-container *ngIf="usernameOptions.forwardedService === 'firefoxrelay'"> <ng-container *ngIf="usernameOptions.forwardedService === 'firefoxrelay'">
<div class="box-content-row" appBoxRow> <div class="box-content-row" appBoxRow>
@ -451,7 +461,7 @@
/> />
</div> </div>
<div class="box-content-row" appBoxRow> <div class="box-content-row" appBoxRow>
<label for="forwardemail-domain">{{ "domainName" | i18n }}</label> <label for="forwardemail-domain">{{ "aliasDomain" | i18n }}</label>
<input <input
id="forwardemail-domain" id="forwardemail-domain"
type="text" type="text"

View File

@ -2415,5 +2415,8 @@
}, },
"submenu": { "submenu": {
"message": "Submenu" "message": "Submenu"
},
"aliasDomain": {
"message": "Alias domain"
} }
} }

View File

@ -309,7 +309,7 @@
/> />
</div> </div>
<div class="form-group col-4"> <div class="form-group col-4">
<label for="anonaddy-domain">{{ "domainName" | i18n }}</label> <label for="anonaddy-domain">{{ "aliasDomain" | i18n }}</label>
<input <input
id="anonaddy-domain" id="anonaddy-domain"
class="form-control" class="form-control"
@ -318,6 +318,17 @@
(blur)="saveUsernameOptions()" (blur)="saveUsernameOptions()"
/> />
</div> </div>
<div class="form-group col-4" *ngIf="isSelfHosted">
<label for="anonaddy-baseUrl">{{ "baseUrl" | i18n }}</label>
<input
id="anonaddy-baseUrl"
class="form-control"
type="text"
name="AnonAddyDomain"
[(ngModel)]="usernameOptions.forwardedAnonAddyBaseUrl"
(blur)="saveUsernameOptions()"
/>
</div>
</div> </div>
<div class="row" *ngIf="usernameOptions.forwardedService === 'firefoxrelay'"> <div class="row" *ngIf="usernameOptions.forwardedService === 'firefoxrelay'">
<div class="form-group col-4"> <div class="form-group col-4">
@ -355,7 +366,7 @@
/> />
</div> </div>
<div class="form-group col-4"> <div class="form-group col-4">
<label for="forwardemail-domain">{{ "domainName" | i18n }}</label> <label for="forwardemail-domain">{{ "aliasDomain" | i18n }}</label>
<input <input
id="forwardemail-domain" id="forwardemail-domain"
class="form-control" class="form-control"

View File

@ -43,6 +43,10 @@ export class GeneratorComponent extends BaseGeneratorComponent {
} }
} }
get isSelfHosted(): boolean {
return this.platformUtilsService.isSelfHost();
}
async history() { async history() {
this.dialogService.open(PasswordGeneratorHistoryComponent); this.dialogService.open(PasswordGeneratorHistoryComponent);
} }

View File

@ -7169,6 +7169,12 @@
"beta": { "beta": {
"message": "Beta" "message": "Beta"
}, },
"baseUrl": {
"message": "Server URL"
},
"aliasDomain": {
"message": "Alias domain"
},
"alreadyHaveAccount": { "alreadyHaveAccount": {
"message": "Already have an account?" "message": "Already have an account?"
} }

View File

@ -280,7 +280,7 @@ const devServer =
http://127.0.0.1:10000 http://127.0.0.1:10000
https://app.simplelogin.io/api/alias/random/new https://app.simplelogin.io/api/alias/random/new
https://quack.duckduckgo.com/api/email/addresses https://quack.duckduckgo.com/api/email/addresses
https://app.anonaddy.com/api/v1/aliases https://app.addy.io/api/v1/aliases
https://api.fastmail.com https://api.fastmail.com
https://api.forwardemail.net https://api.forwardemail.net
http://localhost:5000 http://localhost:5000

View File

@ -11,6 +11,10 @@ export class AnonAddyForwarder implements Forwarder {
if (options.anonaddy?.domain == null || options.anonaddy.domain === "") { if (options.anonaddy?.domain == null || options.anonaddy.domain === "") {
throw "Invalid addy.io domain."; throw "Invalid addy.io domain.";
} }
if (options.anonaddy?.baseUrl == null || options.anonaddy.baseUrl === "") {
throw "Invalid addy.io url.";
}
const requestInit: RequestInit = { const requestInit: RequestInit = {
redirect: "manual", redirect: "manual",
cache: "no-store", cache: "no-store",
@ -21,7 +25,7 @@ export class AnonAddyForwarder implements Forwarder {
"X-Requested-With": "XMLHttpRequest", "X-Requested-With": "XMLHttpRequest",
}), }),
}; };
const url = "https://app.addy.io/api/v1/aliases"; const url = options.anonaddy.baseUrl + "/api/v1/aliases";
requestInit.body = JSON.stringify({ requestInit.body = JSON.stringify({
domain: options.anonaddy.domain, domain: options.anonaddy.domain,
description: description:
@ -37,6 +41,9 @@ export class AnonAddyForwarder implements Forwarder {
if (response.status === 401) { if (response.status === 401) {
throw "Invalid addy.io API token."; throw "Invalid addy.io API token.";
} }
if (response?.statusText != null) {
throw "addy.io error:\n" + response.statusText;
}
throw "Unknown addy.io error occurred."; throw "Unknown addy.io error occurred.";
} }
} }

View File

@ -12,6 +12,7 @@ export class FastmailForwarderOptions {
export class AnonAddyForwarderOptions { export class AnonAddyForwarderOptions {
domain: string; domain: string;
baseUrl: string;
} }
export class ForwardEmailForwarderOptions { export class ForwardEmailForwarderOptions {

View File

@ -10,6 +10,7 @@ export type UsernameGeneratorOptions = {
forwardedService?: string; forwardedService?: string;
forwardedAnonAddyApiToken?: string; forwardedAnonAddyApiToken?: string;
forwardedAnonAddyDomain?: string; forwardedAnonAddyDomain?: string;
forwardedAnonAddyBaseUrl?: string;
forwardedDuckDuckGoToken?: string; forwardedDuckDuckGoToken?: string;
forwardedFirefoxApiToken?: string; forwardedFirefoxApiToken?: string;
forwardedFastmailApiToken?: string; forwardedFastmailApiToken?: string;

View File

@ -24,6 +24,7 @@ const DefaultOptions: UsernameGeneratorOptions = {
catchallType: "random", catchallType: "random",
forwardedService: "", forwardedService: "",
forwardedAnonAddyDomain: "anonaddy.me", forwardedAnonAddyDomain: "anonaddy.me",
forwardedAnonAddyBaseUrl: "https://app.addy.io",
forwardedForwardEmailDomain: "hideaddress.net", forwardedForwardEmailDomain: "hideaddress.net",
}; };
@ -131,6 +132,7 @@ export class UsernameGenerationService implements UsernameGenerationServiceAbstr
forwarder = new AnonAddyForwarder(); forwarder = new AnonAddyForwarder();
forwarderOptions.apiKey = o.forwardedAnonAddyApiToken; forwarderOptions.apiKey = o.forwardedAnonAddyApiToken;
forwarderOptions.anonaddy.domain = o.forwardedAnonAddyDomain; forwarderOptions.anonaddy.domain = o.forwardedAnonAddyDomain;
forwarderOptions.anonaddy.baseUrl = o.forwardedAnonAddyBaseUrl;
} else if (o.forwardedService === "firefoxrelay") { } else if (o.forwardedService === "firefoxrelay") {
forwarder = new FirefoxRelayForwarder(); forwarder = new FirefoxRelayForwarder();
forwarderOptions.apiKey = o.forwardedFirefoxApiToken; forwarderOptions.apiKey = o.forwardedFirefoxApiToken;