diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..19b16ce --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +name: CI + +on: + push: + branches: [JP] + pull_request: + branches: [JP] + +jobs: + build-and-test: + name: Build & Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-dotnet@v4 + with: + dotnet-version: '10.0.x' + + - name: Restore dependencies + run: dotnet restore + + - name: Build (warnings as errors) + run: dotnet build --no-restore --warnaserror + + - name: Test + run: dotnet test --no-build --verbosity normal diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..7902bae --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,27 @@ +name: Security + +on: + push: + branches: [JP] + pull_request: + branches: [JP] + schedule: + - cron: "0 6 * * 1" # Weekly on Monday at 06:00 UTC + +jobs: + vulnerability-scan: + name: .NET vulnerability scan + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-dotnet@v4 + with: + dotnet-version: "10.0.x" + + - name: Restore dependencies + run: dotnet restore + + - name: Check for vulnerable packages + run: dotnet list package --vulnerable --include-transitive diff --git a/.gitignore b/.gitignore index 5c55ab0..d6049de 100644 --- a/.gitignore +++ b/.gitignore @@ -340,4 +340,13 @@ ASALocalRun/ .localhistory/ # BeatPulse healthcheck temp database -healthchecksdb \ No newline at end of file +healthchecksdb + +# Secrets and credentials +.env +.env.local +.env.* +*.key +secrets/ +.aws/ +credentials.json \ No newline at end of file diff --git a/Svrnty.CQRS.Abstractions/Discovery/CommandMeta.cs b/Svrnty.CQRS.Abstractions/Discovery/CommandMeta.cs index d58502b..55aac43 100644 --- a/Svrnty.CQRS.Abstractions/Discovery/CommandMeta.cs +++ b/Svrnty.CQRS.Abstractions/Discovery/CommandMeta.cs @@ -19,7 +19,7 @@ public sealed class CommandMeta : ICommandMeta ServiceType = serviceType; } - private CommandNameAttribute NameAttribute => CommandType.GetCustomAttribute(); + private CommandNameAttribute? NameAttribute => CommandType.GetCustomAttribute(); public string Name { @@ -32,7 +32,7 @@ public sealed class CommandMeta : ICommandMeta public Type CommandType { get; } public Type ServiceType { get; } - public Type CommandResultType { get; } + public Type? CommandResultType { get; } public string LowerCamelCaseName { diff --git a/Svrnty.CQRS.Abstractions/Discovery/ICommandMeta.cs b/Svrnty.CQRS.Abstractions/Discovery/ICommandMeta.cs index bffcd15..66f41d2 100644 --- a/Svrnty.CQRS.Abstractions/Discovery/ICommandMeta.cs +++ b/Svrnty.CQRS.Abstractions/Discovery/ICommandMeta.cs @@ -7,7 +7,7 @@ public interface ICommandMeta string Name { get; } Type CommandType { get; } Type ServiceType { get; } - Type CommandResultType { get; } + Type? CommandResultType { get; } string LowerCamelCaseName { get; } } diff --git a/Svrnty.CQRS.Abstractions/Discovery/IQueryDiscovery.cs b/Svrnty.CQRS.Abstractions/Discovery/IQueryDiscovery.cs index 115ae1e..9d87ecc 100644 --- a/Svrnty.CQRS.Abstractions/Discovery/IQueryDiscovery.cs +++ b/Svrnty.CQRS.Abstractions/Discovery/IQueryDiscovery.cs @@ -5,8 +5,8 @@ namespace Svrnty.CQRS.Abstractions.Discovery; public interface IQueryDiscovery { - IQueryMeta FindQuery(string name); - IQueryMeta FindQuery(Type queryType); + IQueryMeta? FindQuery(string name); + IQueryMeta? FindQuery(Type queryType); IEnumerable GetQueries(); bool QueryExists(string name); bool QueryExists(Type queryType); @@ -16,8 +16,8 @@ public interface ICommandDiscovery { bool CommandExists(string name); bool CommandExists(Type commandType); - ICommandMeta FindCommand(string name); - ICommandMeta FindCommand(Type commandType); + ICommandMeta? FindCommand(string name); + ICommandMeta? FindCommand(Type commandType); IEnumerable GetCommands(); } diff --git a/Svrnty.CQRS.Abstractions/Discovery/QueryMeta.cs b/Svrnty.CQRS.Abstractions/Discovery/QueryMeta.cs index e6a4a14..680f75b 100644 --- a/Svrnty.CQRS.Abstractions/Discovery/QueryMeta.cs +++ b/Svrnty.CQRS.Abstractions/Discovery/QueryMeta.cs @@ -13,7 +13,7 @@ public class QueryMeta : IQueryMeta QueryResultType = queryResultType; } - protected virtual QueryNameAttribute NameAttribute => QueryType.GetCustomAttribute(); + protected virtual QueryNameAttribute? NameAttribute => QueryType.GetCustomAttribute(); public virtual string Name { diff --git a/Svrnty.CQRS.DynamicQuery.Abstractions/IDynamicQuery.cs b/Svrnty.CQRS.DynamicQuery.Abstractions/IDynamicQuery.cs index fce0892..f8d67fd 100644 --- a/Svrnty.CQRS.DynamicQuery.Abstractions/IDynamicQuery.cs +++ b/Svrnty.CQRS.DynamicQuery.Abstractions/IDynamicQuery.cs @@ -20,10 +20,10 @@ public interface IDynamicQuery : IDynamicQue public interface IDynamicQuery { - List GetFilters(); - List GetGroups(); - List GetSorts(); - List GetAggregates(); + List? GetFilters(); + List? GetGroups(); + List? GetSorts(); + List? GetAggregates(); int? GetPage(); int? GetPageSize(); } \ No newline at end of file diff --git a/Svrnty.CQRS.DynamicQuery.Abstractions/IDynamicQueryParams.cs b/Svrnty.CQRS.DynamicQuery.Abstractions/IDynamicQueryParams.cs index 08323c0..5650b7b 100644 --- a/Svrnty.CQRS.DynamicQuery.Abstractions/IDynamicQueryParams.cs +++ b/Svrnty.CQRS.DynamicQuery.Abstractions/IDynamicQueryParams.cs @@ -3,5 +3,5 @@ public interface IDynamicQueryParams where TParams : class { - TParams GetParams(); + TParams? GetParams(); } diff --git a/Svrnty.CQRS.DynamicQuery/Discover/DynamicQueryMeta.cs b/Svrnty.CQRS.DynamicQuery/Discover/DynamicQueryMeta.cs index 54fc225..b3d1623 100644 --- a/Svrnty.CQRS.DynamicQuery/Discover/DynamicQueryMeta.cs +++ b/Svrnty.CQRS.DynamicQuery/Discover/DynamicQueryMeta.cs @@ -22,7 +22,7 @@ public class DynamicQueryMeta(Type queryType, Type serviceType, Type queryResult } } - public Type ParamsType { get; internal set; } - public string OverridableName { get; internal set; } + public Type? ParamsType { get; internal set; } + public string? OverridableName { get; internal set; } } diff --git a/Svrnty.CQRS.DynamicQuery/DynamicQuery.cs b/Svrnty.CQRS.DynamicQuery/DynamicQuery.cs index fd322eb..9144ab0 100644 --- a/Svrnty.CQRS.DynamicQuery/DynamicQuery.cs +++ b/Svrnty.CQRS.DynamicQuery/DynamicQuery.cs @@ -18,9 +18,9 @@ public class DynamicQuery : DynamicQuery, IDynam where TDestination : class where TParams : class { - public TParams Params { get; set; } + public TParams? Params { get; set; } - public TParams GetParams() + public TParams? GetParams() { return Params; } @@ -30,23 +30,23 @@ public class DynamicQuery : IDynamicQuery { public int? Page { get; set; } public int? PageSize { get; set; } - public List Sorts { get; set; } - public List Aggregates { get; set; } - public List Groups { get; set; } - public List Filters { get; set; } + public List? Sorts { get; set; } + public List? Aggregates { get; set; } + public List? Groups { get; set; } + public List? Filters { get; set; } - public List GetAggregates() + public List? GetAggregates() { - return Aggregates?.Select(t => t.ToAggregate())?.ToList();//.AsEnumerable()?.ToList(); + return Aggregates?.Select(t => t.ToAggregate())?.ToList(); } - public List GetFilters() + public List? GetFilters() { return Filters?.Select(t => t.ToFilter())?.ToList(); } - public List GetGroups() + public List? GetGroups() { return this.Groups?.AsEnumerable()?.ToList(); } @@ -61,7 +61,7 @@ public class DynamicQuery : IDynamicQuery return this.PageSize; } - public List GetSorts() + public List? GetSorts() { return this.Sorts?.AsEnumerable()?.ToList(); } diff --git a/Svrnty.CQRS.DynamicQuery/DynamicQueryAggregate.cs b/Svrnty.CQRS.DynamicQuery/DynamicQueryAggregate.cs index f04f8e0..468a3ed 100644 --- a/Svrnty.CQRS.DynamicQuery/DynamicQueryAggregate.cs +++ b/Svrnty.CQRS.DynamicQuery/DynamicQueryAggregate.cs @@ -6,8 +6,8 @@ namespace Svrnty.CQRS.DynamicQuery; public class DynamicQueryAggregate { - public string Path { get; set; } - public string Type { get; set; } + public required string Path { get; set; } + public required string Type { get; set; } public IAggregate ToAggregate() { diff --git a/Svrnty.CQRS.DynamicQuery/DynamicQueryFilter.cs b/Svrnty.CQRS.DynamicQuery/DynamicQueryFilter.cs index 826b965..1300016 100644 --- a/Svrnty.CQRS.DynamicQuery/DynamicQueryFilter.cs +++ b/Svrnty.CQRS.DynamicQuery/DynamicQueryFilter.cs @@ -9,14 +9,14 @@ namespace Svrnty.CQRS.DynamicQuery; public class DynamicQueryFilter { - public List Filters { get; set; } + public List? Filters { get; set; } public bool? And { get; set; } - public string Type { get; set; } + public string? Type { get; set; } public bool? Not { get; set; } - public string Path { get; set; } - public object Value { get; set; } + public string? Path { get; set; } + public object? Value { get; set; } - public string QueryValue + public string? QueryValue { get { @@ -32,7 +32,7 @@ public class DynamicQueryFilter public IFilter ToFilter() { - var type = Enum.Parse(Type); + var type = Enum.Parse(Type!); if (type == FilterType.Composite) { var compositeFilter = new CompositeFilter @@ -44,7 +44,7 @@ public class DynamicQueryFilter return compositeFilter; } - object value = Value; + object? value = Value; if (Value is JsonElement jsonElement) { switch (jsonElement.ValueKind) diff --git a/Svrnty.CQRS.DynamicQuery/DynamicQueryHandlerBase.cs b/Svrnty.CQRS.DynamicQuery/DynamicQueryHandlerBase.cs index 54dee1f..9e7d1b5 100644 --- a/Svrnty.CQRS.DynamicQuery/DynamicQueryHandlerBase.cs +++ b/Svrnty.CQRS.DynamicQuery/DynamicQueryHandlerBase.cs @@ -60,7 +60,10 @@ public abstract class DynamicQueryHandlerBase { var types = _dynamicQueryInterceptorProviders.SelectMany(t => t.GetInterceptorsTypes()).Distinct(); foreach (var type in types) - yield return _serviceProvider.GetService(type) as IQueryInterceptor; + { + if (_serviceProvider.GetService(type) is IQueryInterceptor interceptor) + yield return interceptor; + } } protected async Task> ProcessQueryAsync(IDynamicQuery query, diff --git a/Svrnty.CQRS.DynamicQuery/ServiceCollectionExtensions.cs b/Svrnty.CQRS.DynamicQuery/ServiceCollectionExtensions.cs index 687b9a5..11fa1a0 100644 --- a/Svrnty.CQRS.DynamicQuery/ServiceCollectionExtensions.cs +++ b/Svrnty.CQRS.DynamicQuery/ServiceCollectionExtensions.cs @@ -26,11 +26,11 @@ public static class ServiceCollectionExtensions return new DynamicQueryServicesBuilder(services); } - public static IServiceCollection AddDynamicQuery(this IServiceCollection services, string name = null) + public static IServiceCollection AddDynamicQuery(this IServiceCollection services, string? name = null) where TSourceAndDestination : class => AddDynamicQuery(services, name: name); - public static IServiceCollection AddDynamicQuery(this IServiceCollection services, string name = null) + public static IServiceCollection AddDynamicQuery(this IServiceCollection services, string? name = null) where TSource : class where TDestination : class { @@ -51,7 +51,7 @@ public static class ServiceCollectionExtensions return services; } - public static IServiceCollection AddDynamicQueryWithProvider(this IServiceCollection services, string name = null) + public static IServiceCollection AddDynamicQueryWithProvider(this IServiceCollection services, string? name = null) where TQueryableProvider : class, IQueryableProvider where TSource : class { @@ -60,7 +60,7 @@ public static class ServiceCollectionExtensions return services; } - public static IServiceCollection AddDynamicQueryWithParamsAndProvider(this IServiceCollection services, string name = null) + public static IServiceCollection AddDynamicQueryWithParamsAndProvider(this IServiceCollection services, string? name = null) where TQueryableProvider : class, IQueryableProvider where TParams : class where TSource : class @@ -86,12 +86,12 @@ public static class ServiceCollectionExtensions return services; } - public static IServiceCollection AddDynamicQueryWithParams(this IServiceCollection services, string name = null) + public static IServiceCollection AddDynamicQueryWithParams(this IServiceCollection services, string? name = null) where TSourceAndDestination : class where TParams : class => AddDynamicQueryWithParams(services, name: name); - public static IServiceCollection AddDynamicQueryWithParams(this IServiceCollection services, string name = null) + public static IServiceCollection AddDynamicQueryWithParams(this IServiceCollection services, string? name = null) where TSource : class where TDestination : class where TParams : class diff --git a/Svrnty.CQRS/Discovery/CommandDiscovery.cs b/Svrnty.CQRS/Discovery/CommandDiscovery.cs index 570605f..e06f993 100644 --- a/Svrnty.CQRS/Discovery/CommandDiscovery.cs +++ b/Svrnty.CQRS/Discovery/CommandDiscovery.cs @@ -15,8 +15,8 @@ public sealed class CommandDiscovery : ICommandDiscovery } public IEnumerable GetCommands() => _commandMetas; - public ICommandMeta FindCommand(string name) => _commandMetas.FirstOrDefault(t => t.Name == name); - public ICommandMeta FindCommand(Type commandType) => _commandMetas.FirstOrDefault(t => t.CommandType == commandType); + public ICommandMeta? FindCommand(string name) => _commandMetas.FirstOrDefault(t => t.Name == name); + public ICommandMeta? FindCommand(Type commandType) => _commandMetas.FirstOrDefault(t => t.CommandType == commandType); public bool CommandExists(string name) => _commandMetas.Any(t => t.Name == name); public bool CommandExists(Type commandType) => _commandMetas.Any(t => t.CommandType == commandType); } diff --git a/Svrnty.CQRS/Discovery/QueryDiscovery.cs b/Svrnty.CQRS/Discovery/QueryDiscovery.cs index 8098e40..9606e1e 100644 --- a/Svrnty.CQRS/Discovery/QueryDiscovery.cs +++ b/Svrnty.CQRS/Discovery/QueryDiscovery.cs @@ -15,8 +15,8 @@ public sealed class QueryDiscovery : IQueryDiscovery } public IEnumerable GetQueries() => _queryMetas; - public IQueryMeta FindQuery(string name) => _queryMetas.FirstOrDefault(t => t.Name == name); - public IQueryMeta FindQuery(Type queryType) => _queryMetas.FirstOrDefault(t => t.QueryType == queryType); + public IQueryMeta? FindQuery(string name) => _queryMetas.FirstOrDefault(t => t.Name == name); + public IQueryMeta? FindQuery(Type queryType) => _queryMetas.FirstOrDefault(t => t.QueryType == queryType); public bool QueryExists(string name) => _queryMetas.Any(t => t.Name == name); public bool QueryExists(Type queryType) => _queryMetas.Any(t => t.QueryType == queryType); }