Compare commits
6 Commits
10.1.0-rc3
...
10.1.0-rc7
| Author | SHA1 | Date | |
|---|---|---|---|
|
03041721ca
|
|||
|
05449b9a28
|
|||
|
dfbef9d161
|
|||
|
377977b080
|
|||
|
20147bfec7
|
|||
|
18f81a28e8
|
@@ -2291,6 +2291,7 @@ namespace Svrnty.CQRS.Grpc.Generators
|
||||
sb.AppendLine("using Google.Protobuf.WellKnownTypes;");
|
||||
sb.AppendLine($"using {rootNamespace}.Grpc;");
|
||||
sb.AppendLine("using Svrnty.CQRS.Abstractions;");
|
||||
sb.AppendLine("using Svrnty.CQRS.Abstractions.Security;");
|
||||
sb.AppendLine();
|
||||
|
||||
sb.AppendLine($"namespace {rootNamespace}.Grpc.Services");
|
||||
@@ -2321,6 +2322,17 @@ namespace Svrnty.CQRS.Grpc.Generators
|
||||
sb.AppendLine(" using var scope = _scopeFactory.CreateScope();");
|
||||
sb.AppendLine(" var serviceProvider = scope.ServiceProvider;");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine(" // Authorization check");
|
||||
sb.AppendLine($" var authorizationService = serviceProvider.GetService<ICommandAuthorizationService>();");
|
||||
sb.AppendLine(" if (authorizationService != null)");
|
||||
sb.AppendLine(" {");
|
||||
sb.AppendLine($" var authResult = await authorizationService.IsAllowedAsync(typeof({command.FullyQualifiedName}), context.CancellationToken);");
|
||||
sb.AppendLine(" if (authResult == AuthorizationResult.Unauthorized)");
|
||||
sb.AppendLine(" throw new RpcException(new global::Grpc.Core.Status(global::Grpc.Core.StatusCode.Unauthenticated, \"Unauthorized\"));");
|
||||
sb.AppendLine(" if (authResult == AuthorizationResult.Forbidden)");
|
||||
sb.AppendLine(" throw new RpcException(new global::Grpc.Core.Status(global::Grpc.Core.StatusCode.PermissionDenied, \"Forbidden\"));");
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($" var command = new {command.FullyQualifiedName}");
|
||||
sb.AppendLine(" {");
|
||||
foreach (var prop in command.Properties)
|
||||
@@ -2425,6 +2437,7 @@ namespace Svrnty.CQRS.Grpc.Generators
|
||||
sb.AppendLine("using Microsoft.Extensions.DependencyInjection;");
|
||||
sb.AppendLine($"using {rootNamespace}.Grpc;");
|
||||
sb.AppendLine("using Svrnty.CQRS.Abstractions;");
|
||||
sb.AppendLine("using Svrnty.CQRS.Abstractions.Security;");
|
||||
sb.AppendLine();
|
||||
|
||||
sb.AppendLine($"namespace {rootNamespace}.Grpc.Services");
|
||||
@@ -2455,6 +2468,17 @@ namespace Svrnty.CQRS.Grpc.Generators
|
||||
sb.AppendLine(" using var scope = _scopeFactory.CreateScope();");
|
||||
sb.AppendLine(" var serviceProvider = scope.ServiceProvider;");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine(" // Authorization check");
|
||||
sb.AppendLine($" var authorizationService = serviceProvider.GetService<IQueryAuthorizationService>();");
|
||||
sb.AppendLine(" if (authorizationService != null)");
|
||||
sb.AppendLine(" {");
|
||||
sb.AppendLine($" var authResult = await authorizationService.IsAllowedAsync(typeof({query.FullyQualifiedName}), context.CancellationToken);");
|
||||
sb.AppendLine(" if (authResult == AuthorizationResult.Unauthorized)");
|
||||
sb.AppendLine(" throw new RpcException(new global::Grpc.Core.Status(global::Grpc.Core.StatusCode.Unauthenticated, \"Unauthorized\"));");
|
||||
sb.AppendLine(" if (authResult == AuthorizationResult.Forbidden)");
|
||||
sb.AppendLine(" throw new RpcException(new global::Grpc.Core.Status(global::Grpc.Core.StatusCode.PermissionDenied, \"Forbidden\"));");
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($" var handler = serviceProvider.GetRequiredService<{query.HandlerInterfaceName}>();");
|
||||
sb.AppendLine($" var query = new {query.FullyQualifiedName}");
|
||||
sb.AppendLine(" {");
|
||||
@@ -2736,6 +2760,7 @@ namespace Svrnty.CQRS.Grpc.Generators
|
||||
sb.AppendLine("using Microsoft.Extensions.DependencyInjection;");
|
||||
sb.AppendLine($"using {rootNamespace}.Grpc;");
|
||||
sb.AppendLine("using Svrnty.CQRS.Abstractions;");
|
||||
sb.AppendLine("using Svrnty.CQRS.Abstractions.Security;");
|
||||
sb.AppendLine("using Svrnty.CQRS.DynamicQuery.Abstractions;");
|
||||
sb.AppendLine("using PoweredSoft.DynamicQuery.Core;");
|
||||
sb.AppendLine();
|
||||
@@ -2768,6 +2793,17 @@ namespace Svrnty.CQRS.Grpc.Generators
|
||||
sb.AppendLine(" using var scope = _scopeFactory.CreateScope();");
|
||||
sb.AppendLine(" var serviceProvider = scope.ServiceProvider;");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine(" // Authorization check");
|
||||
sb.AppendLine($" var authorizationService = serviceProvider.GetService<IQueryAuthorizationService>();");
|
||||
sb.AppendLine(" if (authorizationService != null)");
|
||||
sb.AppendLine(" {");
|
||||
sb.AppendLine($" var authResult = await authorizationService.IsAllowedAsync(typeof({dynamicQuery.QueryInterfaceName}), context.CancellationToken);");
|
||||
sb.AppendLine(" if (authResult == AuthorizationResult.Unauthorized)");
|
||||
sb.AppendLine(" throw new RpcException(new global::Grpc.Core.Status(global::Grpc.Core.StatusCode.Unauthenticated, \"Unauthorized\"));");
|
||||
sb.AppendLine(" if (authResult == AuthorizationResult.Forbidden)");
|
||||
sb.AppendLine(" throw new RpcException(new global::Grpc.Core.Status(global::Grpc.Core.StatusCode.PermissionDenied, \"Forbidden\"));");
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine();
|
||||
|
||||
// Build the dynamic query object
|
||||
if (dynamicQuery.HasParams)
|
||||
|
||||
@@ -65,7 +65,7 @@ public class ProtoFileSourceGenerator : IIncrementalGenerator
|
||||
/// <summary>
|
||||
/// Contains the auto-generated Protocol Buffer definition
|
||||
/// </summary>
|
||||
internal static class GeneratedProtoFile
|
||||
public static class GeneratedProtoFile
|
||||
{
|
||||
public const string FileName = "{{protoFileName}}";
|
||||
|
||||
|
||||
@@ -39,6 +39,16 @@ public class WriteProtoFileTask : Task
|
||||
[Required]
|
||||
public string ProtoFileName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The root namespace of the project (optional, falls back to AssemblyName)
|
||||
/// </summary>
|
||||
public string RootNamespace { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The assembly name of the project (used for proto namespace if RootNamespace not set)
|
||||
/// </summary>
|
||||
public string AssemblyName { get; set; } = string.Empty;
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
try
|
||||
@@ -57,6 +67,16 @@ public class WriteProtoFileTask : Task
|
||||
"GeneratedProtoFile.g.cs"
|
||||
);
|
||||
|
||||
// Check if proto file already exists (committed to repo or from previous build)
|
||||
var existingProtoPath = Path.Combine(ProjectDirectory, OutputDirectory, ProtoFileName);
|
||||
if (File.Exists(existingProtoPath) && !File.Exists(generatedFilePath))
|
||||
{
|
||||
Log.LogMessage(MessageImportance.High,
|
||||
$"Svrnty.CQRS.Grpc: Using existing proto file at {existingProtoPath}. " +
|
||||
"To regenerate, delete the file and build twice.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!File.Exists(generatedFilePath))
|
||||
{
|
||||
Log.LogWarning(
|
||||
@@ -65,13 +85,30 @@ public class WriteProtoFileTask : Task
|
||||
|
||||
// Write a minimal placeholder proto file so Grpc.Tools doesn't fail
|
||||
// The real content will be generated on the next build
|
||||
var placeholderProto = @"syntax = ""proto3"";
|
||||
// Use project's namespace so GrpcGenerator can find the service base types
|
||||
var projectNamespace = !string.IsNullOrEmpty(RootNamespace) ? RootNamespace
|
||||
: !string.IsNullOrEmpty(AssemblyName) ? AssemblyName
|
||||
: "Generated";
|
||||
var grpcNamespace = $"{projectNamespace}.Grpc";
|
||||
|
||||
option csharp_namespace = ""Generated.Grpc"";
|
||||
var placeholderProto = $@"syntax = ""proto3"";
|
||||
|
||||
option csharp_namespace = ""{grpcNamespace}"";
|
||||
|
||||
package cqrs;
|
||||
|
||||
// Placeholder proto file - will be regenerated on next build
|
||||
// Placeholder proto file - will be regenerated on next build with actual services
|
||||
// Using namespace: {grpcNamespace}
|
||||
|
||||
// Empty service definitions so Grpc.Tools generates base classes
|
||||
service CommandService {{
|
||||
}}
|
||||
|
||||
service QueryService {{
|
||||
}}
|
||||
|
||||
service DynamicQueryService {{
|
||||
}}
|
||||
";
|
||||
var placeholderOutputPath = Path.Combine(ProjectDirectory, OutputDirectory);
|
||||
Directory.CreateDirectory(placeholderOutputPath);
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
ProjectDirectory="$(MSBuildProjectDirectory)"
|
||||
IntermediateOutputPath="$(IntermediateOutputPath)"
|
||||
OutputDirectory="$(ProtoOutputDirectory)"
|
||||
ProtoFileName="$(GeneratedProtoFileName)" />
|
||||
ProtoFileName="$(GeneratedProtoFileName)"
|
||||
RootNamespace="$(RootNamespace)"
|
||||
AssemblyName="$(AssemblyName)" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
@@ -33,6 +33,7 @@ public static class CqrsBuilderExtensions
|
||||
{
|
||||
Console.WriteLine("Warning: AddGrpcFromConfiguration not found. gRPC services were not registered.");
|
||||
Console.WriteLine("Make sure your project has source generators enabled and references Svrnty.CQRS.Grpc.Generators.");
|
||||
DiagnoseGeneratedCode();
|
||||
}
|
||||
|
||||
// Register mapping callback for automatic endpoint mapping
|
||||
@@ -49,6 +50,59 @@ public static class CqrsBuilderExtensions
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static void DiagnoseGeneratedCode()
|
||||
{
|
||||
var entryAsm = Assembly.GetEntryAssembly();
|
||||
if (entryAsm == null)
|
||||
{
|
||||
Console.WriteLine("Diagnostic: Entry assembly is null");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Diagnostic: Entry assembly = {entryAsm.GetName().Name}");
|
||||
|
||||
try
|
||||
{
|
||||
var allTypes = entryAsm.GetTypes();
|
||||
Console.WriteLine($"Diagnostic: Total types in entry assembly = {allTypes.Length}");
|
||||
|
||||
var grpcTypes = allTypes
|
||||
.Where(t => t.FullName?.Contains("Grpc") == true)
|
||||
.ToList();
|
||||
|
||||
if (grpcTypes.Any())
|
||||
{
|
||||
Console.WriteLine("Diagnostic: Found Grpc-related types:");
|
||||
foreach (var t in grpcTypes)
|
||||
{
|
||||
Console.WriteLine($" - {t.FullName} (IsClass={t.IsClass}, IsSealed={t.IsSealed}, IsPublic={t.IsPublic})");
|
||||
|
||||
// Check for our target method
|
||||
var method = t.GetMethod("AddGrpcFromConfiguration", BindingFlags.Static | BindingFlags.Public);
|
||||
if (method != null)
|
||||
Console.WriteLine($" -> HAS AddGrpcFromConfiguration method!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Diagnostic: No Grpc-related types found. Source generator did NOT run.");
|
||||
}
|
||||
}
|
||||
catch (ReflectionTypeLoadException ex)
|
||||
{
|
||||
Console.WriteLine($"Diagnostic: ReflectionTypeLoadException - {ex.Message}");
|
||||
foreach (var le in ex.LoaderExceptions)
|
||||
{
|
||||
if (le != null)
|
||||
Console.WriteLine($" LoaderException: {le.Message}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Diagnostic: Exception - {ex.GetType().Name}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodInfo? FindExtensionMethod(string methodName, Type parameterType)
|
||||
{
|
||||
// Search through all loaded assemblies for the extension method
|
||||
|
||||
Reference in New Issue
Block a user