mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-02 18:17:46 +01:00
[PM-3326] [CLI] Add minNumber, minSpecial and ambiguous password generation options (#5974)
* feat(cli): add minNumber option and pass to generation service * feat(cli): add minSpecial option and pass to generation service * feat(cli): add ambiguous option and pass to generation service * refactor: extract utils to convert number and string options * feat(ts): add types to utils and options * feat: validate result of parsed value in convertNumberOption util
This commit is contained in:
parent
bf7aa6473e
commit
a920d62dfe
@ -298,9 +298,12 @@ export class Program {
|
|||||||
.option("-p, --passphrase", "Generate a passphrase.")
|
.option("-p, --passphrase", "Generate a passphrase.")
|
||||||
.option("--length <length>", "Length of the password.")
|
.option("--length <length>", "Length of the password.")
|
||||||
.option("--words <words>", "Number of words.")
|
.option("--words <words>", "Number of words.")
|
||||||
|
.option("--minNumber <count>", "Minimum number of numeric characters.")
|
||||||
|
.option("--minSpecial <count>", "Minimum number of special characters.")
|
||||||
.option("--separator <separator>", "Word separator.")
|
.option("--separator <separator>", "Word separator.")
|
||||||
.option("-c, --capitalize", "Title case passphrase.")
|
.option("-c, --capitalize", "Title case passphrase.")
|
||||||
.option("--includeNumber", "Passphrase includes number.")
|
.option("--includeNumber", "Passphrase includes number.")
|
||||||
|
.option("--ambiguous", "Avoid ambiguous characters.")
|
||||||
.on("--help", () => {
|
.on("--help", () => {
|
||||||
writeLn("\n Notes:");
|
writeLn("\n Notes:");
|
||||||
writeLn("");
|
writeLn("");
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||||
|
import { PasswordGeneratorOptions } from "@bitwarden/common/tools/generator/password/password-generator-options";
|
||||||
|
|
||||||
import { Response } from "../models/response";
|
import { Response } from "../models/response";
|
||||||
import { StringResponse } from "../models/response/string.response";
|
import { StringResponse } from "../models/response/string.response";
|
||||||
@ -13,7 +14,7 @@ export class GenerateCommand {
|
|||||||
|
|
||||||
async run(cmdOptions: Record<string, any>): Promise<Response> {
|
async run(cmdOptions: Record<string, any>): Promise<Response> {
|
||||||
const normalizedOptions = new Options(cmdOptions);
|
const normalizedOptions = new Options(cmdOptions);
|
||||||
const options = {
|
const options: PasswordGeneratorOptions = {
|
||||||
uppercase: normalizedOptions.uppercase,
|
uppercase: normalizedOptions.uppercase,
|
||||||
lowercase: normalizedOptions.lowercase,
|
lowercase: normalizedOptions.lowercase,
|
||||||
number: normalizedOptions.number,
|
number: normalizedOptions.number,
|
||||||
@ -24,6 +25,9 @@ export class GenerateCommand {
|
|||||||
numWords: normalizedOptions.words,
|
numWords: normalizedOptions.words,
|
||||||
capitalize: normalizedOptions.capitalize,
|
capitalize: normalizedOptions.capitalize,
|
||||||
includeNumber: normalizedOptions.includeNumber,
|
includeNumber: normalizedOptions.includeNumber,
|
||||||
|
minNumber: normalizedOptions.minNumber,
|
||||||
|
minSpecial: normalizedOptions.minSpecial,
|
||||||
|
ambiguous: normalizedOptions.ambiguous,
|
||||||
};
|
};
|
||||||
|
|
||||||
const enforcedOptions = (await this.stateService.getIsAuthenticated())
|
const enforcedOptions = (await this.stateService.getIsAuthenticated())
|
||||||
@ -47,6 +51,9 @@ class Options {
|
|||||||
words: number;
|
words: number;
|
||||||
capitalize: boolean;
|
capitalize: boolean;
|
||||||
includeNumber: boolean;
|
includeNumber: boolean;
|
||||||
|
minNumber: number;
|
||||||
|
minSpecial: number;
|
||||||
|
ambiguous: boolean;
|
||||||
|
|
||||||
constructor(passedOptions: Record<string, any>) {
|
constructor(passedOptions: Record<string, any>) {
|
||||||
this.uppercase = CliUtils.convertBooleanOption(passedOptions?.uppercase);
|
this.uppercase = CliUtils.convertBooleanOption(passedOptions?.uppercase);
|
||||||
@ -55,10 +62,13 @@ class Options {
|
|||||||
this.special = CliUtils.convertBooleanOption(passedOptions?.special);
|
this.special = CliUtils.convertBooleanOption(passedOptions?.special);
|
||||||
this.capitalize = CliUtils.convertBooleanOption(passedOptions?.capitalize);
|
this.capitalize = CliUtils.convertBooleanOption(passedOptions?.capitalize);
|
||||||
this.includeNumber = CliUtils.convertBooleanOption(passedOptions?.includeNumber);
|
this.includeNumber = CliUtils.convertBooleanOption(passedOptions?.includeNumber);
|
||||||
this.length = passedOptions?.length != null ? parseInt(passedOptions?.length, null) : 14;
|
this.ambiguous = CliUtils.convertBooleanOption(passedOptions?.ambiguous);
|
||||||
|
this.length = CliUtils.convertNumberOption(passedOptions?.length, 14);
|
||||||
this.type = passedOptions?.passphrase ? "passphrase" : "password";
|
this.type = passedOptions?.passphrase ? "passphrase" : "password";
|
||||||
this.separator = passedOptions?.separator == null ? "-" : passedOptions.separator + "";
|
this.separator = CliUtils.convertStringOption(passedOptions?.separator, "-");
|
||||||
this.words = passedOptions?.words != null ? parseInt(passedOptions.words, null) : 3;
|
this.words = CliUtils.convertNumberOption(passedOptions?.words, 3);
|
||||||
|
this.minNumber = CliUtils.convertNumberOption(passedOptions?.minNumber, 1);
|
||||||
|
this.minSpecial = CliUtils.convertNumberOption(passedOptions?.minSpecial, 1);
|
||||||
|
|
||||||
if (!this.uppercase && !this.lowercase && !this.special && !this.number) {
|
if (!this.uppercase && !this.lowercase && !this.special && !this.number) {
|
||||||
this.lowercase = true;
|
this.lowercase = true;
|
||||||
|
@ -253,4 +253,20 @@ export class CliUtils {
|
|||||||
static convertBooleanOption(optionValue: any) {
|
static convertBooleanOption(optionValue: any) {
|
||||||
return optionValue || optionValue === "" ? true : false;
|
return optionValue || optionValue === "" ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static convertNumberOption(optionValue: any, defaultValue: number) {
|
||||||
|
try {
|
||||||
|
if (optionValue != null) {
|
||||||
|
const numVal = parseInt(optionValue);
|
||||||
|
return !Number.isNaN(numVal) ? numVal : defaultValue;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
} catch {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static convertStringOption(optionValue: any, defaultValue: string) {
|
||||||
|
return optionValue != null ? String(optionValue) : defaultValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user