| | | 1 | | using System.Reflection; |
| | | 2 | | using Elsa.Authorization; |
| | | 3 | | using Elsa.Permissions; |
| | | 4 | | using Microsoft.AspNetCore.Authorization; |
| | | 5 | | using Microsoft.Extensions.DependencyInjection; |
| | | 6 | | using Microsoft.Extensions.DependencyInjection.Extensions; |
| | | 7 | | |
| | | 8 | | namespace Elsa.Extensions; |
| | | 9 | | |
| | | 10 | | /// <summary>Registers Elsa's permission model: the evaluator, the descriptor catalog, and the authorization handler.</s |
| | | 11 | | public static class AuthorizationServiceCollectionExtensions |
| | | 12 | | { |
| | | 13 | | /// <summary> |
| | | 14 | | /// Adds the single permission evaluator and the descriptor registry. Safe to call more than once, and |
| | | 15 | | /// safe to call before any module has contributed descriptors. |
| | | 16 | | /// </summary> |
| | | 17 | | public static IServiceCollection AddElsaAuthorization(this IServiceCollection services) |
| | | 18 | | { |
| | 18 | 19 | | services.TryAddSingleton<IPermissionEvaluator, PermissionEvaluator>(); |
| | 18 | 20 | | services.TryAddSingleton<IPermissionDescriptorRegistry, DefaultPermissionDescriptorRegistry>(); |
| | 18 | 21 | | services.TryAddSingleton<IPermissionGrantValidator, PermissionGrantValidator>(); |
| | 18 | 22 | | services.TryAddEnumerable(ServiceDescriptor.Scoped<IAuthorizationHandler, PermissionAuthorizationHandler>()); |
| | | 23 | | |
| | 18 | 24 | | return services; |
| | | 25 | | } |
| | | 26 | | |
| | | 27 | | /// <summary> |
| | | 28 | | /// Contributes every <see cref="IPermissionDescriptorProvider"/> declared in <paramref name="assembly"/>. |
| | | 29 | | /// Discovery is by convention so that a module cannot ship endpoints without the catalog describing them. |
| | | 30 | | /// </summary> |
| | | 31 | | public static IServiceCollection AddPermissionDescriptorsFromAssembly(this IServiceCollection services, Assembly ass |
| | | 32 | | { |
| | 18 | 33 | | var providerTypes = assembly.GetTypes() |
| | 3321 | 34 | | .Where(x => x is { IsClass: true, IsAbstract: false } && typeof(IPermissionDescriptorProvider).IsAssignableF |
| | | 35 | | |
| | 72 | 36 | | foreach (var providerType in providerTypes) |
| | 18 | 37 | | services.TryAddEnumerable(ServiceDescriptor.Singleton(typeof(IPermissionDescriptorProvider), providerType)); |
| | | 38 | | |
| | 18 | 39 | | return services; |
| | | 40 | | } |
| | | 41 | | |
| | | 42 | | /// <summary> |
| | | 43 | | /// Contributes every <see cref="IPermissionDescriptorProvider"/> declared in the loaded Elsa assemblies. |
| | | 44 | | /// </summary> |
| | | 45 | | /// <remarks> |
| | | 46 | | /// The module path discovers descriptors from the assemblies it registers with FastEndpoints. The shell |
| | | 47 | | /// path does not register assemblies that way -- CShells discovers endpoints from features implementing |
| | | 48 | | /// its own marker interface -- so without this the catalog comes up empty on a shell host, taking role |
| | | 49 | | /// authoring, introspection and the stored-permission validator with it. Scanning is bounded to loaded |
| | | 50 | | /// Elsa assemblies and runs once per shell. |
| | | 51 | | /// </remarks> |
| | | 52 | | public static IServiceCollection AddPermissionDescriptorsFromLoadedAssemblies(this IServiceCollection services) |
| | | 53 | | { |
| | 0 | 54 | | var assemblies = AppDomain.CurrentDomain |
| | 0 | 55 | | .GetAssemblies() |
| | 0 | 56 | | .Where(x => x.GetName().Name?.StartsWith("Elsa.", StringComparison.Ordinal) == true && !x.IsDynamic); |
| | | 57 | | |
| | 0 | 58 | | foreach (var assembly in assemblies) |
| | | 59 | | { |
| | | 60 | | try |
| | | 61 | | { |
| | 0 | 62 | | services.AddPermissionDescriptorsFromAssembly(assembly); |
| | 0 | 63 | | } |
| | 0 | 64 | | catch (ReflectionTypeLoadException) |
| | | 65 | | { |
| | | 66 | | // An assembly whose types cannot all be loaded contributes nothing rather than failing startup. |
| | 0 | 67 | | } |
| | | 68 | | } |
| | | 69 | | |
| | 0 | 70 | | return services; |
| | | 71 | | } |
| | | 72 | | |
| | | 73 | | /// <summary>Contributes <typeparamref name="T"/>'s permission descriptors to the catalog.</summary> |
| | | 74 | | public static IServiceCollection AddPermissionDescriptors<T>(this IServiceCollection services) where T : class, IPer |
| | | 75 | | { |
| | 0 | 76 | | services.TryAddEnumerable(ServiceDescriptor.Singleton<IPermissionDescriptorProvider, T>()); |
| | | 77 | | |
| | 0 | 78 | | return services; |
| | | 79 | | } |
| | | 80 | | } |