diff --git a/src/Scanner/StellaOps.Scanner.WebService/Endpoints/SourcesEndpoints.cs b/src/Scanner/StellaOps.Scanner.WebService/Endpoints/SourcesEndpoints.cs index 048cf2d36..65c564b95 100644 --- a/src/Scanner/StellaOps.Scanner.WebService/Endpoints/SourcesEndpoints.cs +++ b/src/Scanner/StellaOps.Scanner.WebService/Endpoints/SourcesEndpoints.cs @@ -3,12 +3,14 @@ using System.Text.Json.Serialization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using StellaOps.Auth.Abstractions; +using StellaOps.Scanner.Sources.Configuration; using StellaOps.Scanner.Sources.Contracts; using StellaOps.Scanner.Sources.Domain; using StellaOps.Scanner.Sources.Services; using StellaOps.Scanner.WebService.Constants; using StellaOps.Scanner.WebService.Infrastructure; using StellaOps.Scanner.WebService.Security; +using StellaOps.Scanner.WebService.Tenancy; namespace StellaOps.Scanner.WebService.Endpoints; diff --git a/src/Scanner/StellaOps.Scanner.WebService/Endpoints/WebhookEndpoints.cs b/src/Scanner/StellaOps.Scanner.WebService/Endpoints/WebhookEndpoints.cs index 7c98c65fa..719ae01e4 100644 --- a/src/Scanner/StellaOps.Scanner.WebService/Endpoints/WebhookEndpoints.cs +++ b/src/Scanner/StellaOps.Scanner.WebService/Endpoints/WebhookEndpoints.cs @@ -15,6 +15,11 @@ using StellaOps.Scanner.WebService.Infrastructure; namespace StellaOps.Scanner.WebService.Endpoints; +/// +/// Marker class for webhook endpoint logging. +/// +internal sealed class WebhookEndpointLogger; + /// /// Endpoints for receiving webhooks from container registries and Git providers. /// @@ -98,7 +103,7 @@ internal static class WebhookEndpoints IEnumerable handlers, ISourceTriggerDispatcher dispatcher, ICredentialResolver credentialResolver, - ILogger logger, + ILogger logger, HttpContext context, CancellationToken ct) { @@ -140,7 +145,7 @@ internal static class WebhookEndpoints logger.LogWarning("Webhook received without signature for source {SourceId}", sourceId); return ProblemResultFactory.Create( context, - ProblemTypes.Unauthorized, + ProblemTypes.Authentication, "Missing webhook signature", StatusCodes.Status401Unauthorized); } @@ -164,7 +169,7 @@ internal static class WebhookEndpoints logger.LogWarning("Invalid webhook signature for source {SourceId}", sourceId); return ProblemResultFactory.Create( context, - ProblemTypes.Unauthorized, + ProblemTypes.Authentication, "Invalid webhook signature", StatusCodes.Status401Unauthorized); } @@ -252,7 +257,7 @@ internal static class WebhookEndpoints IEnumerable handlers, ISourceTriggerDispatcher dispatcher, ICredentialResolver credentialResolver, - ILogger logger, + ILogger logger, HttpContext context, CancellationToken ct) { @@ -290,7 +295,7 @@ internal static class WebhookEndpoints IEnumerable handlers, ISourceTriggerDispatcher dispatcher, ICredentialResolver credentialResolver, - ILogger logger, + ILogger logger, HttpContext context, CancellationToken ct) { @@ -337,7 +342,7 @@ internal static class WebhookEndpoints IEnumerable handlers, ISourceTriggerDispatcher dispatcher, ICredentialResolver credentialResolver, - ILogger logger, + ILogger logger, HttpContext context, CancellationToken ct) { @@ -377,7 +382,7 @@ internal static class WebhookEndpoints IEnumerable handlers, ISourceTriggerDispatcher dispatcher, ICredentialResolver credentialResolver, - ILogger logger, + ILogger logger, HttpContext context, CancellationToken ct) { @@ -420,7 +425,7 @@ internal static class WebhookEndpoints IEnumerable handlers, ISourceTriggerDispatcher dispatcher, ICredentialResolver credentialResolver, - ILogger logger, + ILogger logger, HttpContext context, string signatureHeader, CancellationToken ct) @@ -459,7 +464,7 @@ internal static class WebhookEndpoints logger.LogWarning("Webhook received without signature for source {SourceId}", source.SourceId); return ProblemResultFactory.Create( context, - ProblemTypes.Unauthorized, + ProblemTypes.Authentication, "Missing webhook signature", StatusCodes.Status401Unauthorized); } @@ -483,7 +488,7 @@ internal static class WebhookEndpoints logger.LogWarning("Invalid webhook signature for source {SourceId}", source.SourceId); return ProblemResultFactory.Create( context, - ProblemTypes.Unauthorized, + ProblemTypes.Authentication, "Invalid webhook signature", StatusCodes.Status401Unauthorized); } diff --git a/src/Scanner/StellaOps.Scanner.WebService/Tenancy/ITenantContext.cs b/src/Scanner/StellaOps.Scanner.WebService/Tenancy/ITenantContext.cs new file mode 100644 index 000000000..a84e017dc --- /dev/null +++ b/src/Scanner/StellaOps.Scanner.WebService/Tenancy/ITenantContext.cs @@ -0,0 +1,12 @@ +namespace StellaOps.Scanner.WebService.Tenancy; + +/// +/// Provides the current tenant context for multi-tenant operations. +/// +public interface ITenantContext +{ + /// + /// Gets the current tenant ID. + /// + string TenantId { get; } +} diff --git a/src/Scanner/StellaOps.Scanner.WebService/Tenancy/IUserContext.cs b/src/Scanner/StellaOps.Scanner.WebService/Tenancy/IUserContext.cs new file mode 100644 index 000000000..02f72d4c1 --- /dev/null +++ b/src/Scanner/StellaOps.Scanner.WebService/Tenancy/IUserContext.cs @@ -0,0 +1,17 @@ +namespace StellaOps.Scanner.WebService.Tenancy; + +/// +/// Provides the current user context for audit and authorization. +/// +public interface IUserContext +{ + /// + /// Gets the current user ID. + /// + string UserId { get; } + + /// + /// Gets the current user's display name. + /// + string? DisplayName { get; } +} diff --git a/src/Scanner/__Libraries/StellaOps.Scanner.Sources/Persistence/SbomSourceRepository.cs b/src/Scanner/__Libraries/StellaOps.Scanner.Sources/Persistence/SbomSourceRepository.cs index 7c982964e..f458c2d79 100644 --- a/src/Scanner/__Libraries/StellaOps.Scanner.Sources/Persistence/SbomSourceRepository.cs +++ b/src/Scanner/__Libraries/StellaOps.Scanner.Sources/Persistence/SbomSourceRepository.cs @@ -122,11 +122,11 @@ public sealed class SbomSourceRepository : RepositoryBase( + var totalCount = await ExecuteScalarAsync( tenantId, countSb.ToString(), AddFilters, - ct)).Value; + ct); string? nextCursor = null; if (items.Count > request.Limit) diff --git a/src/Scanner/__Libraries/StellaOps.Scanner.Sources/Persistence/SbomSourceRunRepository.cs b/src/Scanner/__Libraries/StellaOps.Scanner.Sources/Persistence/SbomSourceRunRepository.cs index 844bec0d5..095b9a1da 100644 --- a/src/Scanner/__Libraries/StellaOps.Scanner.Sources/Persistence/SbomSourceRunRepository.cs +++ b/src/Scanner/__Libraries/StellaOps.Scanner.Sources/Persistence/SbomSourceRunRepository.cs @@ -98,12 +98,11 @@ public sealed class SbomSourceRunRepository : RepositoryBase( + var totalCount = await ExecuteScalarAsync( "__system__", countSb.ToString(), AddFilters, ct); - var totalCount = totalCountResult.GetValueOrDefault(); string? nextCursor = null; if (items.Count > request.Limit)