using System.Text; using Azaion.Common; using Azaion.Common.Configs; using Azaion.Common.Database; using Azaion.Common.Entities; using Azaion.Common.Requests; using Azaion.Services; using FluentValidation; using FluentValidation.AspNetCore; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; var builder = WebApplication.CreateBuilder(args); builder.WebHost.ConfigureKestrel(o => o.Limits.MaxRequestBodySize = 209715200); //increase upload limit up to 200mb var jwtConfig = builder.Configuration.GetSection(nameof(JwtConfig)).Get(); if (jwtConfig == null || string.IsNullOrEmpty(jwtConfig.Secret)) throw new Exception("Missing configuration section: JwtConfig"); var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtConfig.Secret)); builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(o => { o.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = jwtConfig.Issuer, ValidAudience = jwtConfig.Audience, IssuerSigningKey = signingKey }; }); var apiAdminPolicy = new AuthorizationPolicyBuilder().RequireRole(RoleEnum.ApiAdmin.ToString()).Build(); builder.Services.AddAuthorization(o => o.AddPolicy("apiAdminPolicy", apiAdminPolicy)); builder.Services.AddHttpContextAccessor(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo {Title = "Azaion.API", Version = "v1"}); c.CustomSchemaIds(type => type.ToString()); var jwtSecurityScheme = new OpenApiSecurityScheme { Scheme = "bearer", BearerFormat = "JWT", Name = "JWT Authentication", In = ParameterLocation.Header, Type = SecuritySchemeType.Http, Description = "Put **_ONLY_** your JWT Bearer token on textbox below!", Reference = new OpenApiReference { Id = JwtBearerDefaults.AuthenticationScheme, Type = ReferenceType.SecurityScheme } }; c.AddSecurityDefinition(jwtSecurityScheme.Reference.Id, jwtSecurityScheme); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { jwtSecurityScheme, Array.Empty() } }); }); builder.Services.Configure(builder.Configuration.GetSection(nameof(ResourcesConfig))); builder.Services.Configure(builder.Configuration.GetSection(nameof(JwtConfig))); builder.Services.Configure(builder.Configuration.GetSection(nameof(ConnectionStrings))); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddValidatorsFromAssemblyContaining(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseAuthentication(); app.UseAuthorization(); app.MapPost("/login", async (LoginRequest request, IUserService userService, IAuthService authService, CancellationToken cancellationToken) => { var user = await userService.ValidateUser(request, cancellationToken: cancellationToken); return Results.Ok(new { Token = authService.CreateToken(user)}); }); app.MapPost("/register-user", async (RegisterUserRequest registerUserRequest, IUserService userService, CancellationToken cancellationToken) => await userService.RegisterUser(registerUserRequest, cancellationToken)) .RequireAuthorization(apiAdminPolicy); app.MapPost("/resources", async (ResourceEnum resourceEnum, IFormFile data, IResourcesService resourceService, CancellationToken cancellationToken) => await resourceService.SaveResource(resourceEnum, data, cancellationToken)) .Accepts("multipart/form-data") .RequireAuthorization(apiAdminPolicy) .DisableAntiforgery(); app.MapPost("/resources/reset-hardware", async (string email, IUserService userService, CancellationToken cancellationToken) => await userService.UpdateHardwareId(email, null!, cancellationToken)); app.MapPost("/resources/get", async (GetResourceRequest request, IAuthService authService, IUserService userService, IResourcesService resourcesService, CancellationToken cancellationToken) => { var user = authService.CurrentUser; if (user == null) throw new UnauthorizedAccessException(); if (string.IsNullOrEmpty(user.HardwareId)) { await userService.UpdateHardwareId(user.Email, request.HardwareId); user.HardwareId = request.HardwareId; } if (user.HardwareId != request.HardwareId) throw new BusinessException(ExceptionEnum.HardwareIdMismatch, "Hardware mismatch! You are not authorized to access this resource from this hardware."); var ms = new MemoryStream(); var key = Security.MakeEncryptionKey(user.Email, request.Password); var filename = await resourcesService.GetEncryptedResource(request.ResourceEnum, key, ms, cancellationToken); return Results.File(ms, "application/octet-stream", filename); }).RequireAuthorization(); app.Run();