From baf11a1275bbddc19765135902417d808740e8ed Mon Sep 17 00:00:00 2001 From: Chris <362037+ChrisAnn@users.noreply.github.com> Date: Thu, 24 Oct 2024 09:42:20 +0100 Subject: [PATCH 1/4] Adds the ability to specify an appsettings file for user-jwts Addresses https://github.com/dotnet/aspnetcore/issues/56169 --- .../src/Commands/ClearCommand.cs | 36 ++++-- .../src/Commands/CreateCommand.cs | 43 ++++++-- .../src/Commands/RemoveCommand.cs | 38 +++++-- src/Tools/dotnet-user-jwts/src/Resources.resx | 18 +++ .../test/UserJwtsTestFixture.cs | 4 + .../dotnet-user-jwts/test/UserJwtsTests.cs | 104 ++++++++++++++++++ 6 files changed, 222 insertions(+), 21 deletions(-) diff --git a/src/Tools/dotnet-user-jwts/src/Commands/ClearCommand.cs b/src/Tools/dotnet-user-jwts/src/Commands/ClearCommand.cs index 2b977e3f6313..97d91cf74a4f 100644 --- a/src/Tools/dotnet-user-jwts/src/Commands/ClearCommand.cs +++ b/src/Tools/dotnet-user-jwts/src/Commands/ClearCommand.cs @@ -19,21 +19,43 @@ public static void Register(ProjectCommandLineApplication app) Resources.ClearCommand_ForceOption_Description, CommandOptionType.NoValue); + var appsettingsFileOption = cmd.Option( + "--appsettings-file", + Resources.CreateCommand_appsettingsFileOption_Description, + CommandOptionType.SingleValue); + cmd.HelpOption("-h|--help"); cmd.OnExecute(() => { - return Execute(cmd.Reporter, cmd.ProjectOption.Value(), forceOption.HasValue()); + if (!DevJwtCliHelpers.GetProjectAndSecretsId(cmd.ProjectOption.Value(), cmd.Reporter, out var project, out var userSecretsId)) + { + return 1; + } + + var appsettingsFile = "appsettings.Development.json"; + if (appsettingsFileOption.HasValue()) + { + appsettingsFile = appsettingsFileOption.Value(); + if (!appsettingsFile.EndsWith(".json", StringComparison.OrdinalIgnoreCase)) + { + cmd.Reporter.Error(Resources.RemoveCommand_InvalidAppsettingsFile_Error); + return 1; + } + else if (!File.Exists(Path.Combine(Path.GetDirectoryName(project), appsettingsFile))) + { + cmd.Reporter.Error(Resources.FormatRemoveCommand_AppsettingsFileNotFound_Error(Path.GetDirectoryName(project))); + return 1; + } + } + + return Execute(cmd.Reporter, project, userSecretsId, forceOption.HasValue(), appsettingsFile); }); }); } - private static int Execute(IReporter reporter, string projectPath, bool force) + private static int Execute(IReporter reporter, string project, string userSecretsId, bool force, string appsettingsFile) { - if (!DevJwtCliHelpers.GetProjectAndSecretsId(projectPath, reporter, out var project, out var userSecretsId)) - { - return 1; - } var jwtStore = new JwtStore(userSecretsId); var count = jwtStore.Jwts.Count; @@ -54,7 +76,7 @@ private static int Execute(IReporter reporter, string projectPath, bool force) } } - var appsettingsFilePath = Path.Combine(Path.GetDirectoryName(project), "appsettings.Development.json"); + var appsettingsFilePath = Path.Combine(Path.GetDirectoryName(project), appsettingsFile); foreach (var jwt in jwtStore.Jwts) { JwtAuthenticationSchemeSettings.RemoveScheme(appsettingsFilePath, jwt.Value.Scheme); diff --git a/src/Tools/dotnet-user-jwts/src/Commands/CreateCommand.cs b/src/Tools/dotnet-user-jwts/src/Commands/CreateCommand.cs index ef3a3b833655..1baac76fa888 100644 --- a/src/Tools/dotnet-user-jwts/src/Commands/CreateCommand.cs +++ b/src/Tools/dotnet-user-jwts/src/Commands/CreateCommand.cs @@ -77,24 +77,29 @@ public static void Register(ProjectCommandLineApplication app, Program program) Resources.CreateCommand_ValidForOption_Description, CommandOptionType.SingleValue); + var appsettingsFileOption = cmd.Option( + "--appsettings-file", + Resources.CreateCommand_appsettingsFileOption_Description, + CommandOptionType.SingleValue); + cmd.HelpOption("-h|--help"); cmd.OnExecute(() => { - var (options, isValid, optionsString) = ValidateArguments( - cmd.Reporter, cmd.ProjectOption, schemeNameOption, nameOption, audienceOption, issuerOption, notBeforeOption, expiresOnOption, validForOption, rolesOption, scopesOption, claimsOption); + var (options, isValid, optionsString, appsettingsFile) = ValidateArguments( + cmd.Reporter, cmd.ProjectOption, schemeNameOption, nameOption, audienceOption, issuerOption, notBeforeOption, expiresOnOption, validForOption, rolesOption, scopesOption, claimsOption, appsettingsFileOption); if (!isValid) { return 1; } - return Execute(cmd.Reporter, cmd.ProjectOption.Value(), options, optionsString, cmd.OutputOption.Value(), program); + return Execute(cmd.Reporter, cmd.ProjectOption.Value(), options, optionsString, cmd.OutputOption.Value(), appsettingsFile, program); }); }); } - private static (JwtCreatorOptions, bool, string) ValidateArguments( + private static (JwtCreatorOptions, bool, string, string) ValidateArguments( IReporter reporter, CommandOption projectOption, CommandOption schemeNameOption, @@ -106,7 +111,8 @@ private static (JwtCreatorOptions, bool, string) ValidateArguments( CommandOption validForOption, CommandOption rolesOption, CommandOption scopesOption, - CommandOption claimsOption) + CommandOption claimsOption, + CommandOption appsettingsFileOption) { var isValid = true; var finder = new MsBuildProjectFinder(Directory.GetCurrentDirectory()); @@ -121,6 +127,7 @@ private static (JwtCreatorOptions, bool, string) ValidateArguments( return ( null, isValid, + string.Empty, string.Empty ); } @@ -209,10 +216,31 @@ private static (JwtCreatorOptions, bool, string) ValidateArguments( optionsString += $"{Resources.JwtPrint_CustomClaims}: [{string.Join(", ", claims.Select(kvp => $"{kvp.Key}={kvp.Value}"))}]{Environment.NewLine}"; } + var appsettingsFile = "appsettings.Development.json"; + if (appsettingsFileOption.HasValue()) + { + appsettingsFile = appsettingsFileOption.Value(); + if (!appsettingsFile.EndsWith(".json", StringComparison.OrdinalIgnoreCase)) + { + reporter.Error(Resources.CreateCommand_InvalidAppsettingsFile_Error); + isValid = false; + } + else if (!File.Exists(Path.Combine(Path.GetDirectoryName(project), appsettingsFile))) + { + reporter.Error(Resources.FormatCreateCommand_AppsettingsFileNotFound_Error(Path.GetDirectoryName(project))); + isValid = false; + } + else + { + optionsString += appsettingsFileOption.HasValue() ? $"{Resources.JwtPrint_appsettingsFile}: {appsettingsFile}{Environment.NewLine}" : string.Empty; + } + } + return ( new JwtCreatorOptions(scheme, name, audience, issuer, notBefore, expiresOn, roles, scopes, claims), isValid, - optionsString); + optionsString, + appsettingsFile); static bool ParseDate(string datetime, out DateTime parsedDateTime) => DateTime.TryParseExact(datetime, _dateTimeFormats, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out parsedDateTime); @@ -224,6 +252,7 @@ private static int Execute( JwtCreatorOptions options, string optionsString, string outputFormat, + string appsettingsFile, Program program) { if (!DevJwtCliHelpers.GetProjectAndSecretsId(projectPath, reporter, out var project, out var userSecretsId)) @@ -244,7 +273,7 @@ private static int Execute( jwtStore.Jwts.Add(jwtToken.Id, jwt); jwtStore.Save(); - var appsettingsFilePath = Path.Combine(Path.GetDirectoryName(project), "appsettings.Development.json"); + var appsettingsFilePath = Path.Combine(Path.GetDirectoryName(project), appsettingsFile); var settingsToWrite = new JwtAuthenticationSchemeSettings(options.Scheme, options.Audiences, options.Issuer); settingsToWrite.Save(appsettingsFilePath); diff --git a/src/Tools/dotnet-user-jwts/src/Commands/RemoveCommand.cs b/src/Tools/dotnet-user-jwts/src/Commands/RemoveCommand.cs index 0c3a69eaf40e..27c2fdad1a42 100644 --- a/src/Tools/dotnet-user-jwts/src/Commands/RemoveCommand.cs +++ b/src/Tools/dotnet-user-jwts/src/Commands/RemoveCommand.cs @@ -15,6 +15,12 @@ public static void Register(ProjectCommandLineApplication app) cmd.Description = Resources.RemoveCommand_Description; var idArgument = cmd.Argument("[id]", Resources.RemoveCommand_IdArgument_Description); + + var appsettingsFileOption = cmd.Option( + "--appsettings-file", + Resources.CreateCommand_appsettingsFileOption_Description, + CommandOptionType.SingleValue); + cmd.HelpOption("-h|--help"); cmd.OnExecute(() => @@ -24,17 +30,35 @@ public static void Register(ProjectCommandLineApplication app) cmd.ShowHelp(); return 0; } - return Execute(cmd.Reporter, cmd.ProjectOption.Value(), idArgument.Value); + + if (!DevJwtCliHelpers.GetProjectAndSecretsId(cmd.ProjectOption.Value(), cmd.Reporter, out var project, out var userSecretsId)) + { + return 1; + } + + var appsettingsFile = "appsettings.Development.json"; + if (appsettingsFileOption.HasValue()) + { + appsettingsFile = appsettingsFileOption.Value(); + if (!appsettingsFile.EndsWith(".json", StringComparison.OrdinalIgnoreCase)) + { + cmd.Reporter.Error(Resources.RemoveCommand_InvalidAppsettingsFile_Error); + return 1; + } + else if (!File.Exists(Path.Combine(Path.GetDirectoryName(project), appsettingsFile))) + { + cmd.Reporter.Error(Resources.FormatRemoveCommand_AppsettingsFileNotFound_Error(Path.GetDirectoryName(project))); + return 1; + } + } + + return Execute(cmd.Reporter, project, userSecretsId, idArgument.Value, appsettingsFile); }); }); } - private static int Execute(IReporter reporter, string projectPath, string id) + private static int Execute(IReporter reporter, string project, string userSecretsId, string id, string appsettingsFile) { - if (!DevJwtCliHelpers.GetProjectAndSecretsId(projectPath, reporter, out var project, out var userSecretsId)) - { - return 1; - } var jwtStore = new JwtStore(userSecretsId); if (!jwtStore.Jwts.TryGetValue(id, out var jwt)) @@ -43,7 +67,7 @@ private static int Execute(IReporter reporter, string projectPath, string id) return 1; } - var appsettingsFilePath = Path.Combine(Path.GetDirectoryName(project), "appsettings.Development.json"); + var appsettingsFilePath = Path.Combine(Path.GetDirectoryName(project), appsettingsFile); JwtAuthenticationSchemeSettings.RemoveScheme(appsettingsFilePath, jwt.Scheme); jwtStore.Jwts.Remove(id); jwtStore.Save(); diff --git a/src/Tools/dotnet-user-jwts/src/Resources.resx b/src/Tools/dotnet-user-jwts/src/Resources.resx index 094a066418d9..64b475f88309 100644 --- a/src/Tools/dotnet-user-jwts/src/Resources.resx +++ b/src/Tools/dotnet-user-jwts/src/Resources.resx @@ -150,6 +150,12 @@ The UTC date & time the JWT should expire in the format 'yyyy-MM-dd [[[[HH:mm]]:ss]]'. Defaults to 3 months after the --not-before date. Do not use this option in conjunction with the --valid-for option. + + Invalid Appsettings file extension. Ensure file extension is .json. + + + Could not find Appsettings file in '{0}'. Check the filename and that the file exists. + Malformed claims supplied. Ensure each claim is in the format "name=value". @@ -189,6 +195,9 @@ The period the JWT should expire after. Specify using a number followed by a duration type like 'd' for days, 'h' for hours, 'm' for minutes, and 's' for seconds, e.g. '365d'. Do not use this option in conjunction with the --expires-on option. + + The appSettings configuration file to add the test scheme to. + Audience(s) @@ -225,6 +234,9 @@ Scopes + + Appsettings File + Token @@ -312,6 +324,12 @@ No JWT with ID '{0}' found. + + Invalid Appsettings file extension. Ensure file extension is .json. + + + Could not find Appsettings file in '{0}'. Check the filename and that the file exists. + The issuer associated with the signing key to be reset or displayed. Defaults to 'dotnet-user-jwts'. diff --git a/src/Tools/dotnet-user-jwts/test/UserJwtsTestFixture.cs b/src/Tools/dotnet-user-jwts/test/UserJwtsTestFixture.cs index 946530df7c6a..b812a017255c 100644 --- a/src/Tools/dotnet-user-jwts/test/UserJwtsTestFixture.cs +++ b/src/Tools/dotnet-user-jwts/test/UserJwtsTestFixture.cs @@ -81,6 +81,10 @@ public string CreateProject(bool hasSecret = true) Path.Combine(projectPath.FullName, "appsettings.Development.json"), "{}"); + File.WriteAllText( + Path.Combine(projectPath.FullName, "appsettings.Local.json"), + "{}"); + if (hasSecret) { _disposables.Push(() => diff --git a/src/Tools/dotnet-user-jwts/test/UserJwtsTests.cs b/src/Tools/dotnet-user-jwts/test/UserJwtsTests.cs index 71cc2cdb7d10..b37355d79408 100644 --- a/src/Tools/dotnet-user-jwts/test/UserJwtsTests.cs +++ b/src/Tools/dotnet-user-jwts/test/UserJwtsTests.cs @@ -79,6 +79,23 @@ public void Create_CanModifyExistingScheme() Assert.Equal("new-issuer", appSettings["Authentication"]["Schemes"]["Bearer"]["ValidIssuer"].GetValue()); } + [Fact] + public void Create_CanModifyExistingSchemeInGivenAppSettings() + { + var project = Path.Combine(fixture.CreateProject(), "TestProject.csproj"); + var appsettings = Path.Combine(Path.GetDirectoryName(project), "appsettings.Local.json"); + var app = new Program(_console); + + app.Run(new[] { "create", "--project", project, "--appsettings-file", "appsettings.Local.json" }); + Assert.Contains("New JWT saved", _console.GetOutput()); + + var appSettings = JsonSerializer.Deserialize(File.ReadAllText(appsettings)); + Assert.Equal("dotnet-user-jwts", appSettings["Authentication"]["Schemes"]["Bearer"]["ValidIssuer"].GetValue()); + app.Run(["create", "--project", project, "--issuer", "new-issuer", "--appsettings-file", "appsettings.Local.json"]); + appSettings = JsonSerializer.Deserialize(File.ReadAllText(appsettings)); + Assert.Equal("new-issuer", appSettings["Authentication"]["Schemes"]["Bearer"]["ValidIssuer"].GetValue()); + } + [Fact] public void Print_ReturnsNothingForMissingToken() { @@ -154,6 +171,24 @@ public void Remove_RemovesGeneratedToken() Assert.Contains("Scheme2", appsettingsContent); } + [Fact] + public void Remove_RemovesGeneratedTokenInGivenAppsettings() + { + var project = Path.Combine(fixture.CreateProject(), "TestProject.csproj"); + var appsettings = Path.Combine(Path.GetDirectoryName(project), "appsettings.Local.json"); + var app = new Program(_console); + + app.Run(new[] { "create", "--project", project, "--appsettings-file", "appsettings.Local.json" }); + var matches = Regex.Matches(_console.GetOutput(), "New JWT saved with ID '(.*?)'"); + var id = matches.SingleOrDefault().Groups[1].Value; + app.Run(new[] { "create", "--project", project, "--appsettings-file", "appsettings.Local.json", "--scheme", "Scheme2" }); + + app.Run(new[] { "remove", id, "--project", project, "--appsettings-file", "appsettings.Local.json" }); + var appsettingsContent = File.ReadAllText(appsettings); + Assert.DoesNotContain(DevJwtsDefaults.Scheme, appsettingsContent); + Assert.Contains("Scheme2", appsettingsContent); + } + [Fact] public void Clear_RemovesGeneratedTokens() { @@ -172,6 +207,24 @@ public void Clear_RemovesGeneratedTokens() Assert.DoesNotContain("Scheme2", appsettingsContent); } + [Fact] + public void Clear_RemovesGeneratedTokensInGivenAppsettings() + { + var project = Path.Combine(fixture.CreateProject(), "TestProject.csproj"); + var appsettings = Path.Combine(Path.GetDirectoryName(project), "appsettings.Local.json"); + var app = new Program(_console); + + app.Run(new[] { "create", "--project", project, "--appsettings-file", "appsettings.Local.json" }); + app.Run(new[] { "create", "--project", project, "--appsettings-file", "appsettings.Local.json", "--scheme", "Scheme2" }); + + Assert.Contains("New JWT saved", _console.GetOutput()); + + app.Run(new[] { "clear", "--project", project, "--appsettings-file", "appsettings.Local.json", "--force" }); + var appsettingsContent = File.ReadAllText(appsettings); + Assert.DoesNotContain(DevJwtsDefaults.Scheme, appsettingsContent); + Assert.DoesNotContain("Scheme2", appsettingsContent); + } + [Fact] public void Key_CanResetSigningKey() { @@ -625,6 +678,18 @@ public void Create_CanHandleNoProjectOptionProvided_WithNoProjects() Assert.DoesNotContain(Resources.CreateCommand_NoAudience_Error, _console.GetOutput()); } + [Fact] + public void Create_CanHandleAppsettingsOption_WithNoFile() + { + var projectPath = fixture.CreateProject(); + Directory.SetCurrentDirectory(projectPath); + + var app = new Program(_console); + app.Run(["create", "--appsettings-file", "appsettings.DoesNotExist.json"]); + + Assert.Contains($"Could not find Appsettings file in '{Directory.GetCurrentDirectory()}'. Check the filename and that the file exists.", _console.GetOutput()); + } + [Fact] public void Delete_CanHandleNoProjectOptionProvided_WithNoProjects() { @@ -637,6 +702,18 @@ public void Delete_CanHandleNoProjectOptionProvided_WithNoProjects() Assert.Contains($"Could not find a MSBuild project file in '{Directory.GetCurrentDirectory()}'. Specify which project to use with the --project option.", _console.GetOutput()); } + [Fact] + public void Delete_CanHandleAppsettingsOption_WithNoFile() + { + var projectPath = fixture.CreateProject(); + Directory.SetCurrentDirectory(projectPath); + + var app = new Program(_console); + app.Run(["remove", "some-id", "--appsettings-file", "appsettings.DoesNotExist.json"]); + + Assert.Contains($"Could not find Appsettings file in '{Directory.GetCurrentDirectory()}'. Check the filename and that the file exists.", _console.GetOutput()); + } + [Fact] public void Clear_CanHandleNoProjectOptionProvided_WithNoProjects() { @@ -649,6 +726,18 @@ public void Clear_CanHandleNoProjectOptionProvided_WithNoProjects() Assert.Contains($"Could not find a MSBuild project file in '{Directory.GetCurrentDirectory()}'. Specify which project to use with the --project option.", _console.GetOutput()); } + [Fact] + public void Clear_CanHandleAppsettingsOption_WithNoFile() + { + var projectPath = fixture.CreateProject(); + Directory.SetCurrentDirectory(projectPath); + + var app = new Program(_console); + app.Run(["clear", "--appsettings-file", "appsettings.DoesNotExist.json"]); + + Assert.Contains($"Could not find Appsettings file in '{Directory.GetCurrentDirectory()}'. Check the filename and that the file exists.", _console.GetOutput()); + } + [Fact] public void List_CanHandleNoProjectOptionProvided_WithNoProjects() { @@ -704,6 +793,21 @@ public void Create_CanHandleRelativePathAsOption() Assert.Contains("New JWT saved", _console.GetOutput()); } + [Fact] + public void Create_CanHandleRelativePathAsOptionForAppsettingsOption() + { + var projectPath = fixture.CreateProject(); + var tempPath = Path.GetTempPath(); + var targetPath = Path.GetRelativePath(tempPath, projectPath); + Directory.SetCurrentDirectory(tempPath); + + var app = new Program(_console); + app.Run(new[] { "create", "--project", targetPath, "--appsettings-file", "appsettings.Local.json" }); + + Assert.DoesNotContain($"Could not find Appsettings file in '{projectPath}'. Check the filename and that the file exists.", _console.GetOutput()); + Assert.Contains("New JWT saved", _console.GetOutput()); + } + [ConditionalFact] [OSSkipCondition(OperatingSystems.Windows, SkipReason = "UnixFileMode is not supported on Windows.")] public void Create_CreatesFileWithUserOnlyUnixFileMode() From 4af9a4b7613c0aeffeceedbf058a6ae022001ecd Mon Sep 17 00:00:00 2001 From: Chris <362037+ChrisAnn@users.noreply.github.com> Date: Tue, 17 Dec 2024 16:04:52 +0000 Subject: [PATCH 2/4] Move the validation logic into a central location --- .../src/Commands/ClearCommand.cs | 15 ++---------- .../src/Commands/CreateCommand.cs | 20 ++++------------ .../src/Commands/RemoveCommand.cs | 15 ++---------- .../src/Helpers/DevJwtCliHelpers.cs | 24 +++++++++++++++++++ 4 files changed, 32 insertions(+), 42 deletions(-) diff --git a/src/Tools/dotnet-user-jwts/src/Commands/ClearCommand.cs b/src/Tools/dotnet-user-jwts/src/Commands/ClearCommand.cs index 97d91cf74a4f..531b45b6f11e 100644 --- a/src/Tools/dotnet-user-jwts/src/Commands/ClearCommand.cs +++ b/src/Tools/dotnet-user-jwts/src/Commands/ClearCommand.cs @@ -33,20 +33,9 @@ public static void Register(ProjectCommandLineApplication app) return 1; } - var appsettingsFile = "appsettings.Development.json"; - if (appsettingsFileOption.HasValue()) + if (!DevJwtCliHelpers.GetAppSettingsFile(project, appsettingsFileOption.Value(), cmd.Reporter, out var appsettingsFile)) { - appsettingsFile = appsettingsFileOption.Value(); - if (!appsettingsFile.EndsWith(".json", StringComparison.OrdinalIgnoreCase)) - { - cmd.Reporter.Error(Resources.RemoveCommand_InvalidAppsettingsFile_Error); - return 1; - } - else if (!File.Exists(Path.Combine(Path.GetDirectoryName(project), appsettingsFile))) - { - cmd.Reporter.Error(Resources.FormatRemoveCommand_AppsettingsFileNotFound_Error(Path.GetDirectoryName(project))); - return 1; - } + return 1; } return Execute(cmd.Reporter, project, userSecretsId, forceOption.HasValue(), appsettingsFile); diff --git a/src/Tools/dotnet-user-jwts/src/Commands/CreateCommand.cs b/src/Tools/dotnet-user-jwts/src/Commands/CreateCommand.cs index 1baac76fa888..58f3969bab76 100644 --- a/src/Tools/dotnet-user-jwts/src/Commands/CreateCommand.cs +++ b/src/Tools/dotnet-user-jwts/src/Commands/CreateCommand.cs @@ -216,24 +216,12 @@ private static (JwtCreatorOptions, bool, string, string) ValidateArguments( optionsString += $"{Resources.JwtPrint_CustomClaims}: [{string.Join(", ", claims.Select(kvp => $"{kvp.Key}={kvp.Value}"))}]{Environment.NewLine}"; } - var appsettingsFile = "appsettings.Development.json"; + var appsettingsFile = DevJwtCliHelpers.DefaultAppSettingsFile; if (appsettingsFileOption.HasValue()) { - appsettingsFile = appsettingsFileOption.Value(); - if (!appsettingsFile.EndsWith(".json", StringComparison.OrdinalIgnoreCase)) - { - reporter.Error(Resources.CreateCommand_InvalidAppsettingsFile_Error); - isValid = false; - } - else if (!File.Exists(Path.Combine(Path.GetDirectoryName(project), appsettingsFile))) - { - reporter.Error(Resources.FormatCreateCommand_AppsettingsFileNotFound_Error(Path.GetDirectoryName(project))); - isValid = false; - } - else - { - optionsString += appsettingsFileOption.HasValue() ? $"{Resources.JwtPrint_appsettingsFile}: {appsettingsFile}{Environment.NewLine}" : string.Empty; - } + isValid = DevJwtCliHelpers.GetAppSettingsFile(project, appsettingsFileOption.Value(), reporter, out appsettingsFile); + + optionsString += appsettingsFileOption.HasValue() ? $"{Resources.JwtPrint_appsettingsFile}: {appsettingsFile}{Environment.NewLine}" : string.Empty; } return ( diff --git a/src/Tools/dotnet-user-jwts/src/Commands/RemoveCommand.cs b/src/Tools/dotnet-user-jwts/src/Commands/RemoveCommand.cs index 27c2fdad1a42..9260a70b1219 100644 --- a/src/Tools/dotnet-user-jwts/src/Commands/RemoveCommand.cs +++ b/src/Tools/dotnet-user-jwts/src/Commands/RemoveCommand.cs @@ -36,20 +36,9 @@ public static void Register(ProjectCommandLineApplication app) return 1; } - var appsettingsFile = "appsettings.Development.json"; - if (appsettingsFileOption.HasValue()) + if (!DevJwtCliHelpers.GetAppSettingsFile(project, appsettingsFileOption.Value(), cmd.Reporter, out var appsettingsFile)) { - appsettingsFile = appsettingsFileOption.Value(); - if (!appsettingsFile.EndsWith(".json", StringComparison.OrdinalIgnoreCase)) - { - cmd.Reporter.Error(Resources.RemoveCommand_InvalidAppsettingsFile_Error); - return 1; - } - else if (!File.Exists(Path.Combine(Path.GetDirectoryName(project), appsettingsFile))) - { - cmd.Reporter.Error(Resources.FormatRemoveCommand_AppsettingsFileNotFound_Error(Path.GetDirectoryName(project))); - return 1; - } + return 1; } return Execute(cmd.Reporter, project, userSecretsId, idArgument.Value, appsettingsFile); diff --git a/src/Tools/dotnet-user-jwts/src/Helpers/DevJwtCliHelpers.cs b/src/Tools/dotnet-user-jwts/src/Helpers/DevJwtCliHelpers.cs index 2d12b67f55a4..d1df17035bb7 100644 --- a/src/Tools/dotnet-user-jwts/src/Helpers/DevJwtCliHelpers.cs +++ b/src/Tools/dotnet-user-jwts/src/Helpers/DevJwtCliHelpers.cs @@ -11,6 +11,8 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer.Tools; internal static class DevJwtCliHelpers { + public const string DefaultAppSettingsFile = "appsettings.Development.json"; + public static string GetOrSetUserSecretsId(string projectFilePath) { var resolver = new ProjectIdResolver(NullReporter.Singleton, projectFilePath); @@ -42,6 +44,27 @@ public static bool GetProjectAndSecretsId(string projectPath, IReporter reporter return true; } + public static bool GetAppSettingsFile(string projectPath, string appsettingsFileOption, IReporter reporter, out string appsettingsFile) + { + appsettingsFile = DevJwtCliHelpers.DefaultAppSettingsFile; + if (appsettingsFileOption is not null) + { + appsettingsFile = appsettingsFileOption; + if (!appsettingsFile.EndsWith(".json", StringComparison.OrdinalIgnoreCase)) + { + reporter.Error(Resources.RemoveCommand_InvalidAppsettingsFile_Error); + return false; + } + else if (!File.Exists(Path.Combine(Path.GetDirectoryName(projectPath), appsettingsFile))) + { + reporter.Error(Resources.FormatRemoveCommand_AppsettingsFileNotFound_Error(Path.GetDirectoryName(projectPath))); + return false; + } + } + + return true; + } + public static List GetAudienceCandidatesFromLaunchSettings(string project) { if (string.IsNullOrEmpty(project)) @@ -213,4 +236,5 @@ public static bool IsNullOrEmpty(this IEnumerable enumerable) { return enumerable == null || !enumerable.Any(); } + } From 26a71e3a5b66b3cac2c417d0b74e43ab8bcd87db Mon Sep 17 00:00:00 2001 From: Chris <362037+ChrisAnn@users.noreply.github.com> Date: Wed, 18 Dec 2024 09:17:29 +0000 Subject: [PATCH 3/4] Adds copilot suggestions to improve error messages --- src/Tools/dotnet-user-jwts/src/Helpers/DevJwtCliHelpers.cs | 2 +- src/Tools/dotnet-user-jwts/src/Resources.resx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Tools/dotnet-user-jwts/src/Helpers/DevJwtCliHelpers.cs b/src/Tools/dotnet-user-jwts/src/Helpers/DevJwtCliHelpers.cs index d1df17035bb7..38735fb5231f 100644 --- a/src/Tools/dotnet-user-jwts/src/Helpers/DevJwtCliHelpers.cs +++ b/src/Tools/dotnet-user-jwts/src/Helpers/DevJwtCliHelpers.cs @@ -57,7 +57,7 @@ public static bool GetAppSettingsFile(string projectPath, string appsettingsFile } else if (!File.Exists(Path.Combine(Path.GetDirectoryName(projectPath), appsettingsFile))) { - reporter.Error(Resources.FormatRemoveCommand_AppsettingsFileNotFound_Error(Path.GetDirectoryName(projectPath))); + reporter.Error(Resources.FormatRemoveCommand_AppsettingsFileNotFound_Error(Path.Combine(Path.GetDirectoryName(projectPath), appsettingsFile))); return false; } } diff --git a/src/Tools/dotnet-user-jwts/src/Resources.resx b/src/Tools/dotnet-user-jwts/src/Resources.resx index 64b475f88309..9f4ff3c041ac 100644 --- a/src/Tools/dotnet-user-jwts/src/Resources.resx +++ b/src/Tools/dotnet-user-jwts/src/Resources.resx @@ -325,10 +325,10 @@ No JWT with ID '{0}' found. - Invalid Appsettings file extension. Ensure file extension is .json. + The specified appsettings file is invalid. Please provide a valid JSON file. - Could not find Appsettings file in '{0}'. Check the filename and that the file exists. + Could not find Appsettings file '{0}'. Check the filename and that the file exists. The issuer associated with the signing key to be reset or displayed. Defaults to 'dotnet-user-jwts'. From 1f60a9e0a8e5140c26351a3fbe8802549f221c05 Mon Sep 17 00:00:00 2001 From: Chris <362037+ChrisAnn@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:38:17 +0000 Subject: [PATCH 4/4] Fix tests after changing error message when appsettings not found --- src/Tools/dotnet-user-jwts/test/UserJwtsTests.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Tools/dotnet-user-jwts/test/UserJwtsTests.cs b/src/Tools/dotnet-user-jwts/test/UserJwtsTests.cs index b37355d79408..c8ad90b61a8e 100644 --- a/src/Tools/dotnet-user-jwts/test/UserJwtsTests.cs +++ b/src/Tools/dotnet-user-jwts/test/UserJwtsTests.cs @@ -683,11 +683,12 @@ public void Create_CanHandleAppsettingsOption_WithNoFile() { var projectPath = fixture.CreateProject(); Directory.SetCurrentDirectory(projectPath); + var expectedAppsettingsPath = Path.Combine(Directory.GetCurrentDirectory(), "appsettings.DoesNotExist.json"); var app = new Program(_console); app.Run(["create", "--appsettings-file", "appsettings.DoesNotExist.json"]); - Assert.Contains($"Could not find Appsettings file in '{Directory.GetCurrentDirectory()}'. Check the filename and that the file exists.", _console.GetOutput()); + Assert.Contains($"Could not find Appsettings file '{expectedAppsettingsPath}'. Check the filename and that the file exists.", _console.GetOutput()); } [Fact] @@ -707,11 +708,12 @@ public void Delete_CanHandleAppsettingsOption_WithNoFile() { var projectPath = fixture.CreateProject(); Directory.SetCurrentDirectory(projectPath); + var expectedAppsettingsPath = Path.Combine(Directory.GetCurrentDirectory(), "appsettings.DoesNotExist.json"); var app = new Program(_console); app.Run(["remove", "some-id", "--appsettings-file", "appsettings.DoesNotExist.json"]); - Assert.Contains($"Could not find Appsettings file in '{Directory.GetCurrentDirectory()}'. Check the filename and that the file exists.", _console.GetOutput()); + Assert.Contains($"Could not find Appsettings file '{expectedAppsettingsPath}'. Check the filename and that the file exists.", _console.GetOutput()); } [Fact] @@ -731,11 +733,12 @@ public void Clear_CanHandleAppsettingsOption_WithNoFile() { var projectPath = fixture.CreateProject(); Directory.SetCurrentDirectory(projectPath); + var expectedAppsettingsPath = Path.Combine(Directory.GetCurrentDirectory(), "appsettings.DoesNotExist.json"); var app = new Program(_console); app.Run(["clear", "--appsettings-file", "appsettings.DoesNotExist.json"]); - Assert.Contains($"Could not find Appsettings file in '{Directory.GetCurrentDirectory()}'. Check the filename and that the file exists.", _console.GetOutput()); + Assert.Contains($"Could not find Appsettings file '{expectedAppsettingsPath}'. Check the filename and that the file exists.", _console.GetOutput()); } [Fact] @@ -804,7 +807,7 @@ public void Create_CanHandleRelativePathAsOptionForAppsettingsOption() var app = new Program(_console); app.Run(new[] { "create", "--project", targetPath, "--appsettings-file", "appsettings.Local.json" }); - Assert.DoesNotContain($"Could not find Appsettings file in '{projectPath}'. Check the filename and that the file exists.", _console.GetOutput()); + Assert.DoesNotContain($"Could not find Appsettings file '{projectPath}'. Check the filename and that the file exists.", _console.GetOutput()); Assert.Contains("New JWT saved", _console.GetOutput()); }