async public static Task <HandlerInstance> GetHandlerInstance(this IServiceProvider serviceProvider, HandlerInfo handlerInfo) { var handlerInstance = new HandlerInstance { Method = handlerInfo.Method, Instance = serviceProvider.GetService(handlerInfo.HandlerType) }; if (handlerInstance.Instance is null) { throw new SWException($"Could not find required service {handlerInfo.Key} for resource {handlerInfo.Resource}."); } CqApiOptions options = serviceProvider.GetService <CqApiOptions>() ?? new CqApiOptions(); var protectAttribute = handlerInfo.HandlerType.GetCustomAttribute <ProtectAttribute>(); var unprotectAttribute = handlerInfo.HandlerType.GetCustomAttribute <UnprotectAttribute>(); if ((options.ProtectAll && unprotectAttribute == null) || protectAttribute is ProtectAttribute) { var requestContext = serviceProvider.GetRequiredService <RequestContext>(); if (!requestContext.IsValid) { throw new SWUnauthorizedException(); } if (protectAttribute?.RequireRole ?? false) { var prefix = string.IsNullOrWhiteSpace(options.RolePrefix) ? handlerInfo.Resource : $"{options.RolePrefix}.{handlerInfo.Resource}"; var requiredRoles = new string[] { $"{prefix}.{handlerInfo.HandlerType.Name}", $"{prefix}.*" }; if (!requestContext.User.Claims.Any(c => c.Subject.RoleClaimType == ClaimTypes.Role && requiredRoles.Contains(c.Value, StringComparer.OrdinalIgnoreCase))) { throw new SWForbiddenException(); } } } return(handlerInstance); }
public static IServiceCollection AddCqApi(this IServiceCollection services, Action <CqApiOptions> configure, params Assembly[] assemblies) { var cqApiOptions = new CqApiOptions(); if (configure != null) { configure.Invoke(cqApiOptions); } services.AddSingleton(cqApiOptions); services.AddSingleton <ServiceDiscovery>(); if (assemblies.Length == 0) { assemblies = new Assembly[] { Assembly.GetCallingAssembly() } } ; services.Scan(scan => scan .FromAssemblies(assemblies) .AddClasses(classes => classes.AssignableTo <IHandler>()) .AsSelf().As <IHandler>().WithScopedLifetime()); services.Scan(scan => scan .FromAssemblies(assemblies) .AddClasses(classes => classes.AssignableTo <IValidator>()) .AsImplementedInterfaces().WithTransientLifetime()); services.AddHttpContextAccessor(); services.AddScoped <RequestContext>(); services.AddRouting(options => { options.ConstraintMap.Add("cqapiPrefix", typeof(CqapiPrefixRouteConstraint)); }); return(services); } }
public ServiceDiscovery(IServiceProvider serviceProvider, ILogger <ServiceDiscovery> logger, CqApiOptions options) { this.options = options; using (var scope = serviceProvider.CreateScope()) { var registeredHandlers = scope.ServiceProvider.GetServices <IHandler>(); foreach (var svc in registeredHandlers) { var serviceType = svc.GetType(); var interfaceType = serviceType.GetTypeInfo().ImplementedInterfaces.Where(i => typeof(IHandler).IsAssignableFrom(i) && i != typeof(IHandler)).Single(); var interfaceTypeNormalized = interfaceType.IsGenericType ? interfaceType.GetGenericTypeDefinition() : interfaceType; var typeNameArray = serviceType.FullName.Split('.'); var resourceName = typeNameArray[typeNameArray.Length - 2].ToLower(); var handlerNameAttribute = serviceType.GetCustomAttribute <HandlerNameAttribute>(); var handlerName = handlerNameAttribute == null ? "" : $"/{handlerNameAttribute.Name.ToLower()}"; if (!resourceHandlers.ContainsKey(resourceName)) { resourceHandlers.Add(resourceName, new Dictionary <string, HandlerInfo>(StringComparer.OrdinalIgnoreCase)); } var handlerKey = $"{HandlerTypeMetadata.Handlers[interfaceTypeNormalized].Key}{handlerName}"; resourceHandlers[resourceName][handlerKey] = new HandlerInfo { HandlerType = serviceType, Method = interfaceType.GetMethod("Handle"), ArgumentTypes = interfaceType.GetMethod("Handle").GetParameters().Select(p => p.ParameterType).ToList(), Key = handlerKey, Resource = resourceName, NormalizedInterfaceType = interfaceTypeNormalized }; } } }
public CqapiPrefixRouteConstraint(CqApiOptions options) { this.options = options; }