|
1 | 1 | using AdvancedTodoList.Application.Mapping; |
2 | | -using AdvancedTodoList.Application.Options; |
3 | | -using AdvancedTodoList.Application.Services.Definitions; |
4 | | -using AdvancedTodoList.Application.Services.Definitions.Auth; |
5 | | -using AdvancedTodoList.Application.Services.Implementations; |
6 | | -using AdvancedTodoList.Application.Services.Implementations.Auth; |
7 | | -using AdvancedTodoList.Application.Validation; |
8 | | -using AdvancedTodoList.Core.Models.Auth; |
9 | | -using AdvancedTodoList.Core.Models.TodoLists; |
10 | | -using AdvancedTodoList.Core.Models.TodoLists.Members; |
11 | | -using AdvancedTodoList.Core.Repositories; |
12 | | -using AdvancedTodoList.Infrastructure.Data; |
13 | | -using AdvancedTodoList.Infrastructure.Repositories; |
14 | | -using FluentValidation; |
15 | | -using Microsoft.AspNetCore.Identity; |
16 | | -using Microsoft.EntityFrameworkCore; |
17 | | -using Microsoft.IdentityModel.Tokens; |
18 | | -using Microsoft.OpenApi.Models; |
| 2 | +using AdvancedTodoList.WebApp.Extensions.ServiceCollection; |
| 3 | +using AdvancedTodoList.WebApp.Extensions.WebAppBuilder; |
19 | 4 | using SharpGrip.FluentValidation.AutoValidation.Mvc.Extensions; |
20 | | -using System.Reflection; |
21 | | -using System.Text; |
22 | | -using System.Text.Json.Serialization; |
23 | 5 |
|
24 | 6 | var builder = WebApplication.CreateBuilder(args); |
25 | 7 |
|
26 | | -// Add services to the container. |
27 | | -builder.Services.AddControllers() |
28 | | - .AddJsonOptions(options => |
29 | | - { |
30 | | - options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; |
31 | | - }); |
32 | | -builder.Services.AddEndpointsApiExplorer(); |
33 | | -builder.Services.AddSwaggerGen(options => |
34 | | -{ |
35 | | - options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme |
36 | | - { |
37 | | - In = ParameterLocation.Header, |
38 | | - Description = "Please enter access token (JWT)", |
39 | | - Name = "Authorization", |
40 | | - Type = SecuritySchemeType.ApiKey |
41 | | - }); |
42 | | - |
43 | | - var scheme = new OpenApiSecurityScheme |
44 | | - { |
45 | | - Reference = new OpenApiReference |
46 | | - { |
47 | | - Type = ReferenceType.SecurityScheme, |
48 | | - Id = "Bearer" |
49 | | - } |
50 | | - }; |
51 | | - |
52 | | - options.AddSecurityRequirement(new OpenApiSecurityRequirement { { scheme, Array.Empty<string>() } }); |
53 | | - |
54 | | - var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; |
55 | | - options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); |
56 | | -}); |
57 | | - |
58 | | -// Configure antiforgery |
59 | | -builder.Services.AddAntiforgery(options => options.HeaderName = "X-XSRF-Token"); |
60 | | - |
61 | | -// Configure auth |
62 | | -string? jwtSecret = builder.Configuration["Auth:AccessToken:SecretKey"] ?? |
63 | | - throw new InvalidOperationException("JWT secret is not configured"); |
64 | | -builder.Services.AddAuthentication() |
65 | | - .AddJwtBearer(options => |
66 | | - { |
67 | | - options.SaveToken = true; |
68 | | - options.TokenValidationParameters = new TokenValidationParameters |
69 | | - { |
70 | | - ClockSkew = TimeSpan.FromSeconds(5), |
71 | | - ValidIssuer = builder.Configuration["Auth:AccessToken:ValidIssuer"], |
72 | | - ValidAudience = builder.Configuration["Auth:AccessToken:ValidAudience"], |
73 | | - IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecret)) |
74 | | - }; |
75 | | - }); |
76 | | -builder.Services.AddAuthorizationBuilder(); |
| 8 | +builder.Services |
| 9 | + .AddEndpoints() |
| 10 | + .AddApplicationSwagger() |
| 11 | + .AddApplicationAntiforgery(); |
77 | 12 |
|
78 | | -// Get connection string |
79 | | -string? connectionString = |
80 | | - builder.Configuration.GetConnectionString("DefaultConnection") ?? |
81 | | - throw new InvalidOperationException("Connection string is not specified in 'ConnectionStrings:DefaultConnection'"); |
82 | | - |
83 | | -// Configure DbContext |
84 | | -builder.Services.AddDbContext<ApplicationDbContext>( |
85 | | - o => o.UseSqlServer(connectionString, |
86 | | - b => b.MigrationsAssembly("AdvancedTodoList.Infrastructure")) |
87 | | - ); |
88 | | - |
89 | | -builder.Services.AddIdentityCore<ApplicationUser>(options => |
90 | | - { |
91 | | - options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._"; |
92 | | - }) |
93 | | - .AddEntityFrameworkStores<ApplicationDbContext>() |
94 | | - .AddApiEndpoints(); |
| 13 | +builder.AddAuth(); |
| 14 | +builder.AddDataAccess(); |
95 | 15 |
|
96 | 16 | // Bind options |
97 | | -builder.Services.Configure<AccessTokenOptions>( |
98 | | - builder.Configuration.GetSection("Auth:AccessToken")); |
99 | | -builder.Services.Configure<RefreshTokenOptions>( |
100 | | - builder.Configuration.GetSection("Auth:RefreshToken")); |
101 | | -builder.Services.Configure<InvitationLinkOptions>( |
102 | | - builder.Configuration.GetSection("Todo:InvitationLink")); |
| 17 | +builder.ConfigureApplicationOptions(); |
103 | 18 |
|
104 | 19 | // Register application services |
105 | | -builder.Services.AddScoped<IAuthService, AuthService>(); |
106 | | -builder.Services.AddScoped<IPermissionsChecker, PermissionsChecker>(); |
107 | | -builder.Services.AddScoped<ITodoListsService, TodoListsService>(); |
108 | | -builder.Services.AddScoped<ITodoItemsService, TodoItemsService>(); |
109 | | -builder.Services.AddScoped<ITodoItemCategoriesService, TodoItemCategoriesService>(); |
110 | | -builder.Services.AddScoped<ITodoListMembersService, TodoListMembersService>(); |
111 | | -builder.Services.AddScoped<ITodoListRolesService, TodoListRolesService>(); |
112 | | -builder.Services.AddScoped<IInvitationLinksService, InvitationLinksService>(); |
113 | | -builder.Services.AddScoped<IEntityExistenceChecker, EntityExistenceChecker>(); |
114 | | -builder.Services.AddSingleton<IAccessTokensService, AccessTokensService>(); |
115 | | -builder.Services.AddScoped<IRefreshTokensService, RefreshTokensService>(); |
116 | | -builder.Services.AddScoped(typeof(ITodoListDependantEntitiesService<,>), |
117 | | - typeof(TodoListDependantEntitiesService<,>)); |
118 | | -// Register unit of work |
119 | | -builder.Services.AddScoped<IUnitOfWork, UnitOfWork>(); |
120 | | -// Register application repositories |
121 | | -builder.Services.AddScoped<IRepository<TodoList, string>, TodoListRepository>(); |
122 | | -builder.Services.AddScoped<IRepository<TodoItem, int>, TodoItemsRepository>(); |
123 | | -builder.Services.AddScoped<IRepository<TodoItemCategory, int>, TodoItemCategoriesRepository>(); |
124 | | -builder.Services.AddScoped<IRepository<InvitationLink, int>, InvitationLinksRepository>(); |
125 | | -builder.Services.AddScoped<IInvitationLinksRepository, InvitationLinksRepository>(); |
126 | | -builder.Services.AddScoped<ITodoListMembersRepository, TodoListMembersRepository>(); |
127 | | -builder.Services.AddScoped<IRepository<TodoListMember, int>, TodoListMembersRepository>(); |
128 | | -builder.Services.AddScoped<IRepository<TodoListRole, int>, TodoListRolesRepository>(); |
129 | | -builder.Services.AddScoped<IRepository<UserRefreshToken, int>, UserRefreshTokensRepository>(); |
130 | | -builder.Services.AddScoped<IUserRefreshTokensRepository, UserRefreshTokensRepository>(); |
| 20 | +builder.Services |
| 21 | + .AddDataAccessServices() |
| 22 | + .AddApplicationServices(); |
131 | 23 |
|
132 | 24 | // Apply mapping settings |
133 | 25 | MappingGlobalSettings.Apply(); |
134 | 26 |
|
135 | 27 | // Add fluent validation |
136 | | -ValidatorOptions.Global.LanguageManager.Enabled = false; // Disable localization |
137 | | -builder.Services.AddValidatorsFromAssemblyContaining<TodoItemCreateDtoValidator>(); |
138 | | - |
139 | | -// Enable auto validation by SharpGrip |
140 | | -builder.Services.AddFluentValidationAutoValidation(configuration => |
141 | | -{ |
142 | | - // Disable the built-in .NET model (data annotations) validation. |
143 | | - configuration.DisableBuiltInModelValidation = true; |
144 | | - // Enable validation for parameters bound from 'BindingSource.Body' binding sources. |
145 | | - configuration.EnableBodyBindingSourceAutomaticValidation = true; |
146 | | - // Enable validation for parameters bound from 'BindingSource.Query' binding sources. |
147 | | - configuration.EnableQueryBindingSourceAutomaticValidation = true; |
148 | | -}); |
149 | | - |
| 28 | +builder.Services |
| 29 | + .AddFluentValidation() |
| 30 | + .AddFluentValidationAutoValidation(); |
150 | 31 |
|
151 | 32 | var app = builder.Build(); |
152 | 33 |
|
|
164 | 45 | app.MapControllers(); |
165 | 46 |
|
166 | 47 | app.Run(); |
| 48 | + |
167 | 49 | public partial class Program { } |
0 commit comments