Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
<PackageVersion Include="OpenIddict.AspNetCore" Version="7.7.2" />
<PackageVersion Include="Shared" Version="2026.10.4" />
<PackageVersion Include="Shared.Results.Web" Version="2026.10.4" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.3.1" />
<PackageVersion Include="Sentry.AspNetCore" Version="6.12.1" />
<PackageVersion Include="NLog.Web.AspNetCore" Version="6.2.2" />
<PackageVersion Include="HtmlAgilityPack" Version="1.13.1" />
Expand Down
49 changes: 49 additions & 0 deletions SecurityService.DataTransferObjects/Requests.cs
Original file line number Diff line number Diff line change
@@ -1,93 +1,142 @@
namespace SecurityService.DataTransferObjects;

/// <summary>Configuration for registering an OAuth/OIDC client.</summary>
/// <example>{"clientId":"orders-web","secret":"replace-with-a-secret","clientName":"Orders web app","allowedScopes":["openid","profile","orders.read"],"allowedGrantTypes":["authorization_code","refresh_token"],"clientUri":"https://orders.example.com","clientRedirectUris":["https://orders.example.com/signin-oidc"],"clientPostLogoutRedirectUris":["https://orders.example.com/signed-out"],"requireConsent":true,"allowOfflineAccess":true}</example>
public sealed class CreateClientRequest
{
/// <summary>Unique identifier sent as the OAuth <c>client_id</c>.</summary>
public string ClientId { get; set; } = string.Empty;

/// <summary>Shared secret for a confidential client. Omit for a public client; never returned by read endpoints.</summary>
public string? Secret { get; set; }

/// <summary>Human-readable client name shown on consent and management screens.</summary>
public string ClientName { get; set; } = string.Empty;

/// <summary>Optional administrative description of this client.</summary>
public string? ClientDescription { get; set; }

/// <summary>OAuth scopes this client is permitted to request, such as <c>openid</c> and <c>orders.read</c>.</summary>
public List<string> AllowedScopes { get; set; } = new();

/// <summary>OAuth grant types this client may use, such as <c>authorization_code</c>, <c>refresh_token</c>, or <c>client_credentials</c>.</summary>
public List<string> AllowedGrantTypes { get; set; } = new();

/// <summary>Optional homepage URI for the client application.</summary>
public string? ClientUri { get; set; }

/// <summary>Exact OAuth callback URIs allowed for authorization responses.</summary>
public List<string> ClientRedirectUris { get; set; } = new();

/// <summary>Exact URIs allowed after an OIDC logout completes.</summary>
public List<string> ClientPostLogoutRedirectUris { get; set; } = new();

/// <summary>Whether the user must approve requested scopes through a consent screen.</summary>
public bool RequireConsent { get; set; }

/// <summary>Whether the client may request offline access and receive refresh tokens when supported by its grant.</summary>
public bool AllowOfflineAccess { get; set; }
}

/// <summary>Definition of a permission scope exposed by a protected API.</summary>
/// <example>{"name":"orders.read","displayName":"Read orders","description":"View orders belonging to the signed-in user."}</example>
public sealed class CreateApiScopeRequest
{
/// <summary>Unique scope name requested by OAuth clients, for example <c>orders.read</c>.</summary>
public string Name { get; set; } = string.Empty;

/// <summary>Optional human-readable name shown in consent and documentation.</summary>
public string? DisplayName { get; set; }

/// <summary>Optional explanation of the access granted by this scope.</summary>
public string? Description { get; set; }
}

/// <summary>Definition of a protected API resource, its scopes, and the user claims it can receive.</summary>
/// <example>{"name":"orders-api","displayName":"Orders API","description":"Order management service","secret":"replace-with-a-secret","scopes":["orders.read"],"userClaims":["sub","email"]}</example>
public sealed class CreateApiResourceRequest
{
/// <summary>Unique audience/resource name used to identify this API.</summary>
public string Name { get; set; } = string.Empty;

/// <summary>Optional human-readable API name.</summary>
public string? DisplayName { get; set; }

/// <summary>Optional description of the API resource.</summary>
public string? Description { get; set; }

/// <summary>Optional shared secret used by the resource server for applicable token validation flows.</summary>
public string? Secret { get; set; }

/// <summary>Scope names that grant access to this resource.</summary>
public List<string> Scopes { get; set; } = new();

/// <summary>User claim names that may be included in tokens issued for this resource.</summary>
public List<string> UserClaims { get; set; } = new();
}

/// <summary>Definition of an OIDC identity resource and the claims it exposes.</summary>
/// <example>{"name":"profile","displayName":"Profile","description":"Basic profile claims","required":false,"emphasize":false,"showInDiscoveryDocument":true,"claims":["name","given_name","family_name"]}</example>
public sealed class CreateIdentityResourceRequest
{
/// <summary>Unique identity scope/resource name, such as <c>profile</c> or <c>email</c>.</summary>
public string Name { get; set; } = string.Empty;
/// <summary>Optional human-readable name shown to the user.</summary>
public string? DisplayName { get; set; }

/// <summary>Optional explanation of the identity data represented by this resource.</summary>
public string? Description { get; set; }

/// <summary>Whether requesting clients must request this resource to complete authentication.</summary>
public bool Required { get; set; }

/// <summary>Whether this resource should be highlighted on the consent screen.</summary>
public bool Emphasize { get; set; }

/// <summary>Whether this resource is listed in the OIDC discovery document. Defaults to <see langword="true"/>.</summary>
public bool ShowInDiscoveryDocument { get; set; } = true;

/// <summary>Claim names provided when this identity resource is granted, such as <c>name</c> or <c>email</c>.</summary>
public List<string> Claims { get; set; } = new();
}

/// <summary>Role name to create.</summary>
/// <example>{"roleName":"OrderManager"}</example>
public sealed class CreateRoleRequest
{
/// <summary>Unique role name to create.</summary>
public string RoleName { get; set; } = string.Empty;
}

/// <summary>Account details, credentials, and optional authorization data for a new user.</summary>
/// <example>{"givenName":"Avery","familyName":"Nguyen","userName":"avery.nguyen","password":"replace-with-a-policy-compliant-password","emailAddress":"avery@example.com","phoneNumber":"+15550102020","claims":{"department":"sales"},"roles":["OrderManager"]}</example>
public sealed class CreateUserRequest
{
/// <summary>Optional given/first name.</summary>
public string? GivenName { get; set; }

/// <summary>Optional middle name.</summary>
public string? MiddleName { get; set; }

/// <summary>Optional family/last name.</summary>
public string? FamilyName { get; set; }

/// <summary>Unique sign-in name for the account.</summary>
public string UserName { get; set; } = string.Empty;

/// <summary>Initial password; must satisfy the service's configured identity password policy.</summary>
public string Password { get; set; } = string.Empty;

/// <summary>Optional email address. Confirmation requirements depend on service configuration.</summary>
public string? EmailAddress { get; set; }

/// <summary>Optional phone number, preferably in international format.</summary>
public string? PhoneNumber { get; set; }

/// <summary>Additional string claims to assign, represented as claim-name/value pairs.</summary>
public Dictionary<string, string> Claims { get; set; } = new();

/// <summary>Names of existing roles to assign to this user.</summary>
public List<string> Roles { get; set; } = new();
}

59 changes: 58 additions & 1 deletion SecurityService.DataTransferObjects/Responses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,120 +3,177 @@

namespace SecurityService.DataTransferObjects;

/// <summary>Public description of a protected API resource. Secrets are intentionally excluded.</summary>
/// <example>{"name":"orders-api","displayName":"Orders API","description":"Order management service","scopes":["orders.read"],"userClaims":["sub","email"]}</example>
public sealed class ApiResourceResponse {
/// <summary>Unique API resource/audience name.</summary>
public string Name { get; set; }

Check warning on line 10 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'Name' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 10 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'Name' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>Optional human-readable API name.</summary>
public string? DisplayName { get; set; }

/// <summary>Optional description of the API.</summary>
public string? Description { get; set; }

/// <summary>Scopes associated with this API.</summary>
public IReadOnlyCollection<string> Scopes { get; set; }

Check warning on line 19 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'Scopes' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 19 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'Scopes' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>User claim names that may be included in tokens for this API.</summary>
public IReadOnlyCollection<string> UserClaims { get; set; }

Check warning on line 22 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'UserClaims' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 22 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'UserClaims' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.
}

/// <summary>Public description of an API scope.</summary>
/// <example>{"name":"orders.read","displayName":"Read orders","description":"View orders belonging to the signed-in user."}</example>
public sealed record ApiScopeResponse {
/// <summary>Unique scope name used in OAuth requests.</summary>
public string Name { get; set; }

Check warning on line 29 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'Name' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>Optional human-readable scope name.</summary>
public string? DisplayName { get; set; }

/// <summary>Optional explanation of the permission.</summary>
public string? Description { get; set; }
}

/// <summary>Public client registration details. The client secret is never returned.</summary>
/// <example>{"clientId":"orders-web","clientName":"Orders web app","description":"Customer order portal","clientUri":"https://orders.example.com","allowedScopes":["openid","profile","orders.read"],"allowedGrantTypes":["authorization_code","refresh_token"],"clientRedirectUris":["https://orders.example.com/signin-oidc"],"clientPostLogoutRedirectUris":["https://orders.example.com/signed-out"],"requireConsent":true,"allowOfflineAccess":true,"clientType":"confidential"}</example>
public sealed record ClientResponse {
/// <summary>OAuth client identifier.</summary>
public string ClientId { get; set; }

Check warning on line 42 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'ClientId' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 42 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'ClientId' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>Human-readable client name.</summary>
public string ClientName { get; set; }

Check warning on line 45 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'ClientName' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 45 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'ClientName' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>Optional administrative description.</summary>
public string? Description { get; set; }

/// <summary>Optional homepage URI.</summary>
public string? ClientUri { get; set; }

/// <summary>Scopes the client is permitted to request.</summary>
public IReadOnlyCollection<string> AllowedScopes { get; set; }

Check warning on line 54 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'AllowedScopes' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 54 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'AllowedScopes' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>OAuth grant types permitted for the client.</summary>
public IReadOnlyCollection<string> AllowedGrantTypes { get; set; }

Check warning on line 57 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'AllowedGrantTypes' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 57 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'AllowedGrantTypes' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>Registered authorization callback URIs.</summary>
public IReadOnlyCollection<string> ClientRedirectUris { get; set; }

Check warning on line 60 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'ClientRedirectUris' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 60 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'ClientRedirectUris' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>Registered post-logout callback URIs.</summary>
public IReadOnlyCollection<string> ClientPostLogoutRedirectUris { get; set; }

Check warning on line 63 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'ClientPostLogoutRedirectUris' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>Whether user consent is required for requested scopes.</summary>
public bool RequireConsent { get; set; }

/// <summary>Whether offline access/refresh tokens are permitted.</summary>
public bool AllowOfflineAccess { get; set; }

/// <summary>Configured client classification, such as public or confidential.</summary>
public string ClientType { get; set; }
}

/// <summary>Public description of an OIDC identity resource.</summary>
/// <example>{"name":"profile","displayName":"Profile","description":"Basic profile claims","required":false,"emphasize":false,"showInDiscoveryDocument":true,"claims":["name","given_name","family_name"]}</example>
public sealed record IdentityResourceResponse
{
/// <summary>Unique identity resource name.</summary>
public string Name { get; set; }

Check warning on line 80 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'Name' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>Optional human-readable name.</summary>
public string? DisplayName { get; set; }

/// <summary>Optional explanation of the identity data.</summary>
public string? Description { get; set; }

/// <summary>Whether clients must request this resource.</summary>
public bool Required { get; set; }

/// <summary>Whether this resource is highlighted on consent screens.</summary>
public bool Emphasize { get; set; }

/// <summary>Whether this resource is listed in OIDC discovery.</summary>
public bool ShowInDiscoveryDocument { get; set; }

/// <summary>Claims provided by this resource.</summary>
public IReadOnlyCollection<string> Claims { get; set; }

Check warning on line 98 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'Claims' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.
}


/// <summary>Role identifier and name.</summary>
/// <example>{"roleId":"2f0c1d2e-3456-4789-a123-123456789abc","roleName":"OrderManager"}</example>
public sealed record RoleResponse
{
/// <summary>Identity system's stable role ID.</summary>
public String RoleId { get; set; }
/// <summary>Unique role name.</summary>
public string RoleName { get; set; }
}

/// <summary>User profile and authorization data returned by management endpoints.</summary>
/// <example>{"userId":"7a0c1d2e-3456-4789-a123-123456789abc","userName":"avery.nguyen","emailAddress":"avery@example.com","phoneNumber":"+15550102020","givenName":"Avery","middleName":null,"familyName":"Nguyen","claims":{"department":"sales"},"roles":["OrderManager"],"registrationDateTime":"2026-10-22T10:30:00Z"}</example>
public sealed record UserResponse {
/// <summary>Identity system's stable user ID.</summary>
public String UserId { get; set; }

Check warning on line 116 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'UserId' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 116 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'UserId' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>Sign-in name.</summary>
public string UserName { get; set; }

Check warning on line 119 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'UserName' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 119 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'UserName' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>Optional email address.</summary>
public string? EmailAddress { get; set; }

/// <summary>Optional phone number.</summary>
public string? PhoneNumber { get; set; }

/// <summary>Optional given/first name.</summary>
public string? GivenName { get; set; }

/// <summary>Optional middle name.</summary>
public string? MiddleName { get; set; }

/// <summary>Optional family/last name.</summary>
public string? FamilyName { get; set; }

/// <summary>Additional string claims assigned to the user.</summary>
public IReadOnlyDictionary<string, string> Claims{ get; set; }

Check warning on line 137 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'Claims' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 137 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'Claims' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>Role names assigned to the user.</summary>
public IReadOnlyCollection<string> Roles { get; set; }

Check warning on line 140 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Non-nullable property 'Roles' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

Check warning on line 140 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Non-nullable property 'Roles' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the property as nullable.

/// <summary>UTC date and time when the account was registered.</summary>
public DateTime RegistrationDateTime { get; set; }
}

/// <summary>OAuth token response details with expiry timestamps.</summary>
/// <example>{"accessToken":"eyJ...","expires":"2026-10-22T11:30:00Z","expiresIn":3600,"issued":"2026-10-22T10:30:00Z","refreshToken":"def..."}</example>
public class TokenResponse
{
/// <summary>Bearer access token issued by the authorization server.</summary>
public String AccessToken { get; private set; }
/// <summary>Absolute expiration timestamp for the access token.</summary>
public DateTimeOffset Expires { get; private set; }
/// <summary>Access token lifetime in seconds.</summary>
public Int64 ExpiresIn { get; private set; }
/// <summary>Timestamp when this response was received/issued.</summary>
public DateTimeOffset Issued { get; private set; }
/// <summary>Refresh token when the grant and client are permitted to receive one; otherwise null.</summary>
public String RefreshToken { get; private set; }
public static TokenResponse Create(String token) {
using var doc = JsonDocument.Parse(token);
var root = doc.RootElement;

long expiresIn = root.GetProperty("expires_in").GetInt64();
string accessToken = root.GetProperty("access_token").GetString();

Check warning on line 165 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Converting null literal or possible null value to non-nullable type.

Check warning on line 165 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Converting null literal or possible null value to non-nullable type.

DateTimeOffset issued = DateTimeOffset.Now;
DateTimeOffset expires = issued.AddSeconds(expiresIn);

string refreshToken = null;

Check warning on line 170 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Converting null literal or possible null value to non-nullable type.

Check warning on line 170 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Converting null literal or possible null value to non-nullable type.
if (root.TryGetProperty("refresh_token", out var refreshElement))
{
refreshToken = refreshElement.GetString();

Check warning on line 173 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Converting null literal or possible null value to non-nullable type.

Check warning on line 173 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Converting null literal or possible null value to non-nullable type.
}

return TokenResponse.Create(accessToken, refreshToken, expiresIn, issued, expires);

Check warning on line 176 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Possible null reference argument for parameter 'refreshToken' in 'TokenResponse TokenResponse.Create(string accessToken, string refreshToken, long expiresIn, DateTimeOffset issued = default(DateTimeOffset), DateTimeOffset expires = default(DateTimeOffset))'.

Check warning on line 176 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Chrome UI

Possible null reference argument for parameter 'accessToken' in 'TokenResponse TokenResponse.Create(string accessToken, string refreshToken, long expiresIn, DateTimeOffset issued = default(DateTimeOffset), DateTimeOffset expires = default(DateTimeOffset))'.

Check warning on line 176 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Possible null reference argument for parameter 'refreshToken' in 'TokenResponse TokenResponse.Create(string accessToken, string refreshToken, long expiresIn, DateTimeOffset issued = default(DateTimeOffset), DateTimeOffset expires = default(DateTimeOffset))'.

Check warning on line 176 in SecurityService.DataTransferObjects/Responses.cs

View workflow job for this annotation

GitHub Actions / Build and Unit Test Pull Requests - Edge UI

Possible null reference argument for parameter 'accessToken' in 'TokenResponse TokenResponse.Create(string accessToken, string refreshToken, long expiresIn, DateTimeOffset issued = default(DateTimeOffset), DateTimeOffset expires = default(DateTimeOffset))'.
}

public static TokenResponse Create(String accessToken,
Expand All @@ -140,4 +197,4 @@
this.Issued = issued;
this.Expires = expires;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
<ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public GenericSteps(ScenarioContext scenarioContext,
public async Task StartSystem()
{
// Initialise a logger
String scenarioName = this.ScenarioContext.ScenarioInfo.Title.Replace(" ", "");
String scenarioName = this.ScenarioContext.ScenarioInfo.Title.Replace(" ", String.Empty);
NlogLogger logger = new NlogLogger();
logger.Initialise(LogManager.GetLogger(scenarioName), scenarioName);
LogManager.AddHiddenAssembly(typeof(NlogLogger).Assembly);
Expand Down
10 changes: 8 additions & 2 deletions SecurityService/Endpoints/DeveloperEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ public static class DeveloperEndpoints
{
public static void MapDeveloperEndpoints(this IEndpointRouteBuilder endpoints)
{
endpoints.MapGet("/api/developer/lastemail", Handlers.DeveloperHandler.GetLastEmail).WithName("GetLastEmail");
endpoints.MapGet("/api/developer/lastsms", Handlers.DeveloperHandler.GetLastSms).WithName("GetLastSms");
endpoints.MapGet("/api/developer/lastemail", Handlers.DeveloperHandler.GetLastEmail).WithName("GetLastEmail").WithTags("Developer testing")
.WithSummary("Get the most recent test email")
.WithDescription("Integration-test helper that returns the last email captured by the test messaging client, including recipient, subject, and body. Example: `GET /api/developer/lastemail` returns the captured email request JSON. Only mapped in the IntegrationTest environment. Returns 404 when no test email has been captured or the test client is unavailable.")
.Produces<MessagingService.DataTransferObjects.SendEmailRequest>().Produces(404);
endpoints.MapGet("/api/developer/lastsms", Handlers.DeveloperHandler.GetLastSms).WithName("GetLastSms").WithTags("Developer testing")
.WithSummary("Get the most recent test SMS")
.WithDescription("Integration-test helper that returns the last SMS captured by the test messaging client, including recipient and message body. Example: `GET /api/developer/lastsms` returns the captured SMS request JSON. Only mapped in the IntegrationTest environment. Returns 404 when no test SMS has been captured or the test client is unavailable.")
.Produces<MessagingService.DataTransferObjects.SendSMSRequest>().Produces(404);
}
}
Loading
Loading