mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 08:43:33 +00:00
[PM-16793] port credential generator service to providers (#14071)
* introduce extension service * deprecate legacy forwarder types * eliminate repeat algorithm emissions * extend logging to preference management * align forwarder ids with vendor ids * fix duplicate policy emissions; debugging required logger enhancements ----- Co-authored-by: Daniel James Smith <2670567+djsmith85@users.noreply.github.com>
This commit is contained in:
@@ -1,71 +1,46 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { ValidatorFn, Validators } from "@angular/forms";
|
||||
import { distinctUntilChanged, map, pairwise, pipe, skipWhile, startWith, takeWhile } from "rxjs";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { I18nKeyOrLiteral } from "@bitwarden/common/tools/types";
|
||||
import { isI18nKey } from "@bitwarden/common/tools/util";
|
||||
import { AlgorithmInfo, AlgorithmMetadata } from "@bitwarden/generator-core";
|
||||
|
||||
import { AnyConstraint, Constraints } from "@bitwarden/common/tools/types";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { CredentialGeneratorConfiguration } from "@bitwarden/generator-core";
|
||||
/** Adapts {@link AlgorithmMetadata} to legacy {@link AlgorithmInfo} structure. */
|
||||
export function toAlgorithmInfo(metadata: AlgorithmMetadata, i18n: I18nService) {
|
||||
const info: AlgorithmInfo = {
|
||||
id: metadata.id,
|
||||
type: metadata.type,
|
||||
name: translate(metadata.i18nKeys.name, i18n),
|
||||
generate: translate(metadata.i18nKeys.generateCredential, i18n),
|
||||
onGeneratedMessage: translate(metadata.i18nKeys.credentialGenerated, i18n),
|
||||
credentialType: translate(metadata.i18nKeys.credentialType, i18n),
|
||||
copy: translate(metadata.i18nKeys.copyCredential, i18n),
|
||||
useGeneratedValue: translate(metadata.i18nKeys.useCredential, i18n),
|
||||
onlyOnRequest: !metadata.capabilities.autogenerate,
|
||||
request: metadata.capabilities.fields,
|
||||
};
|
||||
|
||||
export function completeOnAccountSwitch() {
|
||||
return pipe(
|
||||
map(({ id }: { id: UserId | null }) => id),
|
||||
skipWhile((id) => !id),
|
||||
startWith(null as UserId),
|
||||
pairwise(),
|
||||
takeWhile(([prev, next]) => (prev ?? next) === next),
|
||||
map(([_, id]) => id),
|
||||
distinctUntilChanged(),
|
||||
);
|
||||
if (metadata.i18nKeys.description) {
|
||||
info.description = translate(metadata.i18nKeys.description, i18n);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
export function toValidators<Policy, Settings>(
|
||||
target: keyof Settings,
|
||||
configuration: CredentialGeneratorConfiguration<Settings, Policy>,
|
||||
policy?: Constraints<Settings>,
|
||||
) {
|
||||
const validators: Array<ValidatorFn> = [];
|
||||
|
||||
// widen the types to avoid typecheck issues
|
||||
const config: AnyConstraint = configuration.settings.constraints[target];
|
||||
const runtime: AnyConstraint = policy[target];
|
||||
|
||||
const required = getConstraint("required", config, runtime) ?? false;
|
||||
if (required) {
|
||||
validators.push(Validators.required);
|
||||
}
|
||||
|
||||
const maxLength = getConstraint("maxLength", config, runtime);
|
||||
if (maxLength !== undefined) {
|
||||
validators.push(Validators.maxLength(maxLength));
|
||||
}
|
||||
|
||||
const minLength = getConstraint("minLength", config, runtime);
|
||||
if (minLength !== undefined) {
|
||||
validators.push(Validators.minLength(config.minLength));
|
||||
}
|
||||
|
||||
const min = getConstraint("min", config, runtime);
|
||||
if (min !== undefined) {
|
||||
validators.push(Validators.min(min));
|
||||
}
|
||||
|
||||
const max = getConstraint("max", config, runtime);
|
||||
if (max !== undefined) {
|
||||
validators.push(Validators.max(max));
|
||||
}
|
||||
|
||||
return validators;
|
||||
/** Translates an internationalization key
|
||||
* @param key the key to translate
|
||||
* @param i18n the service providing translations
|
||||
* @returns the translated key; if the key is a literal the literal
|
||||
* is returned instead.
|
||||
*/
|
||||
export function translate(key: I18nKeyOrLiteral, i18n: I18nService) {
|
||||
return isI18nKey(key) ? i18n.t(key) : key.literal;
|
||||
}
|
||||
|
||||
function getConstraint<Key extends keyof AnyConstraint>(
|
||||
key: Key,
|
||||
config: AnyConstraint,
|
||||
policy?: AnyConstraint,
|
||||
) {
|
||||
if (policy && key in policy) {
|
||||
return policy[key] ?? config[key];
|
||||
} else if (config && key in config) {
|
||||
return config[key];
|
||||
}
|
||||
/** Returns true when min < max
|
||||
* @param min the minimum value to check; when this is nullish it becomes 0.
|
||||
* @param max the maximum value to check; when this is nullish it becomes +Infinity.
|
||||
*/
|
||||
export function hasRangeOfValues(min?: number, max?: number) {
|
||||
const minimum = min ?? 0;
|
||||
const maximum = max ?? Number.POSITIVE_INFINITY;
|
||||
return minimum < maximum;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user