Add admin page for bundle
This commit is contained in:
232
src/Managing.Api/Controllers/AdminController.cs
Normal file
232
src/Managing.Api/Controllers/AdminController.cs
Normal file
@@ -0,0 +1,232 @@
|
||||
using Managing.Api.Models.Responses;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Abstractions.Shared;
|
||||
using Managing.Application.Shared;
|
||||
using Managing.Domain.Backtests;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Api.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Controller for admin operations.
|
||||
/// Provides endpoints for administrative tasks that require admin authorization.
|
||||
/// All endpoints in this controller require admin access.
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("[controller]")]
|
||||
[Produces("application/json")]
|
||||
public class AdminController : BaseController
|
||||
{
|
||||
private readonly IBacktester _backtester;
|
||||
private readonly IAdminConfigurationService _adminService;
|
||||
private readonly ILogger<AdminController> _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AdminController"/> class.
|
||||
/// </summary>
|
||||
/// <param name="userService">The service for user management.</param>
|
||||
/// <param name="backtester">The service for backtesting operations.</param>
|
||||
/// <param name="adminService">The admin configuration service for authorization checks.</param>
|
||||
/// <param name="logger">The logger instance.</param>
|
||||
public AdminController(
|
||||
IUserService userService,
|
||||
IBacktester backtester,
|
||||
IAdminConfigurationService adminService,
|
||||
ILogger<AdminController> logger) : base(userService)
|
||||
{
|
||||
_backtester = backtester;
|
||||
_adminService = adminService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the current user is an admin
|
||||
/// </summary>
|
||||
private async Task<bool> IsUserAdmin()
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = await GetUser();
|
||||
if (user == null)
|
||||
return false;
|
||||
|
||||
return await _adminService.IsUserAdminAsync(user.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error checking if user is admin");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves paginated bundle backtest requests for admin users.
|
||||
/// This endpoint returns all bundle backtest requests without user filtering.
|
||||
/// </summary>
|
||||
/// <param name="page">Page number (defaults to 1)</param>
|
||||
/// <param name="pageSize">Number of items per page (defaults to 50, max 100)</param>
|
||||
/// <param name="sortBy">Field to sort by (defaults to "CreatedAt")</param>
|
||||
/// <param name="sortOrder">Sort order - "asc" or "desc" (defaults to "desc")</param>
|
||||
/// <param name="nameContains">Filter by name contains</param>
|
||||
/// <param name="status">Filter by status (Pending, Running, Completed, Failed, Saved)</param>
|
||||
/// <param name="userId">Filter by user ID</param>
|
||||
/// <param name="userNameContains">Filter by user name contains</param>
|
||||
/// <param name="totalBacktestsMin">Filter by minimum total backtests</param>
|
||||
/// <param name="totalBacktestsMax">Filter by maximum total backtests</param>
|
||||
/// <param name="completedBacktestsMin">Filter by minimum completed backtests</param>
|
||||
/// <param name="completedBacktestsMax">Filter by maximum completed backtests</param>
|
||||
/// <param name="progressPercentageMin">Filter by minimum progress percentage (0-100)</param>
|
||||
/// <param name="progressPercentageMax">Filter by maximum progress percentage (0-100)</param>
|
||||
/// <param name="createdAtFrom">Filter by created date from</param>
|
||||
/// <param name="createdAtTo">Filter by created date to</param>
|
||||
/// <returns>A paginated list of bundle backtest requests.</returns>
|
||||
[HttpGet]
|
||||
[Route("BundleBacktestRequests/Paginated")]
|
||||
public async Task<ActionResult<PaginatedBundleBacktestRequestsResponse>> GetBundleBacktestRequestsPaginated(
|
||||
[FromQuery] int page = 1,
|
||||
[FromQuery] int pageSize = 50,
|
||||
[FromQuery] BundleBacktestRequestSortableColumn sortBy = BundleBacktestRequestSortableColumn.CreatedAt,
|
||||
[FromQuery] string sortOrder = "desc",
|
||||
[FromQuery] string? nameContains = null,
|
||||
[FromQuery] BundleBacktestRequestStatus? status = null,
|
||||
[FromQuery] int? userId = null,
|
||||
[FromQuery] string? userNameContains = null,
|
||||
[FromQuery] int? totalBacktestsMin = null,
|
||||
[FromQuery] int? totalBacktestsMax = null,
|
||||
[FromQuery] int? completedBacktestsMin = null,
|
||||
[FromQuery] int? completedBacktestsMax = null,
|
||||
[FromQuery] double? progressPercentageMin = null,
|
||||
[FromQuery] double? progressPercentageMax = null,
|
||||
[FromQuery] DateTime? createdAtFrom = null,
|
||||
[FromQuery] DateTime? createdAtTo = null)
|
||||
{
|
||||
if (!await IsUserAdmin())
|
||||
{
|
||||
_logger.LogWarning("Non-admin user attempted to access admin bundle backtest requests endpoint");
|
||||
return StatusCode(403, new { error = "Only admin users can access this endpoint" });
|
||||
}
|
||||
|
||||
if (page < 1)
|
||||
{
|
||||
return BadRequest("Page must be greater than 0");
|
||||
}
|
||||
|
||||
if (pageSize < 1 || pageSize > 100)
|
||||
{
|
||||
return BadRequest("Page size must be between 1 and 100");
|
||||
}
|
||||
|
||||
if (sortOrder != "asc" && sortOrder != "desc")
|
||||
{
|
||||
return BadRequest("Sort order must be 'asc' or 'desc'");
|
||||
}
|
||||
|
||||
// Validate progress percentage ranges [0,100]
|
||||
if (progressPercentageMin.HasValue && (progressPercentageMin < 0 || progressPercentageMin > 100))
|
||||
{
|
||||
return BadRequest("progressPercentageMin must be between 0 and 100");
|
||||
}
|
||||
|
||||
if (progressPercentageMax.HasValue && (progressPercentageMax < 0 || progressPercentageMax > 100))
|
||||
{
|
||||
return BadRequest("progressPercentageMax must be between 0 and 100");
|
||||
}
|
||||
|
||||
if (progressPercentageMin.HasValue && progressPercentageMax.HasValue && progressPercentageMin > progressPercentageMax)
|
||||
{
|
||||
return BadRequest("progressPercentageMin must be less than or equal to progressPercentageMax");
|
||||
}
|
||||
|
||||
// Build filter
|
||||
var filter = new BundleBacktestRequestsFilter
|
||||
{
|
||||
NameContains = string.IsNullOrWhiteSpace(nameContains) ? null : nameContains.Trim(),
|
||||
Status = status,
|
||||
UserId = userId,
|
||||
UserNameContains = string.IsNullOrWhiteSpace(userNameContains) ? null : userNameContains.Trim(),
|
||||
TotalBacktestsMin = totalBacktestsMin,
|
||||
TotalBacktestsMax = totalBacktestsMax,
|
||||
CompletedBacktestsMin = completedBacktestsMin,
|
||||
CompletedBacktestsMax = completedBacktestsMax,
|
||||
ProgressPercentageMin = progressPercentageMin,
|
||||
ProgressPercentageMax = progressPercentageMax,
|
||||
CreatedAtFrom = createdAtFrom,
|
||||
CreatedAtTo = createdAtTo
|
||||
};
|
||||
|
||||
var (bundleRequests, totalCount) =
|
||||
await _backtester.GetBundleBacktestRequestsPaginatedAsync(
|
||||
page,
|
||||
pageSize,
|
||||
sortBy,
|
||||
sortOrder,
|
||||
filter);
|
||||
|
||||
var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);
|
||||
|
||||
var response = new PaginatedBundleBacktestRequestsResponse
|
||||
{
|
||||
BundleRequests = bundleRequests.Select(b => new BundleBacktestRequestListItemResponse
|
||||
{
|
||||
RequestId = b.RequestId,
|
||||
Name = b.Name,
|
||||
Version = b.Version,
|
||||
Status = b.Status.ToString(),
|
||||
CreatedAt = b.CreatedAt,
|
||||
CompletedAt = b.CompletedAt,
|
||||
UpdatedAt = b.UpdatedAt,
|
||||
TotalBacktests = b.TotalBacktests,
|
||||
CompletedBacktests = b.CompletedBacktests,
|
||||
FailedBacktests = b.FailedBacktests,
|
||||
ProgressPercentage = b.ProgressPercentage,
|
||||
UserId = b.User?.Id,
|
||||
UserName = b.User?.Name,
|
||||
ErrorMessage = b.ErrorMessage,
|
||||
CurrentBacktest = b.CurrentBacktest,
|
||||
EstimatedTimeRemainingSeconds = b.EstimatedTimeRemainingSeconds
|
||||
}),
|
||||
TotalCount = totalCount,
|
||||
CurrentPage = page,
|
||||
PageSize = pageSize,
|
||||
TotalPages = totalPages,
|
||||
HasNextPage = page < totalPages,
|
||||
HasPreviousPage = page > 1
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a summary of bundle backtest requests grouped by status with counts.
|
||||
/// Admin only endpoint.
|
||||
/// </summary>
|
||||
/// <returns>Summary statistics of bundle backtest requests</returns>
|
||||
[HttpGet]
|
||||
[Route("BundleBacktestRequests/Summary")]
|
||||
public async Task<ActionResult<BundleBacktestRequestSummaryResponse>> GetBundleBacktestRequestsSummary()
|
||||
{
|
||||
if (!await IsUserAdmin())
|
||||
{
|
||||
_logger.LogWarning("Non-admin user attempted to get bundle backtest requests summary");
|
||||
return StatusCode(403, new { error = "Only admin users can access bundle backtest requests summary" });
|
||||
}
|
||||
|
||||
var summary = await _backtester.GetBundleBacktestRequestsSummaryAsync();
|
||||
|
||||
var response = new BundleBacktestRequestSummaryResponse
|
||||
{
|
||||
StatusSummary = summary.StatusCounts.Select(s => new BundleBacktestRequestStatusSummary
|
||||
{
|
||||
Status = s.Status.ToString(),
|
||||
Count = s.Count
|
||||
}).ToList(),
|
||||
TotalRequests = summary.TotalRequests
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user