something

This commit is contained in:
2025-10-01 01:56:05 +03:00
parent ece9cedb37
commit 40342a0e14
112 changed files with 5468 additions and 5468 deletions

View File

@@ -1,41 +1,41 @@
using LctMonolith.Application.Options;
using LctMonolith.Database.UnitOfWork;
using LctMonolith.Services;
using LctMonolith.Services.Contracts;
using LctMonolith.Services.Interfaces;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace LctMonolith.Application.Extensions;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddApplicationServices(this IServiceCollection services, IConfiguration configuration)
{
// Unit of Work
services.AddScoped<IUnitOfWork, UnitOfWork>();
// Core domain / gamification services
services.AddScoped<ITokenService, TokenService>();
services.AddScoped<IStoreService, StoreService>();
services.AddScoped<INotificationService, NotificationService>();
services.AddScoped<IAnalyticsService, AnalyticsService>();
services.AddScoped<IPlayerService, PlayerService>();
services.AddScoped<IRankService, RankService>();
services.AddScoped<ISkillService, SkillService>();
services.AddScoped<IMissionCategoryService, MissionCategoryService>();
services.AddScoped<IMissionService, MissionService>();
services.AddScoped<IRewardService, RewardService>();
services.AddScoped<IRuleValidationService, RuleValidationService>();
services.AddScoped<IProgressTrackingService, ProgressTrackingService>();
services.AddScoped<IDialogueService, DialogueService>();
services.AddScoped<IInventoryService, InventoryService>();
services.Configure<S3StorageOptions>(configuration.GetSection("S3"));
services.AddSingleton<IFileStorageService, S3FileStorageService>();
services.AddScoped<IProfileService, ProfileService>();
return services;
}
}
using LctMonolith.Application.Options;
using LctMonolith.Database.UnitOfWork;
using LctMonolith.Services;
using LctMonolith.Services.Contracts;
using LctMonolith.Services.Interfaces;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace LctMonolith.Application.Extensions;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddApplicationServices(this IServiceCollection services, IConfiguration configuration)
{
// Unit of Work
services.AddScoped<IUnitOfWork, UnitOfWork>();
// Core domain / gamification services
services.AddScoped<ITokenService, TokenService>();
services.AddScoped<IStoreService, StoreService>();
services.AddScoped<INotificationService, NotificationService>();
services.AddScoped<IAnalyticsService, AnalyticsService>();
services.AddScoped<IPlayerService, PlayerService>();
services.AddScoped<IRankService, RankService>();
services.AddScoped<ISkillService, SkillService>();
services.AddScoped<IMissionCategoryService, MissionCategoryService>();
services.AddScoped<IMissionService, MissionService>();
services.AddScoped<IRewardService, RewardService>();
services.AddScoped<IRuleValidationService, RuleValidationService>();
services.AddScoped<IProgressTrackingService, ProgressTrackingService>();
services.AddScoped<IDialogueService, DialogueService>();
services.AddScoped<IInventoryService, InventoryService>();
services.Configure<S3StorageOptions>(configuration.GetSection("S3"));
services.AddSingleton<IFileStorageService, S3FileStorageService>();
services.AddScoped<IProfileService, ProfileService>();
return services;
}
}

View File

@@ -1,46 +1,46 @@
using System.Net;
using System.Text.Json;
using Serilog;
namespace LctMonolith.Application.Middleware;
/// <summary>
/// Global error handling middleware capturing unhandled exceptions and converting to standardized JSON response.
/// </summary>
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
public ErrorHandlingMiddleware(RequestDelegate next) => _next = next;
public async Task Invoke(HttpContext ctx)
{
try
{
await _next(ctx);
}
catch (OperationCanceledException)
{
// Client aborted request (non-standard 499 code used by some proxies)
if (!ctx.Response.HasStarted)
{
ctx.Response.StatusCode = 499; // Client Closed Request (custom)
}
}
catch (Exception ex)
{
Log.Error(ex, "Unhandled exception");
if (ctx.Response.HasStarted) throw;
ctx.Response.ContentType = "application/json";
ctx.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var payload = new { error = new { message = ex.Message, traceId = ctx.TraceIdentifier } };
await ctx.Response.WriteAsync(JsonSerializer.Serialize(payload));
}
}
}
public static class ErrorHandlingMiddlewareExtensions
{
/// <summary>Adds global error handling middleware.</summary>
public static IApplicationBuilder UseErrorHandling(this IApplicationBuilder app) => app.UseMiddleware<ErrorHandlingMiddleware>();
}
using System.Net;
using System.Text.Json;
using Serilog;
namespace LctMonolith.Application.Middleware;
/// <summary>
/// Global error handling middleware capturing unhandled exceptions and converting to standardized JSON response.
/// </summary>
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
public ErrorHandlingMiddleware(RequestDelegate next) => _next = next;
public async Task Invoke(HttpContext ctx)
{
try
{
await _next(ctx);
}
catch (OperationCanceledException)
{
// Client aborted request (non-standard 499 code used by some proxies)
if (!ctx.Response.HasStarted)
{
ctx.Response.StatusCode = 499; // Client Closed Request (custom)
}
}
catch (Exception ex)
{
Log.Error(ex, "Unhandled exception");
if (ctx.Response.HasStarted) throw;
ctx.Response.ContentType = "application/json";
ctx.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var payload = new { error = new { message = ex.Message, traceId = ctx.TraceIdentifier } };
await ctx.Response.WriteAsync(JsonSerializer.Serialize(payload));
}
}
}
public static class ErrorHandlingMiddlewareExtensions
{
/// <summary>Adds global error handling middleware.</summary>
public static IApplicationBuilder UseErrorHandling(this IApplicationBuilder app) => app.UseMiddleware<ErrorHandlingMiddleware>();
}

View File

@@ -1,14 +1,14 @@
namespace LctMonolith.Application.Options;
/// <summary>
/// JWT issuing configuration loaded from appsettings (section Jwt).
/// </summary>
public class JwtOptions
{
public string Key { get; set; } = string.Empty;
public string Issuer { get; set; } = string.Empty;
public string Audience { get; set; } = string.Empty;
public int AccessTokenMinutes { get; set; } = 60;
public int RefreshTokenDays { get; set; } = 7;
}
namespace LctMonolith.Application.Options;
/// <summary>
/// JWT issuing configuration loaded from appsettings (section Jwt).
/// </summary>
public class JwtOptions
{
public string Key { get; set; } = string.Empty;
public string Issuer { get; set; } = string.Empty;
public string Audience { get; set; } = string.Empty;
public int AccessTokenMinutes { get; set; } = 60;
public int RefreshTokenDays { get; set; } = 7;
}

View File

@@ -1,12 +1,12 @@
namespace LctMonolith.Application.Options;
public class S3StorageOptions
{
public string Endpoint { get; set; } = string.Empty;
public bool UseSsl { get; set; } = true;
public string AccessKey { get; set; } = string.Empty;
public string SecretKey { get; set; } = string.Empty;
public string Bucket { get; set; } = "avatars";
public string? PublicBaseUrl { get; set; } // optional CDN / reverse proxy base
public int PresignExpirationMinutes { get; set; } = 60;
}
namespace LctMonolith.Application.Options;
public class S3StorageOptions
{
public string Endpoint { get; set; } = string.Empty;
public bool UseSsl { get; set; } = true;
public string AccessKey { get; set; } = string.Empty;
public string SecretKey { get; set; } = string.Empty;
public string Bucket { get; set; } = "avatars";
public string? PublicBaseUrl { get; set; } // optional CDN / reverse proxy base
public int PresignExpirationMinutes { get; set; } = 60;
}