Refactor
Some checks failed
Code Coverage / Generate Coverage Report (push) Has been cancelled
Tests / Run Tests (9.0.x) (push) Has been cancelled
Tests / Docker Build Test (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled

This commit is contained in:
Yaojia Wang
2025-11-03 21:02:14 +01:00
parent 5c541ddb79
commit a220e5d5d7
64 changed files with 3867 additions and 732 deletions

View File

@@ -11,22 +11,12 @@ namespace ColaFlow.API.Controllers;
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
public class AuthController(
IMediator mediator,
IRefreshTokenService refreshTokenService,
ILogger<AuthController> logger)
: ControllerBase
{
private readonly IMediator _mediator;
private readonly IRefreshTokenService _refreshTokenService;
private readonly ILogger<AuthController> _logger;
public AuthController(
IMediator mediator,
IRefreshTokenService refreshTokenService,
ILogger<AuthController> logger)
{
_mediator = mediator;
_refreshTokenService = refreshTokenService;
_logger = logger;
}
/// <summary>
/// Login with email and password
/// </summary>
@@ -44,7 +34,7 @@ public class AuthController : ControllerBase
userAgent
);
var result = await _mediator.Send(command);
var result = await mediator.Send(command);
return Ok(result);
}
@@ -89,7 +79,7 @@ public class AuthController : ControllerBase
var ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString();
var userAgent = HttpContext.Request.Headers["User-Agent"].ToString();
var (accessToken, newRefreshToken) = await _refreshTokenService.RefreshTokenAsync(
var (accessToken, newRefreshToken) = await refreshTokenService.RefreshTokenAsync(
request.RefreshToken,
ipAddress,
userAgent,
@@ -105,7 +95,7 @@ public class AuthController : ControllerBase
}
catch (UnauthorizedAccessException ex)
{
_logger.LogWarning(ex, "Refresh token failed");
logger.LogWarning(ex, "Refresh token failed");
return Unauthorized(new { message = "Invalid or expired refresh token" });
}
}
@@ -121,7 +111,7 @@ public class AuthController : ControllerBase
{
var ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString();
await _refreshTokenService.RevokeTokenAsync(
await refreshTokenService.RevokeTokenAsync(
request.RefreshToken,
ipAddress,
HttpContext.RequestAborted);
@@ -130,7 +120,7 @@ public class AuthController : ControllerBase
}
catch (Exception ex)
{
_logger.LogError(ex, "Logout failed");
logger.LogError(ex, "Logout failed");
return BadRequest(new { message = "Logout failed" });
}
}
@@ -146,7 +136,7 @@ public class AuthController : ControllerBase
{
var userId = Guid.Parse(User.FindFirstValue("user_id")!);
await _refreshTokenService.RevokeAllUserTokensAsync(
await refreshTokenService.RevokeAllUserTokensAsync(
userId,
HttpContext.RequestAborted);
@@ -154,7 +144,7 @@ public class AuthController : ControllerBase
}
catch (Exception ex)
{
_logger.LogError(ex, "Logout from all devices failed");
logger.LogError(ex, "Logout from all devices failed");
return BadRequest(new { message = "Logout failed" });
}
}

View File

@@ -13,14 +13,9 @@ namespace ColaFlow.API.Controllers;
/// </summary>
[ApiController]
[Route("api/v1")]
public class EpicsController : ControllerBase
public class EpicsController(IMediator mediator) : ControllerBase
{
private readonly IMediator _mediator;
public EpicsController(IMediator mediator)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
}
private readonly IMediator _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
/// <summary>
/// Get all epics for a project

View File

@@ -12,14 +12,9 @@ namespace ColaFlow.API.Controllers;
/// </summary>
[ApiController]
[Route("api/v1/[controller]")]
public class ProjectsController : ControllerBase
public class ProjectsController(IMediator mediator) : ControllerBase
{
private readonly IMediator _mediator;
public ProjectsController(IMediator mediator)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
}
private readonly IMediator _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
/// <summary>
/// Get all projects

View File

@@ -16,14 +16,9 @@ namespace ColaFlow.API.Controllers;
/// </summary>
[ApiController]
[Route("api/v1")]
public class StoriesController : ControllerBase
public class StoriesController(IMediator mediator) : ControllerBase
{
private readonly IMediator _mediator;
public StoriesController(IMediator mediator)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
}
private readonly IMediator _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
/// <summary>
/// Get story by ID

View File

@@ -17,14 +17,9 @@ namespace ColaFlow.API.Controllers;
/// </summary>
[ApiController]
[Route("api/v1")]
public class TasksController : ControllerBase
public class TasksController(IMediator mediator) : ControllerBase
{
private readonly IMediator _mediator;
public TasksController(IMediator mediator)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
}
private readonly IMediator _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
/// <summary>
/// Get task by ID

View File

@@ -11,15 +11,8 @@ namespace ColaFlow.API.Controllers;
[ApiController]
[Route("api/tenants/{tenantId}/users")]
[Authorize]
public class TenantUsersController : ControllerBase
public class TenantUsersController(IMediator mediator) : ControllerBase
{
private readonly IMediator _mediator;
public TenantUsersController(IMediator mediator)
{
_mediator = mediator;
}
/// <summary>
/// List all users in a tenant with their roles
/// </summary>
@@ -41,7 +34,7 @@ public class TenantUsersController : ControllerBase
return StatusCode(403, new { error = "Access denied: You can only manage users in your own tenant" });
var query = new ListTenantUsersQuery(tenantId, pageNumber, pageSize, search);
var result = await _mediator.Send(query);
var result = await mediator.Send(query);
return Ok(result);
}
@@ -72,7 +65,7 @@ public class TenantUsersController : ControllerBase
var currentUserId = Guid.Parse(currentUserIdClaim);
var command = new AssignUserRoleCommand(tenantId, userId, request.Role, currentUserId);
await _mediator.Send(command);
await mediator.Send(command);
return Ok(new { Message = "Role assigned successfully" });
}
@@ -102,7 +95,7 @@ public class TenantUsersController : ControllerBase
var currentUserId = Guid.Parse(currentUserIdClaim);
var command = new RemoveUserFromTenantCommand(tenantId, userId, currentUserId, null);
await _mediator.Send(command);
await mediator.Send(command);
return Ok(new { Message = "User removed from tenant successfully" });
}

View File

@@ -7,22 +7,15 @@ namespace ColaFlow.API.Controllers;
[ApiController]
[Route("api/[controller]")]
public class TenantsController : ControllerBase
public class TenantsController(IMediator mediator) : ControllerBase
{
private readonly IMediator _mediator;
public TenantsController(IMediator mediator)
{
_mediator = mediator;
}
/// <summary>
/// Register a new tenant (company signup)
/// </summary>
[HttpPost("register")]
public async Task<IActionResult> Register([FromBody] RegisterTenantCommand command)
{
var result = await _mediator.Send(command);
var result = await mediator.Send(command);
return Ok(result);
}
@@ -33,7 +26,7 @@ public class TenantsController : ControllerBase
public async Task<IActionResult> GetBySlug(string slug)
{
var query = new GetTenantBySlugQuery(slug);
var result = await _mediator.Send(query);
var result = await mediator.Send(query);
if (result == null)
return NotFound(new { message = "Tenant not found" });
@@ -48,7 +41,7 @@ public class TenantsController : ControllerBase
public async Task<IActionResult> CheckSlug(string slug)
{
var query = new GetTenantBySlugQuery(slug);
var result = await _mediator.Send(query);
var result = await mediator.Send(query);
return Ok(new { available = result == null });
}

View File

@@ -11,14 +11,9 @@ namespace ColaFlow.API.Handlers;
/// Global exception handler using IExceptionHandler (.NET 8+)
/// Handles all unhandled exceptions and converts them to ProblemDetails responses
/// </summary>
public sealed class GlobalExceptionHandler : IExceptionHandler
public sealed class GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger) : IExceptionHandler
{
private readonly ILogger<GlobalExceptionHandler> _logger;
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
private readonly ILogger<GlobalExceptionHandler> _logger = logger ?? throw new ArgumentNullException(nameof(logger));
public async ValueTask<bool> TryHandleAsync(
HttpContext httpContext,