Skip to content

Commit 1380236

Browse files
authored
Fix up project search scenarios when no option is provided (#42860)
* Fix up project search scenarios when no option is provided * Clean up tests and react to feedback
1 parent 3c22e6e commit 1380236

File tree

4 files changed

+115
-32
lines changed

4 files changed

+115
-32
lines changed

src/Tools/dotnet-user-jwts/src/Commands/CreateCommand.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System.Globalization;
55
using System.Linq;
6-
using System.Text;
76
using System.Text.Json;
87
using Microsoft.Extensions.CommandLineUtils;
98
using Microsoft.Extensions.Tools.Internal;
@@ -117,6 +116,19 @@ private static (JwtCreatorOptions, bool, string) ValidateArguments(
117116
var isValid = true;
118117
var project = DevJwtCliHelpers.GetProject(projectOption.Value());
119118

119+
if (project == null)
120+
{
121+
reporter.Error(Resources.ProjectOption_ProjectNotFound);
122+
isValid = false;
123+
// Break out early if we haven't been able to resolve a project
124+
// since we depend on it for the managing of JWT tokens
125+
return (
126+
null,
127+
isValid,
128+
string.Empty
129+
);
130+
}
131+
120132
var scheme = schemeNameOption.HasValue() ? schemeNameOption.Value() : "Bearer";
121133
var optionsString = schemeNameOption.HasValue() ? $"{Resources.JwtPrint_Scheme}: {scheme}{Environment.NewLine}" : string.Empty;
122134

src/Tools/dotnet-user-jwts/src/Helpers/DevJwtCliHelpers.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ public static bool GetProjectAndSecretsId(string projectPath, IReporter reporter
4848
userSecretsId = null;
4949
if (project == null)
5050
{
51-
reporter.Error($"No project found at `-p|--project` path or current directory.");
51+
reporter.Error(Resources.ProjectOption_ProjectNotFound);
5252
return false;
5353
}
5454

5555
userSecretsId = GetOrSetUserSecretsId(project);
5656
if (userSecretsId == null)
5757
{
58-
reporter.Error($"Project does not contain a user secrets ID.");
58+
reporter.Error(Resources.ProjectOption_SercretIdNotFound);
5959
return false;
6060
}
6161
return true;
@@ -112,7 +112,10 @@ public static byte[] CreateSigningKeyMaterial(string userSecretsId, string schem
112112

113113
public static List<string> GetAudienceCandidatesFromLaunchSettings(string project)
114114
{
115-
ArgumentException.ThrowIfNullOrEmpty(nameof(project));
115+
if (string.IsNullOrEmpty(project))
116+
{
117+
return new List<string>();
118+
}
116119

117120
var launchSettingsFilePath = Path.Combine(Path.GetDirectoryName(project)!, "Properties", "launchSettings.json");
118121
var applicationUrls = new HashSet<string>();

src/Tools/dotnet-user-jwts/src/Resources.resx

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<root>
3-
<!--
4-
Microsoft ResX Schema
5-
3+
<!--
4+
Microsoft ResX Schema
5+
66
Version 2.0
7-
8-
The primary goals of this format is to allow a simple XML format
9-
that is mostly human readable. The generation and parsing of the
10-
various data types are done through the TypeConverter classes
7+
8+
The primary goals of this format is to allow a simple XML format
9+
that is mostly human readable. The generation and parsing of the
10+
various data types are done through the TypeConverter classes
1111
associated with the data types.
12-
12+
1313
Example:
14-
14+
1515
... ado.net/XML headers & schema ...
1616
<resheader name="resmimetype">text/microsoft-resx</resheader>
1717
<resheader name="version">2.0</resheader>
@@ -26,36 +26,36 @@
2626
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
2727
<comment>This is a comment</comment>
2828
</data>
29-
30-
There are any number of "resheader" rows that contain simple
29+
30+
There are any number of "resheader" rows that contain simple
3131
name/value pairs.
32-
33-
Each data row contains a name, and value. The row also contains a
34-
type or mimetype. Type corresponds to a .NET class that support
35-
text/value conversion through the TypeConverter architecture.
36-
Classes that don't support this are serialized and stored with the
32+
33+
Each data row contains a name, and value. The row also contains a
34+
type or mimetype. Type corresponds to a .NET class that support
35+
text/value conversion through the TypeConverter architecture.
36+
Classes that don't support this are serialized and stored with the
3737
mimetype set.
38-
39-
The mimetype is used for serialized objects, and tells the
40-
ResXResourceReader how to depersist the object. This is currently not
38+
39+
The mimetype is used for serialized objects, and tells the
40+
ResXResourceReader how to depersist the object. This is currently not
4141
extensible. For a given mimetype the value must be set accordingly:
42-
43-
Note - application/x-microsoft.net.object.binary.base64 is the format
44-
that the ResXResourceWriter will generate, however the reader can
42+
43+
Note - application/x-microsoft.net.object.binary.base64 is the format
44+
that the ResXResourceWriter will generate, however the reader can
4545
read any of the formats listed below.
46-
46+
4747
mimetype: application/x-microsoft.net.object.binary.base64
48-
value : The object must be serialized with
48+
value : The object must be serialized with
4949
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
5050
: and then encoded with base64 encoding.
51-
51+
5252
mimetype: application/x-microsoft.net.object.soap.base64
53-
value : The object must be serialized with
53+
value : The object must be serialized with
5454
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
5555
: and then encoded with base64 encoding.
5656
5757
mimetype: application/x-microsoft.net.object.bytearray.base64
58-
value : The object must be serialized into a byte array
58+
value : The object must be serialized into a byte array
5959
: using a System.ComponentModel.TypeConverter
6060
: and then encoded with base64 encoding.
6161
-->
@@ -294,6 +294,12 @@
294294
<data name="PrintCommand_ShowAllOption_Description" xml:space="preserve">
295295
<value>Whether to show all details associated with the JWT.</value>
296296
</data>
297+
<data name="ProjectOption_ProjectNotFound" xml:space="preserve">
298+
<value>No project found at `-p|--project` path or current directory.</value>
299+
</data>
300+
<data name="ProjectOption_SercretIdNotFound" xml:space="preserve">
301+
<value>Project does not contain a user secrets ID.</value>
302+
</data>
297303
<data name="ProjectOption_Description" xml:space="preserve">
298304
<value>The path of the project to operate on. Defaults to the project in the current directory.</value>
299305
</data>
@@ -309,4 +315,4 @@
309315
<data name="RemoveCommand_NoJwtFound" xml:space="preserve">
310316
<value>No JWT with ID '{0}' found.</value>
311317
</data>
312-
</root>
318+
</root>

src/Tools/dotnet-user-jwts/test/UserJwtsTests.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,4 +480,66 @@ public void Key_CanPrintAndReset_BySchemeAndIssuer()
480480
var resetKey = resetMatches.SingleOrDefault().Groups[1].Value;
481481
Assert.NotEqual(key, resetKey);
482482
}
483+
484+
[Fact]
485+
public void Create_CanHandleNoProjectOptionProvided()
486+
{
487+
var projectPath = _fixture.CreateProject();
488+
Directory.SetCurrentDirectory(projectPath);
489+
490+
var app = new Program(_console);
491+
app.Run(new[] { "create" });
492+
493+
Assert.DoesNotContain("No project found at `-p|--project` path or current directory.", _console.GetOutput());
494+
Assert.Contains("New JWT saved", _console.GetOutput());
495+
}
496+
497+
[Fact]
498+
public void Create_CanHandleNoProjectOptionProvided_WithNoProjects()
499+
{
500+
var path = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "userjwtstest"));
501+
Directory.SetCurrentDirectory(path.FullName);
502+
503+
var app = new Program(_console);
504+
app.Run(new[] { "create" });
505+
506+
Assert.Contains("No project found at `-p|--project` path or current directory.", _console.GetOutput());
507+
Assert.DoesNotContain(Resources.CreateCommand_NoAudience_Error, _console.GetOutput());
508+
}
509+
510+
[Fact]
511+
public void Delete_CanHandleNoProjectOptionProvided_WithNoProjects()
512+
{
513+
var path = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "userjwtstest"));
514+
Directory.SetCurrentDirectory(path.FullName);
515+
516+
var app = new Program(_console);
517+
app.Run(new[] { "remove", "some-id" });
518+
519+
Assert.Contains("No project found at `-p|--project` path or current directory.", _console.GetOutput());
520+
}
521+
522+
[Fact]
523+
public void Clear_CanHandleNoProjectOptionProvided_WithNoProjects()
524+
{
525+
var path = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "userjwtstest"));
526+
Directory.SetCurrentDirectory(path.FullName);
527+
528+
var app = new Program(_console);
529+
app.Run(new[] { "clear" });
530+
531+
Assert.Contains("No project found at `-p|--project` path or current directory.", _console.GetOutput());
532+
}
533+
534+
[Fact]
535+
public void List_CanHandleNoProjectOptionProvided_WithNoProjects()
536+
{
537+
var path = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), "userjwtstest"));
538+
Directory.SetCurrentDirectory(path.FullName);
539+
540+
var app = new Program(_console);
541+
app.Run(new[] { "list" });
542+
543+
Assert.Contains("No project found at `-p|--project` path or current directory.", _console.GetOutput());
544+
}
483545
}

0 commit comments

Comments
 (0)