mirror of
https://github.com/bitwarden/browser.git
synced 2024-10-22 07:50:04 +02:00
add forwarder settings to credential generator
This commit is contained in:
parent
d5a19bab75
commit
1a5dae51d3
@ -37,8 +37,8 @@ import { Constraints, SubjectConstraints, WithConstraints } from "../types";
|
|||||||
|
|
||||||
import { ClassifiedFormat, isClassifiedFormat } from "./classified-format";
|
import { ClassifiedFormat, isClassifiedFormat } from "./classified-format";
|
||||||
import { unconstrained$ } from "./identity-state-constraint";
|
import { unconstrained$ } from "./identity-state-constraint";
|
||||||
|
import { isObjectKey, ObjectKey, toUserKeyDefinition } from "./object-key";
|
||||||
import { isDynamic } from "./state-constraints-dependency";
|
import { isDynamic } from "./state-constraints-dependency";
|
||||||
import { isObjectKey, ObjectKey, toUserKeyDefinition } from "./subject-key";
|
|
||||||
import { UserEncryptor } from "./user-encryptor.abstraction";
|
import { UserEncryptor } from "./user-encryptor.abstraction";
|
||||||
import { UserStateSubjectDependencies } from "./user-state-subject-dependencies";
|
import { UserStateSubjectDependencies } from "./user-state-subject-dependencies";
|
||||||
|
|
||||||
|
@ -68,6 +68,11 @@
|
|||||||
[userId]="userId$ | async"
|
[userId]="userId$ | async"
|
||||||
(onUpdated)="generate$.next()"
|
(onUpdated)="generate$.next()"
|
||||||
/>
|
/>
|
||||||
|
<tools-forwarder-settings
|
||||||
|
*ngIf="!!(forwarderId$ | async)"
|
||||||
|
[forwarder]="forwarderId$ | async"
|
||||||
|
[userId]="this.userId$ | async"
|
||||||
|
/>
|
||||||
<tools-subaddress-settings
|
<tools-subaddress-settings
|
||||||
*ngIf="(algorithm$ | async)?.id === 'subaddress'"
|
*ngIf="(algorithm$ | async)?.id === 'subaddress'"
|
||||||
[userId]="userId$ | async"
|
[userId]="userId$ | async"
|
||||||
|
@ -16,6 +16,7 @@ import {
|
|||||||
|
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
|
import { IntegrationId } from "@bitwarden/common/tools/integration";
|
||||||
import { UserId } from "@bitwarden/common/types/guid";
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
import { Option } from "@bitwarden/components/src/select/option";
|
import { Option } from "@bitwarden/components/src/select/option";
|
||||||
import {
|
import {
|
||||||
@ -260,6 +261,11 @@ export class CredentialGeneratorComponent implements OnInit, OnDestroy {
|
|||||||
// template bindings refresh immediately
|
// template bindings refresh immediately
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
this.algorithm$.next(algorithm);
|
this.algorithm$.next(algorithm);
|
||||||
|
if (userNav === FORWARDER && forwarderNav !== NONE_SELECTED) {
|
||||||
|
this.forwarderId$.next(forwarderNav.forwarder);
|
||||||
|
} else {
|
||||||
|
this.forwarderId$.next(null);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -314,6 +320,9 @@ export class CredentialGeneratorComponent implements OnInit, OnDestroy {
|
|||||||
/** Lists the credential types of the username algorithm box. */
|
/** Lists the credential types of the username algorithm box. */
|
||||||
protected forwarderOptions$ = new BehaviorSubject<Option<ForwarderNavValue>[]>([]);
|
protected forwarderOptions$ = new BehaviorSubject<Option<ForwarderNavValue>[]>([]);
|
||||||
|
|
||||||
|
/** Tracks the currently selected forwarder. */
|
||||||
|
protected forwarderId$ = new BehaviorSubject<IntegrationId>(null);
|
||||||
|
|
||||||
/** tracks the currently selected credential type */
|
/** tracks the currently selected credential type */
|
||||||
protected algorithm$ = new ReplaySubject<AlgorithmInfo>(1);
|
protected algorithm$ = new ReplaySubject<AlgorithmInfo>(1);
|
||||||
|
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
<form class="box" [formGroup]="settings" class="tw-container">
|
||||||
|
<bit-form-field *ngIf="displayDomain">
|
||||||
|
<bit-label>{{ "aliasDomain" | i18n }}</bit-label>
|
||||||
|
<input bitInput formControlName="domain" type="text" />
|
||||||
|
</bit-form-field>
|
||||||
|
<bit-form-field *ngIf="displayToken">
|
||||||
|
<bit-label>{{ "apiAccessToken" | i18n }}</bit-label>
|
||||||
|
<input bitInput formControlName="token" type="password" />
|
||||||
|
<button type="button" bitIconButton bitSuffix bitPasswordInputToggle></button>
|
||||||
|
</bit-form-field>
|
||||||
|
<bit-form-field *ngIf="displayBaseUrl">
|
||||||
|
<bit-label>{{ "baseUrl" | i18n }}</bit-label>
|
||||||
|
<input bitInput formControlName="baseUrl" type="text" />
|
||||||
|
</bit-form-field>
|
||||||
|
</form>
|
@ -0,0 +1,132 @@
|
|||||||
|
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
|
||||||
|
import { FormBuilder } from "@angular/forms";
|
||||||
|
import { BehaviorSubject, skip, Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
|
import { IntegrationId } from "@bitwarden/common/tools/integration";
|
||||||
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
|
import {
|
||||||
|
CredentialGeneratorService,
|
||||||
|
getForwarderConfiguration,
|
||||||
|
toCredentialGeneratorConfiguration,
|
||||||
|
} from "@bitwarden/generator-core";
|
||||||
|
|
||||||
|
import { completeOnAccountSwitch, toValidators } from "./util";
|
||||||
|
|
||||||
|
const Controls = Object.freeze({
|
||||||
|
domain: "domain",
|
||||||
|
token: "token",
|
||||||
|
baseUrl: "baseUrl",
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Options group for forwarder integrations */
|
||||||
|
@Component({
|
||||||
|
selector: "tools-forwarder-settings",
|
||||||
|
templateUrl: "forwarder-settings.component.html",
|
||||||
|
})
|
||||||
|
export class ForwarderSettingsComponent implements OnInit, OnDestroy {
|
||||||
|
/** Instantiates the component
|
||||||
|
* @param accountService queries user availability
|
||||||
|
* @param generatorService settings and policy logic
|
||||||
|
* @param formBuilder reactive form controls
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private formBuilder: FormBuilder,
|
||||||
|
private generatorService: CredentialGeneratorService,
|
||||||
|
private accountService: AccountService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/** Binds the component to a specific user's settings.
|
||||||
|
* When this input is not provided, the form binds to the active
|
||||||
|
* user
|
||||||
|
*/
|
||||||
|
@Input()
|
||||||
|
userId: UserId | null;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
forwarder: IntegrationId;
|
||||||
|
|
||||||
|
/** Emits settings updates and completes if the settings become unavailable.
|
||||||
|
* @remarks this does not emit the initial settings. If you would like
|
||||||
|
* to receive live settings updates including the initial update,
|
||||||
|
* use `CredentialGeneratorService.settings$(...)` instead.
|
||||||
|
*/
|
||||||
|
@Output()
|
||||||
|
readonly onUpdated = new EventEmitter<unknown>();
|
||||||
|
|
||||||
|
/** The template's control bindings */
|
||||||
|
protected settings = this.formBuilder.group({
|
||||||
|
[Controls.domain]: [""],
|
||||||
|
[Controls.token]: [""],
|
||||||
|
[Controls.baseUrl]: [""],
|
||||||
|
});
|
||||||
|
|
||||||
|
async ngOnInit() {
|
||||||
|
const singleUserId$ = this.singleUserId$();
|
||||||
|
const forwarder = getForwarderConfiguration(this.forwarder);
|
||||||
|
|
||||||
|
// type erasure necessary because the configuration properties are
|
||||||
|
// determined dynamically at runtime
|
||||||
|
// FIXME: this can be eliminated by unifying the forwarder settings types;
|
||||||
|
// see `ForwarderConfiguration<...>` for details.
|
||||||
|
const configuration = toCredentialGeneratorConfiguration<any>(forwarder);
|
||||||
|
this.displayDomain = configuration.request.includes("domain");
|
||||||
|
this.displayToken = configuration.request.includes("token");
|
||||||
|
this.displayBaseUrl = configuration.request.includes("baseUrl");
|
||||||
|
|
||||||
|
// bind settings to the UI
|
||||||
|
const settings = await this.generatorService.settings(configuration, { singleUserId$ });
|
||||||
|
settings.pipe(takeUntil(this.destroyed$)).subscribe((s) => {
|
||||||
|
// skips reactive event emissions to break a subscription cycle
|
||||||
|
this.settings.patchValue(s, { emitEvent: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
// bind policy to the template
|
||||||
|
this.generatorService
|
||||||
|
.policy$(configuration, { userId$: singleUserId$ })
|
||||||
|
.pipe(takeUntil(this.destroyed$))
|
||||||
|
.subscribe(({ constraints }) => {
|
||||||
|
for (const name in Controls) {
|
||||||
|
const control = this.settings.get(name);
|
||||||
|
if (configuration.request.includes(control as any)) {
|
||||||
|
control.enable({ emitEvent: false });
|
||||||
|
control.setValidators(
|
||||||
|
// the configuration's type erasure affects `toValidators` as well
|
||||||
|
toValidators(name, configuration, constraints),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
control.disable({ emitEvent: false });
|
||||||
|
control.clearValidators();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// the first emission is the current value; subsequent emissions are updates
|
||||||
|
settings.pipe(skip(1), takeUntil(this.destroyed$)).subscribe(this.onUpdated);
|
||||||
|
|
||||||
|
// now that outputs are set up, connect inputs
|
||||||
|
this.settings.valueChanges.pipe(takeUntil(this.destroyed$)).subscribe(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected displayDomain: boolean;
|
||||||
|
protected displayToken: boolean;
|
||||||
|
protected displayBaseUrl: boolean;
|
||||||
|
|
||||||
|
private singleUserId$() {
|
||||||
|
// FIXME: this branch should probably scan for the user and make sure
|
||||||
|
// the account is unlocked
|
||||||
|
if (this.userId) {
|
||||||
|
return new BehaviorSubject(this.userId as UserId).asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.accountService.activeAccount$.pipe(
|
||||||
|
completeOnAccountSwitch(),
|
||||||
|
takeUntil(this.destroyed$),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly destroyed$ = new Subject<void>();
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.destroyed$.complete();
|
||||||
|
}
|
||||||
|
}
|
@ -33,6 +33,7 @@ import {
|
|||||||
|
|
||||||
import { CatchallSettingsComponent } from "./catchall-settings.component";
|
import { CatchallSettingsComponent } from "./catchall-settings.component";
|
||||||
import { CredentialGeneratorComponent } from "./credential-generator.component";
|
import { CredentialGeneratorComponent } from "./credential-generator.component";
|
||||||
|
import { ForwarderSettingsComponent } from "./forwarder-settings.component";
|
||||||
import { PassphraseSettingsComponent } from "./passphrase-settings.component";
|
import { PassphraseSettingsComponent } from "./passphrase-settings.component";
|
||||||
import { PasswordGeneratorComponent } from "./password-generator.component";
|
import { PasswordGeneratorComponent } from "./password-generator.component";
|
||||||
import { PasswordSettingsComponent } from "./password-settings.component";
|
import { PasswordSettingsComponent } from "./password-settings.component";
|
||||||
@ -84,12 +85,13 @@ const RANDOMIZER = new SafeInjectionToken<Randomizer>("Randomizer");
|
|||||||
declarations: [
|
declarations: [
|
||||||
CatchallSettingsComponent,
|
CatchallSettingsComponent,
|
||||||
CredentialGeneratorComponent,
|
CredentialGeneratorComponent,
|
||||||
|
ForwarderSettingsComponent,
|
||||||
SubaddressSettingsComponent,
|
SubaddressSettingsComponent,
|
||||||
UsernameSettingsComponent,
|
|
||||||
PasswordGeneratorComponent,
|
PasswordGeneratorComponent,
|
||||||
PasswordSettingsComponent,
|
|
||||||
PassphraseSettingsComponent,
|
PassphraseSettingsComponent,
|
||||||
|
PasswordSettingsComponent,
|
||||||
UsernameGeneratorComponent,
|
UsernameGeneratorComponent,
|
||||||
|
UsernameSettingsComponent,
|
||||||
],
|
],
|
||||||
exports: [CredentialGeneratorComponent, PasswordGeneratorComponent, UsernameGeneratorComponent],
|
exports: [CredentialGeneratorComponent, PasswordGeneratorComponent, UsernameGeneratorComponent],
|
||||||
})
|
})
|
||||||
|
@ -43,6 +43,11 @@
|
|||||||
[userId]="this.userId$ | async"
|
[userId]="this.userId$ | async"
|
||||||
(onUpdated)="generate$.next()"
|
(onUpdated)="generate$.next()"
|
||||||
/>
|
/>
|
||||||
|
<tools-forwarder-settings
|
||||||
|
*ngIf="!!(forwarderId$ | async)"
|
||||||
|
[forwarder]="forwarderId$ | async"
|
||||||
|
[userId]="this.userId$ | async"
|
||||||
|
/>
|
||||||
<tools-subaddress-settings
|
<tools-subaddress-settings
|
||||||
*ngIf="(algorithm$ | async)?.id === 'subaddress'"
|
*ngIf="(algorithm$ | async)?.id === 'subaddress'"
|
||||||
[userId]="this.userId$ | async"
|
[userId]="this.userId$ | async"
|
||||||
@ -53,7 +58,6 @@
|
|||||||
[userId]="this.userId$ | async"
|
[userId]="this.userId$ | async"
|
||||||
(onUpdated)="generate$.next()"
|
(onUpdated)="generate$.next()"
|
||||||
/>
|
/>
|
||||||
<!-- TODO: list forwarder settings components -->
|
|
||||||
</bit-card>
|
</bit-card>
|
||||||
</div>
|
</div>
|
||||||
</bit-section>
|
</bit-section>
|
||||||
|
@ -16,6 +16,7 @@ import {
|
|||||||
|
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
|
import { IntegrationId } from "@bitwarden/common/tools/integration";
|
||||||
import { UserId } from "@bitwarden/common/types/guid";
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
import { Option } from "@bitwarden/components/src/select/option";
|
import { Option } from "@bitwarden/components/src/select/option";
|
||||||
import {
|
import {
|
||||||
@ -201,6 +202,11 @@ export class UsernameGeneratorComponent implements OnInit, OnDestroy {
|
|||||||
// template bindings refresh immediately
|
// template bindings refresh immediately
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
this.algorithm$.next(algorithm);
|
this.algorithm$.next(algorithm);
|
||||||
|
if (userNav === FORWARDER && forwarderNav !== NONE_SELECTED) {
|
||||||
|
this.forwarderId$.next(forwarderNav.forwarder);
|
||||||
|
} else {
|
||||||
|
this.forwarderId$.next(null);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -249,6 +255,9 @@ export class UsernameGeneratorComponent implements OnInit, OnDestroy {
|
|||||||
/** tracks the currently selected credential type */
|
/** tracks the currently selected credential type */
|
||||||
protected algorithm$ = new ReplaySubject<AlgorithmInfo>(1);
|
protected algorithm$ = new ReplaySubject<AlgorithmInfo>(1);
|
||||||
|
|
||||||
|
/** Tracks the currently selected forwarder. */
|
||||||
|
protected forwarderId$ = new BehaviorSubject<IntegrationId>(null);
|
||||||
|
|
||||||
/** Emits hint key for the currently selected credential type */
|
/** Emits hint key for the currently selected credential type */
|
||||||
protected credentialTypeHint$ = new ReplaySubject<string>(1);
|
protected credentialTypeHint$ = new ReplaySubject<string>(1);
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ const PASSPHRASE = Object.freeze({
|
|||||||
category: "password",
|
category: "password",
|
||||||
nameKey: "passphrase",
|
nameKey: "passphrase",
|
||||||
onlyOnRequest: false,
|
onlyOnRequest: false,
|
||||||
|
request: [],
|
||||||
engine: {
|
engine: {
|
||||||
create(
|
create(
|
||||||
dependencies: GeneratorDependencyProvider,
|
dependencies: GeneratorDependencyProvider,
|
||||||
@ -92,6 +93,7 @@ const PASSWORD = Object.freeze({
|
|||||||
category: "password",
|
category: "password",
|
||||||
nameKey: "password",
|
nameKey: "password",
|
||||||
onlyOnRequest: false,
|
onlyOnRequest: false,
|
||||||
|
request: [],
|
||||||
engine: {
|
engine: {
|
||||||
create(
|
create(
|
||||||
dependencies: GeneratorDependencyProvider,
|
dependencies: GeneratorDependencyProvider,
|
||||||
@ -139,6 +141,7 @@ const USERNAME = Object.freeze({
|
|||||||
category: "username",
|
category: "username",
|
||||||
nameKey: "randomWord",
|
nameKey: "randomWord",
|
||||||
onlyOnRequest: false,
|
onlyOnRequest: false,
|
||||||
|
request: [],
|
||||||
engine: {
|
engine: {
|
||||||
create(
|
create(
|
||||||
dependencies: GeneratorDependencyProvider,
|
dependencies: GeneratorDependencyProvider,
|
||||||
@ -172,6 +175,7 @@ const CATCHALL = Object.freeze({
|
|||||||
nameKey: "catchallEmail",
|
nameKey: "catchallEmail",
|
||||||
descriptionKey: "catchallEmailDesc",
|
descriptionKey: "catchallEmailDesc",
|
||||||
onlyOnRequest: false,
|
onlyOnRequest: false,
|
||||||
|
request: [],
|
||||||
engine: {
|
engine: {
|
||||||
create(
|
create(
|
||||||
dependencies: GeneratorDependencyProvider,
|
dependencies: GeneratorDependencyProvider,
|
||||||
@ -205,6 +209,7 @@ const SUBADDRESS = Object.freeze({
|
|||||||
nameKey: "plusAddressedEmail",
|
nameKey: "plusAddressedEmail",
|
||||||
descriptionKey: "plusAddressedEmailDesc",
|
descriptionKey: "plusAddressedEmailDesc",
|
||||||
onlyOnRequest: false,
|
onlyOnRequest: false,
|
||||||
|
request: [],
|
||||||
engine: {
|
engine: {
|
||||||
create(
|
create(
|
||||||
dependencies: GeneratorDependencyProvider,
|
dependencies: GeneratorDependencyProvider,
|
||||||
@ -240,6 +245,7 @@ export function toCredentialGeneratorConfiguration<Settings extends ApiSettings
|
|||||||
category: "email",
|
category: "email",
|
||||||
nameKey: configuration.name,
|
nameKey: configuration.name,
|
||||||
onlyOnRequest: true,
|
onlyOnRequest: true,
|
||||||
|
request: configuration.forwarder.request,
|
||||||
engine: {
|
engine: {
|
||||||
create(dependencies: GeneratorDependencyProvider) {
|
create(dependencies: GeneratorDependencyProvider) {
|
||||||
// FIXME: figure out why `configuration` fails to typecheck
|
// FIXME: figure out why `configuration` fails to typecheck
|
||||||
@ -249,7 +255,7 @@ export function toCredentialGeneratorConfiguration<Settings extends ApiSettings
|
|||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
initial: configuration.forwarder.defaultSettings,
|
initial: configuration.forwarder.defaultSettings,
|
||||||
constraints: {},
|
constraints: configuration.forwarder.settingsConstraints,
|
||||||
account: configuration.forwarder.settings,
|
account: configuration.forwarder.settings,
|
||||||
},
|
},
|
||||||
policy: {
|
policy: {
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import { UserKeyDefinition } from "@bitwarden/common/platform/state";
|
import { UserKeyDefinition } from "@bitwarden/common/platform/state";
|
||||||
import { IntegrationConfiguration } from "@bitwarden/common/tools/integration/integration-configuration";
|
import { IntegrationConfiguration } from "@bitwarden/common/tools/integration/integration-configuration";
|
||||||
import { ApiSettings } from "@bitwarden/common/tools/integration/rpc";
|
import { ApiSettings, SelfHostedApiSettings } from "@bitwarden/common/tools/integration/rpc";
|
||||||
import { IntegrationRequest } from "@bitwarden/common/tools/integration/rpc/integration-request";
|
import { IntegrationRequest } from "@bitwarden/common/tools/integration/rpc/integration-request";
|
||||||
import { RpcConfiguration } from "@bitwarden/common/tools/integration/rpc/rpc-definition";
|
import { RpcConfiguration } from "@bitwarden/common/tools/integration/rpc/rpc-definition";
|
||||||
import { BufferedKeyDefinition } from "@bitwarden/common/tools/state/buffered-key-definition";
|
import { BufferedKeyDefinition } from "@bitwarden/common/tools/state/buffered-key-definition";
|
||||||
import { ObjectKey } from "@bitwarden/common/tools/state/subject-key";
|
import { ObjectKey } from "@bitwarden/common/tools/state/object-key";
|
||||||
|
import { Constraints } from "@bitwarden/common/tools/types";
|
||||||
|
|
||||||
import { ForwarderContext } from "./forwarder-context";
|
import { ForwarderContext } from "./forwarder-context";
|
||||||
|
import { EmailDomainSettings, EmailPrefixSettings } from "./settings";
|
||||||
|
|
||||||
/** Mixin for transmitting `getAccountId` result. */
|
/** Mixin for transmitting `getAccountId` result. */
|
||||||
export type AccountRequest = {
|
export type AccountRequest = {
|
||||||
@ -25,8 +27,16 @@ export type GetAccountIdRpcDef<
|
|||||||
Request extends IntegrationRequest = IntegrationRequest,
|
Request extends IntegrationRequest = IntegrationRequest,
|
||||||
> = RpcConfiguration<Request, ForwarderContext<Settings>, string>;
|
> = RpcConfiguration<Request, ForwarderContext<Settings>, string>;
|
||||||
|
|
||||||
|
export type ForwarderRequestFields = keyof (ApiSettings &
|
||||||
|
SelfHostedApiSettings &
|
||||||
|
EmailDomainSettings &
|
||||||
|
EmailPrefixSettings);
|
||||||
|
|
||||||
/** Forwarder-specific static definition */
|
/** Forwarder-specific static definition */
|
||||||
export type ForwarderConfiguration<
|
export type ForwarderConfiguration<
|
||||||
|
// FIXME: simply forwarder settings to an object that has all
|
||||||
|
// settings properties. The runtime dynamism should be limited
|
||||||
|
// to which have values, not which have properties listed.
|
||||||
Settings extends ApiSettings,
|
Settings extends ApiSettings,
|
||||||
Request extends IntegrationRequest = IntegrationRequest,
|
Request extends IntegrationRequest = IntegrationRequest,
|
||||||
> = IntegrationConfiguration & {
|
> = IntegrationConfiguration & {
|
||||||
@ -35,6 +45,11 @@ export type ForwarderConfiguration<
|
|||||||
/** default value of all fields */
|
/** default value of all fields */
|
||||||
defaultSettings: Partial<Settings>;
|
defaultSettings: Partial<Settings>;
|
||||||
|
|
||||||
|
settingsConstraints: Constraints<Settings>;
|
||||||
|
|
||||||
|
/** Well-known fields to display on the forwarder screen */
|
||||||
|
request: readonly ForwarderRequestFields[];
|
||||||
|
|
||||||
/** forwarder settings storage
|
/** forwarder settings storage
|
||||||
* @deprecated use local.settings instead
|
* @deprecated use local.settings instead
|
||||||
*/
|
*/
|
||||||
|
@ -52,6 +52,12 @@ const createForwardingEmail = Object.freeze({
|
|||||||
const forwarder = Object.freeze({
|
const forwarder = Object.freeze({
|
||||||
defaultSettings,
|
defaultSettings,
|
||||||
createForwardingEmail,
|
createForwardingEmail,
|
||||||
|
request: ["token", "baseUrl", "domain"],
|
||||||
|
settingsConstraints: {
|
||||||
|
token: { required: true },
|
||||||
|
domain: { required: true },
|
||||||
|
baseUrl: {},
|
||||||
|
},
|
||||||
local: {
|
local: {
|
||||||
settings: {
|
settings: {
|
||||||
// FIXME: integration should issue keys at runtime
|
// FIXME: integration should issue keys at runtime
|
||||||
|
@ -44,6 +44,10 @@ const createForwardingEmail = Object.freeze({
|
|||||||
const forwarder = Object.freeze({
|
const forwarder = Object.freeze({
|
||||||
defaultSettings,
|
defaultSettings,
|
||||||
createForwardingEmail,
|
createForwardingEmail,
|
||||||
|
request: ["token"],
|
||||||
|
settingsConstraints: {
|
||||||
|
token: { required: true },
|
||||||
|
},
|
||||||
local: {
|
local: {
|
||||||
settings: {
|
settings: {
|
||||||
// FIXME: integration should issue keys at runtime
|
// FIXME: integration should issue keys at runtime
|
||||||
|
@ -110,6 +110,12 @@ const forwarder = Object.freeze({
|
|||||||
defaultSettings,
|
defaultSettings,
|
||||||
createForwardingEmail,
|
createForwardingEmail,
|
||||||
getAccountId,
|
getAccountId,
|
||||||
|
request: ["token", "domain", "prefix"],
|
||||||
|
settingsConstraints: {
|
||||||
|
token: { required: true },
|
||||||
|
domain: { required: true },
|
||||||
|
prefix: {},
|
||||||
|
},
|
||||||
local: {
|
local: {
|
||||||
settings: {
|
settings: {
|
||||||
// FIXME: integration should issue keys at runtime
|
// FIXME: integration should issue keys at runtime
|
||||||
|
@ -48,6 +48,10 @@ const createForwardingEmail = Object.freeze({
|
|||||||
const forwarder = Object.freeze({
|
const forwarder = Object.freeze({
|
||||||
defaultSettings,
|
defaultSettings,
|
||||||
createForwardingEmail,
|
createForwardingEmail,
|
||||||
|
request: ["token"],
|
||||||
|
settingsConstraints: {
|
||||||
|
token: { required: true },
|
||||||
|
},
|
||||||
local: {
|
local: {
|
||||||
settings: {
|
settings: {
|
||||||
// FIXME: integration should issue keys at runtime
|
// FIXME: integration should issue keys at runtime
|
||||||
|
@ -50,6 +50,11 @@ const createForwardingEmail = Object.freeze({
|
|||||||
// forwarder configuration
|
// forwarder configuration
|
||||||
const forwarder = Object.freeze({
|
const forwarder = Object.freeze({
|
||||||
defaultSettings,
|
defaultSettings,
|
||||||
|
request: ["token", "domain"],
|
||||||
|
settingsConstraints: {
|
||||||
|
token: { required: true },
|
||||||
|
domain: { required: true },
|
||||||
|
},
|
||||||
local: {
|
local: {
|
||||||
settings: {
|
settings: {
|
||||||
// FIXME: integration should issue keys at runtime
|
// FIXME: integration should issue keys at runtime
|
||||||
|
@ -53,6 +53,10 @@ const createForwardingEmail = Object.freeze({
|
|||||||
const forwarder = Object.freeze({
|
const forwarder = Object.freeze({
|
||||||
defaultSettings,
|
defaultSettings,
|
||||||
createForwardingEmail,
|
createForwardingEmail,
|
||||||
|
request: ["token", "baseUrl"],
|
||||||
|
settingsConstraints: {
|
||||||
|
token: { required: true },
|
||||||
|
},
|
||||||
local: {
|
local: {
|
||||||
settings: {
|
settings: {
|
||||||
// FIXME: integration should issue keys at runtime
|
// FIXME: integration should issue keys at runtime
|
||||||
|
@ -244,6 +244,7 @@ export class CredentialGeneratorService {
|
|||||||
category: generator.category,
|
category: generator.category,
|
||||||
name: integration ? integration.name : this.i18nService.t(generator.nameKey),
|
name: integration ? integration.name : this.i18nService.t(generator.nameKey),
|
||||||
onlyOnRequest: generator.onlyOnRequest,
|
onlyOnRequest: generator.onlyOnRequest,
|
||||||
|
request: generator.request,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (generator.descriptionKey) {
|
if (generator.descriptionKey) {
|
||||||
|
@ -40,6 +40,11 @@ export type AlgorithmInfo = {
|
|||||||
* to Bitwarden.
|
* to Bitwarden.
|
||||||
*/
|
*/
|
||||||
onlyOnRequest: boolean;
|
onlyOnRequest: boolean;
|
||||||
|
|
||||||
|
/** Well-known fields to display on the options panel or collect from the environment.
|
||||||
|
* @remarks: at present, this is only used by forwarders
|
||||||
|
*/
|
||||||
|
request: readonly string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Credential generator metadata common across credential generators */
|
/** Credential generator metadata common across credential generators */
|
||||||
@ -68,6 +73,11 @@ export type CredentialGeneratorInfo = {
|
|||||||
* to Bitwarden.
|
* to Bitwarden.
|
||||||
*/
|
*/
|
||||||
onlyOnRequest: boolean;
|
onlyOnRequest: boolean;
|
||||||
|
|
||||||
|
/** Well-known fields to display on the options panel or collect from the environment.
|
||||||
|
* @remarks: at present, this is only used by forwarders
|
||||||
|
*/
|
||||||
|
request: readonly string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Credential generator metadata that relies upon typed setting and policy definitions.
|
/** Credential generator metadata that relies upon typed setting and policy definitions.
|
||||||
|
Loading…
Reference in New Issue
Block a user