/
ivanstrike
/
tasker
Обзор
Документация
Войти
/
ivanstrike
/
tasker
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Controllers/V2/ProjectsController.cs
242 строки
8 KB
ivanstrike
Лабораторная работа 2
08 ноя 2025, 11:16
08 ноя 2025, 11:16
ec39293
Код
Авторство
О чём код?
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using TaskerApi.Data; using TaskerApi.DTOs; using TaskerApi.Models; namespace TaskerApi.Controllers.V2; /// <summary> /// Контроллер для управления проектами (API v2) - идентичен v1 для обратной совместимости /// </summary> [ApiController] [ApiVersion("2.0")] [Route("api/v{version:apiVersion}/[controller]")] [Authorize] public class ProjectsController : ControllerBase { private readonly ApplicationDbContext _context; private readonly ILogger<ProjectsController> _logger; public ProjectsController(ApplicationDbContext context, ILogger<ProjectsController> logger) { _context = context; _logger = logger; } /// <summary> /// Получить все проекты текущего пользователя с пагинацией /// </summary> [HttpGet] [ProducesResponseType(typeof(PaginatedResult<ProjectResponseDto>), StatusCodes.Status200OK)] public async Task<ActionResult<PaginatedResult<ProjectResponseDto>>> GetProjects( [FromQuery] bool includeArchived = false, [FromQuery] int page = 1, [FromQuery] int pageSize = 20) { var userId = GetCurrentUserId(); var query = _context.Projects .Include(p => p.Owner) .Include(p => p.Tasks) .Where(p => p.OwnerId == userId); if (!includeArchived) { query = query.Where(p => !p.IsArchived); } var totalCount = await query.CountAsync(); var pagination = new PaginationParams { Page = page, PageSize = pageSize }; var projects = await query .OrderByDescending(p => p.CreatedAt) .Skip(pagination.Skip) .Take(pagination.PageSize) .Select(p => new ProjectResponseDto { Id = p.Id, Name = p.Name, Description = p.Description, OwnerId = p.OwnerId, OwnerUsername = p.Owner.Username, CreatedAt = p.CreatedAt, UpdatedAt = p.UpdatedAt, IsArchived = p.IsArchived, TaskCount = p.Tasks.Count }) .ToListAsync(); var result = new PaginatedResult<ProjectResponseDto> { Items = projects, Page = pagination.Page, PageSize = pagination.PageSize, TotalCount = totalCount }; Response.Headers.Append("X-Pagination-Page", result.Page.ToString()); Response.Headers.Append("X-Pagination-PageSize", result.PageSize.ToString()); Response.Headers.Append("X-Pagination-TotalCount", result.TotalCount.ToString()); Response.Headers.Append("X-Pagination-TotalPages", result.TotalPages.ToString()); return Ok(result); } /// <summary> /// Получить проект по ID /// </summary> [HttpGet("{id}")] [ProducesResponseType(typeof(ProjectResponseDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task<ActionResult<ProjectResponseDto>> GetProject(Guid id) { var userId = GetCurrentUserId(); var project = await _context.Projects .Include(p => p.Owner) .Include(p => p.Tasks) .FirstOrDefaultAsync(p => p.Id == id && p.OwnerId == userId); if (project == null) { return NotFound(new { message = "Project not found" }); } var response = new ProjectResponseDto { Id = project.Id, Name = project.Name, Description = project.Description, OwnerId = project.OwnerId, OwnerUsername = project.Owner.Username, CreatedAt = project.CreatedAt, UpdatedAt = project.UpdatedAt, IsArchived = project.IsArchived, TaskCount = project.Tasks.Count }; return Ok(response); } /// <summary> /// Создать новый проект /// </summary> [HttpPost] [ProducesResponseType(typeof(ProjectResponseDto), StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task<ActionResult<ProjectResponseDto>> CreateProject([FromBody] CreateProjectDto dto) { var userId = GetCurrentUserId(); var project = new Project { Name = dto.Name, Description = dto.Description, OwnerId = userId, CreatedAt = DateTime.UtcNow }; _context.Projects.Add(project); await _context.SaveChangesAsync(); await _context.Entry(project).Reference(p => p.Owner).LoadAsync(); var response = new ProjectResponseDto { Id = project.Id, Name = project.Name, Description = project.Description, OwnerId = project.OwnerId, OwnerUsername = project.Owner.Username, CreatedAt = project.CreatedAt, UpdatedAt = project.UpdatedAt, IsArchived = project.IsArchived, TaskCount = 0 }; _logger.LogInformation("Project created (V2): {ProjectId} by user {UserId}", project.Id, userId); return CreatedAtAction(nameof(GetProject), new { id = project.Id, version = "2.0" }, response); } /// <summary> /// Обновить проект /// </summary> [HttpPut("{id}")] [ProducesResponseType(typeof(ProjectResponseDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task<ActionResult<ProjectResponseDto>> UpdateProject(Guid id, [FromBody] UpdateProjectDto dto) { var userId = GetCurrentUserId(); var project = await _context.Projects .Include(p => p.Owner) .FirstOrDefaultAsync(p => p.Id == id && p.OwnerId == userId); if (project == null) { return NotFound(new { message = "Project not found" }); } if (dto.Name != null) project.Name = dto.Name; if (dto.Description != null) project.Description = dto.Description; if (dto.IsArchived.HasValue) project.IsArchived = dto.IsArchived.Value; project.UpdatedAt = DateTime.UtcNow; await _context.SaveChangesAsync(); var taskCount = await _context.Tasks.CountAsync(t => t.ProjectId == id); var response = new ProjectResponseDto { Id = project.Id, Name = project.Name, Description = project.Description, OwnerId = project.OwnerId, OwnerUsername = project.Owner.Username, CreatedAt = project.CreatedAt, UpdatedAt = project.UpdatedAt, IsArchived = project.IsArchived, TaskCount = taskCount }; _logger.LogInformation("Project updated (V2): {ProjectId} by user {UserId}", project.Id, userId); return Ok(response); } /// <summary> /// Удалить проект /// </summary> [HttpDelete("{id}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task<IActionResult> DeleteProject(Guid id) { var userId = GetCurrentUserId(); var project = await _context.Projects .FirstOrDefaultAsync(p => p.Id == id && p.OwnerId == userId); if (project == null) { return NotFound(new { message = "Project not found" }); } _context.Projects.Remove(project); await _context.SaveChangesAsync(); _logger.LogInformation("Project deleted (V2): {ProjectId} by user {UserId}", project.Id, userId); return NoContent(); } private Guid GetCurrentUserId() { return Guid.Parse(User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value ?? "0"); } }