Custom mask for secret (#970)

* Masking Character added, not yet used.

* Setting the masking character can be chained with other extensions.

* Added string extension for masking, and replaced hardcoded asterisks.

* Check if mask is null first.

* Fixed Typo in previous test and added new test for custom masks.

* Added tests for masking with null character

* Added docs and example.

* Adjusted extensions so that Mask is integrated into Secret extension. Updated Exampls and Tests accordingly
This commit is contained in:
Gary McDougall
2022-09-26 11:34:41 -07:00
committed by GitHub
parent 088db165ed
commit eb02c3d534
9 changed files with 142 additions and 12 deletions

View File

@ -28,7 +28,13 @@ public sealed class TextPrompt<T> : IPrompt<T>
/// Gets or sets a value indicating whether input should
/// be hidden in the console.
/// </summary>
public bool IsSecret { get; set; }
public bool IsSecret { get; set; }
/// <summary>
/// Gets or sets the character to use while masking
/// a secret prompt.
/// </summary>
public char? Mask { get; set; } = '*';
/// <summary>
/// Gets or sets the validation error message.
@ -119,14 +125,15 @@ public sealed class TextPrompt<T> : IPrompt<T>
while (true)
{
var input = await console.ReadLine(promptStyle, IsSecret, choices, cancellationToken).ConfigureAwait(false);
var input = await console.ReadLine(promptStyle, IsSecret, Mask, choices, cancellationToken).ConfigureAwait(false);
// Nothing entered?
if (string.IsNullOrWhiteSpace(input))
{
if (DefaultValue != null)
{
console.Write(IsSecret ? "******" : converter(DefaultValue.Value), promptStyle);
{
var defaultValue = converter(DefaultValue.Value);
console.Write(IsSecret ? defaultValue.Mask(Mask) : defaultValue, promptStyle);
console.WriteLine();
return DefaultValue.Value;
}
@ -201,13 +208,14 @@ public sealed class TextPrompt<T> : IPrompt<T>
{
appendSuffix = true;
var converter = Converter ?? TypeConverterHelper.ConvertToString;
var defaultValueStyle = DefaultValueStyle?.ToMarkup() ?? "green";
var defaultValueStyle = DefaultValueStyle?.ToMarkup() ?? "green";
var defaultValue = converter(DefaultValue.Value);
builder.AppendFormat(
CultureInfo.InvariantCulture,
" [{0}]({1})[/]",
defaultValueStyle,
IsSecret ? "******" : converter(DefaultValue.Value));
IsSecret ? defaultValue.Mask(Mask) : defaultValue);
}
var markup = builder.ToString().Trim();

View File

@ -286,6 +286,25 @@ public static class TextPromptExtensions
obj.IsSecret = true;
return obj;
}
/// <summary>
/// Replaces prompt user input with mask in the console.
/// </summary>
/// <typeparam name="T">The prompt type.</typeparam>
/// <param name="obj">The prompt.</param>
/// <param name="mask">The masking character to use for the secret.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static TextPrompt<T> Secret<T>(this TextPrompt<T> obj, char? mask)
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.IsSecret = true;
obj.Mask = mask;
return obj;
}
/// <summary>