Добавление логики работы с инструкциями

1. Добавил сервисы и репозитории для инфструкций
2. Добавил контроллеры
3. Обновил конфиг
This commit is contained in:
parent f94db74d6a
commit e56530a10f
17 changed files with 814 additions and 0 deletions

View File

@ -0,0 +1,25 @@
using System.Collections.Generic;
using System.Linq;
namespace AsbCloudApp.Data.Manuals;
/// <summary>
/// Элемент каталога инструкций
/// </summary>
public class CatalogItemManualDto
{
/// <summary>
/// DTO категории
/// </summary>
public FileCategoryDto Category { get; set; } = null!;
/// <summary>
/// DTO инструкций хранящиеся без папки
/// </summary>
public IEnumerable<ManualDto> ManualsWithoutFolder { get; set; } = Enumerable.Empty<ManualDto>();
/// <summary>
/// DTO папок с инструкциями
/// </summary>
public IEnumerable<ManualFolderDto> Folders { get; set; } = Enumerable.Empty<ManualFolderDto>();
}

View File

@ -0,0 +1,32 @@
using System;
namespace AsbCloudApp.Data.Manuals;
/// <summary>
/// DTO инструкции
/// </summary>
public class ManualDto : IId
{
/// <inheritdoc/>
public int Id { get; set; }
/// <summary>
/// Название
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// Дата загрузки
/// </summary>
public DateTime DateDownload { get; set; }
/// <summary>
/// Id папки
/// </summary>
public int? IdFolder { get; set; }
/// <summary>
/// Id категории файла
/// </summary>
public int? IdCategory { get; set; }
}

View File

@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Linq;
namespace AsbCloudApp.Data.Manuals;
/// <summary>
/// DTO папки для хранения инструкций
/// </summary>
public class ManualFolderDto : IId
{
/// <inheritdoc/>
public int Id { get; set; }
/// <summary>
/// Название
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// Id родительской папки
/// </summary>
public int? IdParent { get; set; }
/// <summary>
/// Id категории
/// </summary>
public int IdCategory { get; set; }
/// <summary>
/// Вложенные папки
/// </summary>
public IEnumerable<ManualFolderDto> Children { get; set; } = Enumerable.Empty<ManualFolderDto>();
/// <summary>
/// Хранимые инструкции
/// </summary>
public IEnumerable<ManualDto> Manuals { get; set; } = Enumerable.Empty<ManualDto>();
}

View File

@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Services;
namespace AsbCloudApp.Repositories;
/// <summary>
/// Репозиторий для работы с категориями файлов
/// </summary>
public interface IFileCategoryRepository : ICrudRepository<FileCategoryDto>
{
/// <summary>
/// Получение всех записей по идентификатору типа
/// </summary>
/// <param name="idType"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<FileCategoryDto>> GetAllAsync(int idType, CancellationToken cancellationToken);
}

View File

@ -47,6 +47,12 @@ namespace AsbCloudApp.Repositories
/// <param name="fileName"></param>
void DeleteFile(string fileName);
/// <summary>
/// Удаление директории
/// </summary>
/// <param name="path"></param>
void DeleteDirectory(string path);
/// <summary>
/// Удаление всех файлов с диска о которых нет информации в базе
/// </summary>

View File

@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.Manuals;
using AsbCloudApp.Services;
namespace AsbCloudApp.Repositories;
/// <summary>
/// Репозиторий для работы с папки хранящими инструкциями
/// </summary>
public interface IManualFolderRepository : ICrudRepository<ManualFolderDto>
{
/// <summary>
/// Получение дерева каталога папок
/// </summary>
/// <param name="idCategory"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<ManualFolderDto>> GetTreeAsync(int idCategory, CancellationToken cancellationToken);
/// <summary>
/// Получение одной папки по параметрам
/// </summary>
/// <param name="name"></param>
/// <param name="idParent"></param>
/// <param name="idCategory"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<ManualFolderDto?> GetOrDefaultAsync(string name, int? idParent, int idCategory, CancellationToken cancellationToken);
}

View File

@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.Manuals;
using AsbCloudApp.Services;
namespace AsbCloudApp.Repositories;
/// <summary>
/// Репозиторий для инструкций
/// </summary>
public interface IManualRepository : ICrudRepository<ManualDto>
{
/// <summary>
/// Получение инструкций, которые не добавлены в папку
/// </summary>
/// <param name="idCategory"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<ManualDto>> GetManualsWithoutFolderAsync(int idCategory, CancellationToken cancellationToken);
}

View File

@ -0,0 +1,76 @@
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.Manuals;
namespace AsbCloudApp.Services;
/// <summary>
/// Сервис для работы c каталогом инструкций
/// </summary>
public interface IManualCatalogService
{
/// <summary>
/// Сохранение файла
/// </summary>
/// <param name="idCategory"></param>
/// <param name="idFolder"></param>
/// <param name="name"></param>
/// <param name="stream"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<int> SaveFileAsync(int? idCategory, int? idFolder, string name, Stream stream,
CancellationToken cancellationToken);
/// <summary>
/// Добавление новой папки
/// </summary>
/// <param name="name"></param>
/// <param name="idParent"></param>
/// <param name="idCategory"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<int> AddFolderAsync(string name, int? idParent, int idCategory,
CancellationToken cancellationToken);
/// <summary>
/// Обновление папки
/// </summary>
/// <param name="id"></param>
/// <param name="name"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task UpdateFolderAsync(int id, string name, CancellationToken cancellationToken);
/// <summary>
/// Удаление папки
/// </summary>
/// <param name="id"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<int> DeleteFolderAsync(int id, CancellationToken cancellationToken);
/// <summary>
/// Удаление файла
/// </summary>
/// <param name="id"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<int> DeleteFileAsync(int id, CancellationToken cancellationToken);
/// <summary>
/// Получение файла
/// </summary>
/// <param name="id"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<(Stream stream, string fileName)?> GetFileAsync(int id, CancellationToken cancellationToken);
/// <summary>
/// Получение каталога
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<CatalogItemManualDto>> GetCatalogAsync(CancellationToken cancellationToken);
}

View File

@ -221,6 +221,11 @@ namespace AsbCloudInfrastructure
services.AddTransient<IAutoGeneratedDailyReportService, AutoGeneratedDailyReportService>();
services.AddTransient<IAutoGeneratedDailyReportMakerService, AutoGeneratedDailyReportMakerService>();
services.AddTransient<IManualFolderRepository, ManualFolderRepository>();
services.AddTransient<IManualCatalogService, ManualCatalogService>();
services.AddTransient<IManualRepository, ManualRepository>();
services.AddTransient<IFileCategoryRepository, FileCategoryRepository>();
return services;
}

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using AsbCloudDb.Model;
using Mapster;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
namespace AsbCloudInfrastructure.Repository;
public class FileCategoryRepository : CrudCacheRepositoryBase<FileCategoryDto, FileCategory>, IFileCategoryRepository
{
public FileCategoryRepository(IAsbCloudDbContext dbContext, IMemoryCache memoryCache) : base(dbContext, memoryCache)
{
}
public FileCategoryRepository(IAsbCloudDbContext dbContext, IMemoryCache memoryCache,
Func<DbSet<FileCategory>, IQueryable<FileCategory>> makeQuery) : base(dbContext, memoryCache, makeQuery)
{
}
public async Task<IEnumerable<FileCategoryDto>> GetAllAsync(int idType, CancellationToken cancellationToken)
{
return await dbContext.FileCategories.Where(f => f.IdType == idType)
.Select(f => f.Adapt<FileCategoryDto>())
.ToArrayAsync(cancellationToken);
}
}

View File

@ -33,6 +33,21 @@ public class FileStorageRepository : IFileStorageRepository
DeleteFile(fileName);
}
}
public void DeleteDirectory(string path)
{
var fullPath = Path.Combine(RootPath, path);
if (!Directory.Exists(fullPath))
return;
foreach (var file in Directory.GetFiles(fullPath))
{
File.Delete(file);
}
Directory.Delete(fullPath, true);
}
public void DeleteFile(string fileName)
{

View File

@ -0,0 +1,62 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.Manuals;
using AsbCloudApp.Repositories;
using AsbCloudDb.Model;
using AsbCloudDb.Model.Manuals;
using Mapster;
using Microsoft.EntityFrameworkCore;
namespace AsbCloudInfrastructure.Repository;
public class ManualFolderRepository : CrudRepositoryBase<ManualFolderDto, ManualFolder>, IManualFolderRepository
{
public ManualFolderRepository(IAsbCloudDbContext context) : base(context)
{
}
public async Task<IEnumerable<ManualFolderDto>> GetTreeAsync(int idCategory,
CancellationToken cancellationToken)
{
var folders = await dbContext.ManualFolders
.Where(m => m.IdCategory == idCategory)
.AsNoTracking()
.Include(m => m.Manuals)
.Include(m => m.Parent)
.ToArrayAsync(cancellationToken);
return BuildTree(folders).Select(x => x.Adapt<ManualFolderDto>());
}
public async Task<ManualFolderDto?> GetOrDefaultAsync(string name, int? idParent, int idCategory,
CancellationToken cancellationToken)
{
var entity = await dbContext.ManualFolders
.FirstOrDefaultAsync(m => m.Name == name &&
m.IdCategory == idCategory &&
m.IdParent == idParent, cancellationToken);
if (entity is null)
return null;
return Convert(entity);
}
private IEnumerable<ManualFolder> BuildTree(IEnumerable<ManualFolder> folders)
{
var folderDict = folders.ToDictionary(f => f.Id);
foreach (var folder in folders)
{
if (folder.IdParent.HasValue && folderDict.TryGetValue(folder.IdParent.Value, out var parent))
{
parent.Children ??= new List<ManualFolder>();
parent.Children.Add(folder);
}
}
return folders.Where(f => f.IdParent == null);
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.Manuals;
using AsbCloudApp.Repositories;
using AsbCloudDb.Model;
using AsbCloudDb.Model.Manuals;
using Mapster;
using Microsoft.EntityFrameworkCore;
namespace AsbCloudInfrastructure.Repository;
public class ManualRepository : CrudRepositoryBase<ManualDto, Manual>, IManualRepository
{
public ManualRepository(IAsbCloudDbContext context) : base(context)
{
}
public ManualRepository(IAsbCloudDbContext context, Func<DbSet<Manual>, IQueryable<Manual>> makeQuery)
: base(context, makeQuery)
{
}
public async Task<IEnumerable<ManualDto>> GetManualsWithoutFolderAsync(int idCategory, CancellationToken cancellationToken)
{
return await dbContext.Manuals.Where(m => m.IdCategory == idCategory &&
m.IdFolder == null)
.Select(m => m.Adapt<ManualDto>())
.ToArrayAsync(cancellationToken);
}
}

View File

@ -0,0 +1,202 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.Manuals;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Microsoft.Extensions.Configuration;
namespace AsbCloudInfrastructure.Services;
public class ManualCatalogService : IManualCatalogService
{
private readonly IEnumerable<string> validExtensions = new[]
{
".pdf",
".mp4"
};
private readonly string directoryFiles;
private readonly IFileStorageRepository fileStorageRepository;
private readonly IManualFolderRepository manualFolderRepository;
private readonly IManualRepository manualRepository;
private readonly IFileCategoryRepository fileCategoryRepository;
public ManualCatalogService(IFileStorageRepository fileStorageRepository,
IManualFolderRepository manualFolderRepository,
IManualRepository manualRepository,
IFileCategoryRepository fileCategoryRepository,
IConfiguration configuration)
{
this.fileStorageRepository = fileStorageRepository;
this.manualFolderRepository = manualFolderRepository;
this.manualRepository = manualRepository;
this.fileCategoryRepository = fileCategoryRepository;
directoryFiles = configuration.GetValue<string>("DirectoryManualFiles");
if (string.IsNullOrWhiteSpace(directoryFiles))
directoryFiles = "manuals";
}
public async Task<int> SaveFileAsync(int? idCategory, int? idFolder, string name, Stream stream,
CancellationToken cancellationToken)
{
var extension = Path.GetExtension(name);
if (!validExtensions.Contains(extension))
throw new ArgumentInvalidException(
$"Невозможно загрузить файл с расширением '{extension}'. Допустимые форматы файлов: {string.Join(", ", validExtensions)}",
extension);
var path = await BuildFilePathAsync(idCategory, idFolder, name, cancellationToken);
await fileStorageRepository.SaveFileAsync(path,
stream,
cancellationToken);
var manual = new ManualDto
{
Name = name,
DateDownload = DateTime.UtcNow,
IdFolder = idFolder,
IdCategory = idCategory
};
return await manualRepository.InsertAsync(manual, cancellationToken);
}
public async Task<int> AddFolderAsync(string name, int? idParent, int idCategory,
CancellationToken cancellationToken)
{
if (idParent.HasValue)
{
var parent = await manualFolderRepository.GetOrDefaultAsync(idParent.Value, cancellationToken)
?? throw new ArgumentInvalidException("Родительской папки не существует", nameof(idParent));
if (parent.IdCategory != idCategory)
throw new ArgumentInvalidException("Категория родительской папки не соответствует текущей категории",
nameof(idCategory));
}
var manualFolder = new ManualFolderDto
{
Name = name,
IdParent = idParent,
IdCategory = idCategory,
};
if (await IsExistFolderAsync(manualFolder, cancellationToken))
throw new ArgumentInvalidException("Папка с таким названием уже существует", name);
return await manualFolderRepository.InsertAsync(manualFolder, cancellationToken);
}
public async Task UpdateFolderAsync(int id, string name, CancellationToken cancellationToken)
{
var folder = await manualFolderRepository.GetOrDefaultAsync(id, cancellationToken)
?? throw new ArgumentInvalidException($"Папки с Id: {id} не сущесвует", nameof(id));
folder.Name = name;
if (await IsExistFolderAsync(folder, cancellationToken))
throw new ArgumentInvalidException("Папка с таким названием уже существует", name);
await manualFolderRepository.UpdateAsync(folder, cancellationToken);
}
public async Task<int> DeleteFolderAsync(int id, CancellationToken cancellationToken)
{
var folder = await manualFolderRepository.GetOrDefaultAsync(id, cancellationToken);
if (folder is null)
return 0;
var path = Path.Combine(directoryFiles, folder.IdCategory.ToString(), folder.Id.ToString());
fileStorageRepository.DeleteDirectory(path);
return await manualFolderRepository.DeleteAsync(folder.Id, cancellationToken);
}
public async Task<int> DeleteFileAsync(int id, CancellationToken cancellationToken)
{
var manual = await manualRepository.GetOrDefaultAsync(id, cancellationToken);
if (manual is null)
return 0;
var filePath = await BuildFilePathAsync(manual.IdCategory, manual.IdFolder, manual.Name,
cancellationToken);
fileStorageRepository.DeleteFile(filePath);
return await manualRepository.DeleteAsync(manual.Id, cancellationToken);
}
public async Task<(Stream stream, string fileName)?> GetFileAsync(int id, CancellationToken cancellationToken)
{
var manual = await manualRepository.GetOrDefaultAsync(id, cancellationToken);
if (manual is null)
return null;
var path = await BuildFilePathAsync(manual.IdCategory, manual.IdFolder, manual.Name, cancellationToken);
var fileStream = new FileStream(Path.GetFullPath(path), FileMode.Open);
return (fileStream, manual.Name);
}
public async Task<IEnumerable<CatalogItemManualDto>> GetCatalogAsync(CancellationToken cancellationToken)
{
var catalogItems = new List<CatalogItemManualDto>();
var categories = await fileCategoryRepository.GetAllAsync(FileCategory.IdFileCategoryTypeManuals,
cancellationToken);
foreach (var category in categories)
{
catalogItems.Add(new CatalogItemManualDto()
{
Category = category,
ManualsWithoutFolder = await manualRepository.GetManualsWithoutFolderAsync(category.Id, cancellationToken),
Folders = await manualFolderRepository.GetTreeAsync(category.Id, cancellationToken)
});
}
return catalogItems;
}
private async Task<bool> IsExistFolderAsync(ManualFolderDto folder, CancellationToken cancellationToken)
{
var existingFolder = await manualFolderRepository.GetOrDefaultAsync(folder.Name, folder.IdParent,
folder.IdCategory,
cancellationToken);
return existingFolder is not null && folder.Id != existingFolder.Id;
}
private async Task<string> BuildFilePathAsync(int? idCategory, int? idFolder, string name,
CancellationToken cancellationToken)
{
if (idFolder.HasValue)
{
var folder = await manualFolderRepository.GetOrDefaultAsync(idFolder.Value, cancellationToken)
?? throw new ArgumentInvalidException($"Папки с Id: {idFolder} не сущесвует", nameof(idFolder));
return fileStorageRepository.MakeFilePath(directoryFiles, Path.Combine(folder.IdCategory.ToString(),
folder.IdParent.ToString() ?? string.Empty,
folder.Id.ToString()), name);
}
if (!idCategory.HasValue)
throw new ArgumentInvalidException("Не указан идентификатор категории", nameof(idCategory));
return fileStorageRepository.MakeFilePath(directoryFiles, idCategory.Value.ToString(), name);
}
}

View File

@ -0,0 +1,120 @@
using System.ComponentModel.DataAnnotations;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace AsbCloudWebApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class ManualController : ControllerBase
{
private readonly IManualCatalogService manualCatalogService;
private readonly IUserRepository userRepository;
public ManualController(IManualCatalogService manualCatalogService,
IUserRepository userRepository)
{
this.manualCatalogService = manualCatalogService;
this.userRepository = userRepository;
}
/// <summary>
/// Сохранение файла
/// </summary>
/// <param name="idCategory">Необязательный параметр. 30000 - АСУ ТП, 30001 - Технология бурения</param>
/// <param name="idFolder">Необязательный параметр. Id папки</param>
/// <param name="file">Загружаемый файл</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<IActionResult> SaveFileAsync(
[Range(minimum: 30000, maximum: 30001, ErrorMessage = "Категория файла недопустима. Допустимые: 30000, 30001")]
int? idCategory,
int? idFolder,
[Required] IFormFile file,
CancellationToken cancellationToken)
{
if(!CanUserAccess("Manual.edit"))
return Forbid();
using var fileStream = file.OpenReadStream();
var id = await manualCatalogService.SaveFileAsync(idCategory, idFolder, file.FileName, fileStream, cancellationToken);
return Ok(id);
}
/// <summary>
/// Получение файла
/// </summary>
/// <param name="id">Id инструкции</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet("{id:int}")]
[Permission]
[ProducesResponseType(typeof(PhysicalFileResult), StatusCodes.Status200OK, "application/octet-stream")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<IActionResult> GetFileAsync(int id, CancellationToken cancellationToken)
{
if(!CanUserAccess("Manual.view"))
return Forbid();
var file = await manualCatalogService.GetFileAsync(id, cancellationToken);
if (!file.HasValue)
return NoContent();
return File(file.Value.stream, "application/octet-stream", file.Value.fileName);
}
/// <summary>
/// Удаление файла
/// </summary>
/// <param name="id">Id инструкции</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpDelete]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<IActionResult> DeleteFileAsync(int id, CancellationToken cancellationToken)
{
if(!CanUserAccess("Manual.edit"))
return Forbid();
return Ok(await manualCatalogService.DeleteFileAsync(id, cancellationToken));
}
/// <summary>
/// Получение каталога с инструкциями
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpGet]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<IActionResult> GetCatalogAsync(CancellationToken cancellationToken)
{
if(!CanUserAccess("Manual.view"))
return Forbid();
return Ok(await manualCatalogService.GetCatalogAsync(cancellationToken));
}
private bool CanUserAccess(string permission)
{
var idUser = User.GetUserId();
return idUser.HasValue && userRepository.HasPermission(idUser.Value, permission);
}
}

View File

@ -0,0 +1,94 @@
using System.ComponentModel.DataAnnotations;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace AsbCloudWebApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class ManualFolderController : ControllerBase
{
private readonly IManualCatalogService manualCatalogService;
private readonly IUserRepository userRepository;
public ManualFolderController(IManualCatalogService manualCatalogService,
IUserRepository userRepository)
{
this.manualCatalogService = manualCatalogService;
this.userRepository = userRepository;
}
/// <summary>
/// Создание папки
/// </summary>
/// <param name="name">Название</param>
/// <param name="idParent">Необязательный параметр. Id родительской папки</param>
/// <param name="idCategory">Id категории. 30000 - АСУ ТП, 30001 - Технология бурения</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<IActionResult> AddFolderAsync(string name, int? idParent,
[Required(ErrorMessage = "Обязательный параметр")]
[Range(minimum: 30000, maximum: 30001, ErrorMessage = "Категория файла недопустима. Допустимые: 30000, 30001")]
int idCategory,
CancellationToken cancellationToken)
{
if (!CanUserAccess())
Forbid();
return Ok(await manualCatalogService.AddFolderAsync(name, idParent, idCategory, cancellationToken));
}
/// <summary>
/// Обновление папки
/// </summary>
/// <param name="id"></param>
/// <param name="name">Новое название папки</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPut]
[Permission]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<IActionResult> UpdateFolderAsync(int id, string name, CancellationToken cancellationToken)
{
if (!CanUserAccess())
Forbid();
await manualCatalogService.UpdateFolderAsync(id, name, cancellationToken);
return Ok();
}
/// <summary>
/// Удаление папки
/// </summary>
/// <param name="id"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpDelete]
[Permission]
[ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<IActionResult> DeleteFolderAsync(int id, CancellationToken cancellationToken)
{
if (!CanUserAccess())
Forbid();
return Ok(await manualCatalogService.DeleteFolderAsync(id, cancellationToken));
}
private bool CanUserAccess()
{
var idUser = User.GetUserId();
return idUser.HasValue && userRepository.HasPermission(idUser.Value, "Manual.edit");
}
}

View File

@ -27,6 +27,7 @@
"supportMail": "support@digitaldrilling.ru"
},
"DirectoryNameHelpPageFiles": "helpPages",
"DirectoryManualFiles": "manuals",
"Urls": "http://0.0.0.0:5000" //;https://0.0.0.0:5001" //,
// See https man: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/endpoints?view=aspnetcore-6.0
//"Kestrel": {