StartupHelper.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. using System.Text;
  2. using DataSharing.Repository;
  3. using DataSharing.SendTask;
  4. using Mapster;
  5. using MapsterMapper;
  6. using Microsoft.AspNetCore.Authentication.JwtBearer;
  7. using Microsoft.IdentityModel.Tokens;
  8. using Microsoft.OpenApi.Models;
  9. using Quartz;
  10. using Quartz.AspNetCore;
  11. using XF.Domain.Entities;
  12. using XF.Domain.Exceptions;
  13. using XF.Domain.Options;
  14. using XF.Domain.Repository;
  15. namespace DataSharing.Host
  16. {
  17. public static class StartupHelper
  18. {
  19. /// <summary>
  20. /// Authentication
  21. /// </summary>
  22. /// <param name="services"></param>
  23. /// <param name="configuration"></param>
  24. /// <returns></returns>
  25. public static IServiceCollection RegisterAuthentication(this IServiceCollection services, ConfigurationManager configuration)
  26. {
  27. //JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
  28. //services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  29. // .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, d =>
  30. // {
  31. // d.Authority = identityConfigs.IdentityUrl;
  32. // d.RequireHttpsMetadata = false;
  33. // d.TokenValidationParameters = new TokenValidationParameters
  34. // {
  35. // ValidateAudience = false
  36. // };
  37. // //d.Audience = "hotline_api";
  38. // d.Events = new JwtBearerEvents
  39. // {
  40. // OnMessageReceived = context =>
  41. // {
  42. // var accessToken = context.Request.Query["access_token"];
  43. // // If the request is for our hub...
  44. // var path = context.HttpContext.Request.Path;
  45. // if (!string.IsNullOrEmpty(accessToken) &&
  46. // (path.StartsWithSegments("/hubs/callcenter")))
  47. // {
  48. // // Read the token out of the query string
  49. // context.Token = accessToken;
  50. // }
  51. // return Task.CompletedTask;
  52. // }
  53. // };
  54. // });
  55. services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  56. .AddJwtBearer(d =>
  57. {
  58. var jwtOptions = configuration.GetSection("IdentityConfiguration").Get<IdentityConfiguration>().Jwt;
  59. byte[] bytes = Encoding.UTF8.GetBytes(jwtOptions.SecretKey);
  60. var secKey = new SymmetricSecurityKey(bytes);
  61. d.TokenValidationParameters = new()
  62. {
  63. ValidateIssuer = false,
  64. ValidateAudience = false,
  65. ValidateLifetime = true,
  66. ValidateIssuerSigningKey = true,
  67. IssuerSigningKey = secKey,
  68. };
  69. //d.Audience = "hotline_api";
  70. d.Events = new JwtBearerEvents
  71. {
  72. OnMessageReceived = context =>
  73. {
  74. var accessToken = context.Request.Query["access_token"];
  75. // If the request is for our hub...
  76. var path = context.HttpContext.Request.Path;
  77. if (!string.IsNullOrEmpty(accessToken) &&
  78. (path.StartsWithSegments("/hubs/hotline")))
  79. {
  80. // Read the token out of the query string
  81. context.Token = accessToken;
  82. }
  83. return Task.CompletedTask;
  84. }
  85. };
  86. })
  87. ;
  88. return services;
  89. }
  90. /// <summary>
  91. /// Swagger
  92. /// </summary>
  93. /// <param name="services"></param>
  94. /// <returns></returns>
  95. public static IServiceCollection RegisterSwagger(this IServiceCollection services)
  96. {
  97. services.AddSwaggerGen(c =>
  98. {
  99. //添加文档
  100. c.SwaggerDoc("v1", new OpenApiInfo() { Title = "Hotline Api", Version = "v1.0", Description = "城市热线api" });
  101. var files = Directory.GetFiles(AppContext.BaseDirectory).Where(d => d.EndsWith(".xml"));
  102. foreach (var file in files)
  103. {
  104. c.IncludeXmlComments(file, true);
  105. }
  106. var scheme = new OpenApiSecurityScheme()
  107. {
  108. Description = "Authorization header. \r\nExample: 'Bearer ***'",
  109. Reference = new OpenApiReference
  110. {
  111. Type = ReferenceType.SecurityScheme,
  112. Id = "Authorization"
  113. },
  114. Scheme = "oauth2",
  115. Name = "Authorization",
  116. In = ParameterLocation.Header,
  117. Type = SecuritySchemeType.ApiKey,
  118. };
  119. c.AddSecurityDefinition("Authorization", scheme);
  120. var requirement = new OpenApiSecurityRequirement();
  121. requirement[scheme] = new List<string>();
  122. c.AddSecurityRequirement(requirement);
  123. });
  124. return services;
  125. }
  126. /// <summary>
  127. /// Cors
  128. /// </summary>
  129. /// <param name="services"></param>
  130. /// <param name="configuration"></param>
  131. /// <param name="corsOrigins"></param>
  132. /// <returns></returns>
  133. public static IServiceCollection RegisterCors(this IServiceCollection services, ConfigurationManager configuration, string corsOrigins)
  134. {
  135. services.AddCors(options =>
  136. {
  137. options.AddPolicy(name: corsOrigins,
  138. builder =>
  139. {
  140. var origins = configuration.GetSection("Cors:Origins").Get<string[]>();
  141. builder.SetIsOriginAllowed(a =>
  142. {
  143. return origins.Any(origin => origin.StartsWith("*.", StringComparison.Ordinal)
  144. ? a.EndsWith(origin[1..], StringComparison.Ordinal)
  145. : a.Equals(origin, StringComparison.Ordinal));
  146. })
  147. .AllowAnyHeader()
  148. .AllowAnyMethod()
  149. .AllowCredentials();
  150. });
  151. });
  152. return services;
  153. }
  154. /// <summary>
  155. /// Mapper
  156. /// </summary>
  157. /// <param name="services"></param>
  158. /// <returns></returns>
  159. public static IServiceCollection RegisterMapper(this IServiceCollection services)
  160. {
  161. var config = TypeAdapterConfig.GlobalSettings;
  162. config.ForDestinationType<IDataPermission>()
  163. .Ignore(d => d.CreatorId)
  164. .Ignore(d => d.CreatorOrgId)
  165. //.Ignore(d => d.CreatorOrgCode)
  166. .Ignore(d => d.AreaId);
  167. config.ForDestinationType<IWorkflow>()
  168. .Ignore(d => d.ExpiredTimeConfigId);
  169. config.ForDestinationType<IHasCreationTime>()
  170. .Ignore(d => d.CreationTime);
  171. config.ForDestinationType<IHasDeletionTime>().Ignore(d => d.DeletionTime);
  172. config.ForDestinationType<ISoftDelete>().Ignore(d => d.IsDeleted);
  173. config.ForDestinationType<IHasModificationTime>().Ignore(d => d.LastModificationTime);
  174. config.ForDestinationType<Entity>().Ignore(d => d.Id);
  175. services.AddSingleton(config);
  176. services.AddScoped<IMapper, ServiceMapper>();
  177. return services;
  178. }
  179. /// <summary>
  180. /// SignalR
  181. /// </summary>
  182. /// <param name="services"></param>
  183. /// <param name="configuration"></param>
  184. /// <returns></returns>
  185. public static IServiceCollection RegisterSignalR(this IServiceCollection services, ConfigurationManager configuration)
  186. {
  187. var connectionString = configuration.GetConnectionString("Redis");
  188. if (string.IsNullOrEmpty(connectionString))
  189. throw new UserFriendlyException("未配置signalR的redis连接");
  190. services.AddSignalR().AddStackExchangeRedis(connectionString, options =>
  191. {
  192. options.Configuration.ChannelPrefix = "Hotline:signalr:";
  193. });
  194. return services;
  195. }
  196. public static IServiceCollection RegisterRepository(this IServiceCollection services)
  197. {
  198. services.AddScoped(typeof(IRepository<>), typeof(BaseRepository<>));
  199. return services;
  200. }
  201. public static IServiceCollection RegisterJob(this IServiceCollection services)
  202. {
  203. services.AddQuartz(d =>
  204. {
  205. d.SchedulerId = "scheduler1";
  206. d.InterruptJobsOnShutdown = true;
  207. d.InterruptJobsOnShutdownWithWait = true;
  208. d.MaxBatchSize = 3;
  209. //load send task
  210. var taskLoadJobKey = new JobKey("task-load-job", "load task");
  211. d.AddJob<TaskLoadJob>(taskLoadJobKey);
  212. d.AddTrigger(t => t
  213. .WithIdentity("task-load-trigger")
  214. .ForJob(taskLoadJobKey)
  215. .StartNow()
  216. .WithCronSchedule("0 0/1 * * * ? ")
  217. );
  218. //execute send task
  219. var taskExecuteJobKey = new JobKey("task-execute-job", "send task");
  220. d.AddJob<TaskExecuteJob>(taskExecuteJobKey);
  221. d.AddTrigger(t => t
  222. .WithIdentity("task-execute-trigger")
  223. .ForJob(taskExecuteJobKey)
  224. .StartNow()
  225. .WithCronSchedule("0/1 * * * * ? ")
  226. );
  227. });
  228. services.AddQuartzServer(d =>
  229. {
  230. d.WaitForJobsToComplete = true;
  231. d.StartDelay = TimeSpan.FromSeconds(5);
  232. });
  233. return services;
  234. }
  235. }
  236. }