using AsbCloudApp.Data; using AsbCloudApp.Requests; using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System.IO; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Repositories; namespace AsbCloudWebApi.Controllers { /// <summary> /// Хранение файлов /// </summary> [Route("api/well/{idWell}/files")] [ApiController] [Authorize] public class FileController : ControllerBase { private readonly FileService fileService; private readonly IWellService wellService; public FileController(FileService fileService, IWellService wellService) { this.fileService = fileService; this.wellService = wellService; } /// <summary> /// Сохраняет переданные файлы и информацию о них /// </summary> /// <param name="idWell">id скважины</param> /// <param name="idCategory">id категории файла</param> /// <param name="files">Коллекция файлов</param> /// <param name="userRepository">dependency</param> /// <param name="token"> Токен отмены задачи </param> /// <returns></returns> [HttpPost] [Permission] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task<IActionResult> SaveFilesAsync(int idWell, int idCategory, [FromForm] IFormFileCollection files, [FromServices] IUserRepository userRepository, CancellationToken token) { int? idCompany = User.GetCompanyId(); int? idUser = User.GetUserId(); if (idCompany is null || idUser is null) return Forbid(); if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) return Forbid(); if (!userRepository.HasPermission((int)idUser, $"File.edit{idCategory}")) return Forbid(); foreach (var file in files) { var fileStream = file.OpenReadStream(); await fileService.SaveAsync(idWell, idUser ?? 0, idCategory, file.FileName, fileStream, token).ConfigureAwait(false); } return Ok(); } /// <summary> /// Возвращает информацию о файлах для скважины в выбраной категории /// </summary> /// <param name="request"> </param> /// <param name="token"> Токен отмены задачи </param> /// <returns>Список информации о файлах в этой категории</returns> [HttpGet("/api/files")] [Permission] [ProducesResponseType(typeof(PaginationContainer<FileInfoDto>), (int)System.Net.HttpStatusCode.OK)] public async Task<IActionResult> GetFilesInfoAsync( [FromQuery] FileRequest request, CancellationToken token) { int? idCompany = User.GetCompanyId(); if (request.IdCategory is null || idCompany is null) return Forbid(); if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value, request.IdWell, token).ConfigureAwait(false)) return Forbid(); var filesInfo = await fileService.GetInfosPaginatedAsync(request, token).ConfigureAwait(false); return Ok(filesInfo); } /// <summary> /// Возвращает файл с диска на сервере /// </summary> /// <param name="idFile">id запрашиваемого файла</param> /// <param name="token"> Токен отмены задачи </param> /// <returns>Запрашиваемый файл</returns> [HttpGet("{idFile}")] [Permission] [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] public async Task<IActionResult> GetFileAsync( int idFile, CancellationToken token) { int? idCompany = User.GetCompanyId(); if (idCompany is null) return Forbid(); var fileInfo = await fileService.GetOrDefaultAsync(idFile, token); if (fileInfo is null) return NotFound(idFile); if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, fileInfo.IdWell, token).ConfigureAwait(false)) return Forbid(); var fileStream = fileService.GetFileStream(fileInfo); return File(fileStream, "application/octet-stream", fileInfo.Name); } /// <summary> /// Помечает файл как удаленный /// </summary> /// <param name="idWell">id скважины</param> /// <param name="idFile">id запрашиваемого файла</param> /// <param name="userRepository">dependency</param> /// <param name="token">Токен отмены задачи </param> /// <returns></returns> [HttpDelete("{idFile}")] [Permission] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task<IActionResult> DeleteAsync(int idWell, int idFile, [FromServices] IUserRepository userRepository, CancellationToken token) { int? idUser = User.GetUserId(); int? idCompany = User.GetCompanyId(); if (idUser is null || idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) return Forbid(); var fileInfo = await fileService.GetOrDefaultAsync(idFile, token); if (fileInfo is null) return NotFound(idFile); if (!userRepository.HasPermission((int)idUser, $"File.edit{fileInfo?.IdCategory}")) return Forbid(); var result = await fileService.MarkAsDeletedAsync(idFile, token); return Ok(result); } /// <summary> /// Создает метку для файла /// </summary> /// <param name="idWell">id скважины </param> /// <param name="markDto">метка файла</param> /// <param name="token">Токен отмены задачи </param> /// <returns></returns> [HttpPost("fileMark")] [Permission] public async Task<IActionResult> CreateFileMarkAsync(int idWell, FileMarkDto markDto, CancellationToken token) { var idCompany = User.GetCompanyId(); var idUser = User.GetUserId(); if (idCompany is null || idUser is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) return Forbid(); var result = await fileService.CreateFileMarkAsync(markDto, (int)idUser, token) .ConfigureAwait(false); return Ok(result); } /// <summary> /// Помечает метку у файла как удаленную /// </summary> /// <param name="idWell">id скважины </param> /// <param name="idMark">id метки </param> /// <param name="token">Токен отмены задачи </param> /// <returns></returns> [HttpDelete("fileMark")] [Permission] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task<IActionResult> DeleteFileMarkAsync(int idWell, int idMark, CancellationToken token) { var idCompany = User.GetCompanyId(); if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) return Forbid(); var result = await fileService.MarkFileMarkAsDeletedAsync(idMark, token) .ConfigureAwait(false); return Ok(result); } /// <summary> /// Возвращает информацию о файле /// </summary> /// <param name="idFile">id запрашиваемого файла</param> /// <param name="token"> Токен отмены задачи </param> /// <returns>Запрашиваемый файл</returns> [HttpGet("/api/files/{idFile}")] [Permission] [ProducesResponseType(typeof(FileInfoDto), (int)System.Net.HttpStatusCode.OK)] public async Task<IActionResult> GetFileInfoAsync([FromRoute] int idFile, CancellationToken token) { int? idCompany = User.GetCompanyId(); if (idCompany is null) return Forbid(); try { var fileInfo = await fileService.GetOrDefaultAsync(idFile, token).ConfigureAwait(false); return Ok(fileInfo); } catch (FileNotFoundException ex) { return NotFound(ex.FileName); } } } }