diff --git a/.gitignore b/.gitignore index 0a8e0559ee40f980c98cf9af85ceef89e5cdc385..c524fb9e6a76f62d010c6ea470ea1966e71452a7 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ .vs obj bin +StaticFiles diff --git a/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs b/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs index 07e1566697c0d69bfc9157b5d449be5cf4a9f575..7c82f7a8e4863b1150bebce631dcba9e8100412b 100644 --- a/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs +++ b/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs @@ -50,7 +50,6 @@ namespace Tsi1.Api.Controllers public async Task<IActionResult> Create(CourseCreateDto newCourse) { var tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value); - newCourse.TenantId = tenantId; var result = await _courseService.Create(newCourse); @@ -59,10 +58,6 @@ namespace Tsi1.Api.Controllers return BadRequest(result.Message); } - var path = Path.Combine(tenantId.ToString(), result.Data.Id.ToString()); - - _fileService.CreateFolder(path); - return Ok(); } @@ -214,10 +209,6 @@ namespace Tsi1.Api.Controllers return NotFound(result.Message); } - var path = Path.Combine(result.Data.TenantId.ToString(), result.Data.Id.ToString()); - - _fileService.DeleteFolder(path); - return Ok(); } diff --git a/Tsi1.Api/Tsi1.Api/Controllers/FileController.cs b/Tsi1.Api/Tsi1.Api/Controllers/FileController.cs index 144a8298f82892a2caafe88b4957da0c01b96b24..fb7296dfe4acc041f55513ebeb4dd8b42bc18489 100644 --- a/Tsi1.Api/Tsi1.Api/Controllers/FileController.cs +++ b/Tsi1.Api/Tsi1.Api/Controllers/FileController.cs @@ -22,13 +22,12 @@ namespace Tsi1.Api.Controllers } [Authorize(Roles = UserTypes.Professor)] - [HttpPost("Create/{courseId}")] - public async Task<IActionResult> Create(IFormFile file, int courseId) + [HttpPost("Upload/{courseId}")] + public async Task<IActionResult> Upload(IFormFile file, int courseId) { - var tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value); - - var result = await _fileService.Create(file, tenantId, courseId); + var tenantId = HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value; + var result = await _fileService.Create(file, tenantId, courseId.ToString()); if (result.HasError) { return BadRequest(result.Message); diff --git a/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs b/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs index ce849fad5a8181e60e393cc4ddfc226540111847..83a96c4131d8d15ce2ab53da366c9b0c59477bef 100644 --- a/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs +++ b/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -23,10 +23,10 @@ namespace Tsi1.Api.Controllers } [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] - [HttpGet("GetForums/{courseId}")] - public async Task<IActionResult> GetForums(int courseId) + [HttpGet("GetForums/{sectionId}")] + public async Task<IActionResult> GetForums(int sectionId) { - var result = await _forumService.GetForums(courseId); + var result = await _forumService.GetForums(sectionId); if (result.HasError) { diff --git a/Tsi1.Api/Tsi1.Api/Controllers/SectionController.cs b/Tsi1.Api/Tsi1.Api/Controllers/SectionController.cs new file mode 100644 index 0000000000000000000000000000000000000000..81946f2c304d9d9862e5a186937fee95d0ca7f32 --- /dev/null +++ b/Tsi1.Api/Tsi1.Api/Controllers/SectionController.cs @@ -0,0 +1,71 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; + +namespace Tsi1.Api.Controllers +{ + [Authorize(Roles = UserTypes.Professor)] + [Route("api/[controller]")] + [ApiController] + public class SectionController : ControllerBase + { + private readonly ISectionService _sectionService; + + public SectionController(ISectionService sectionService) + { + _sectionService = sectionService; + } + + [HttpPost("Create")] + public async Task<IActionResult> Create(SectionCreateDto section) + { + var result = await _sectionService.Create(section); + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + + [HttpPut("Modify/{sectionId}")] + public async Task<IActionResult> Modify(int sectionId, string newName) + { + var result = await _sectionService.Modify(sectionId, newName); + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + + [HttpDelete("Delete/{sectionId}")] + public async Task<IActionResult> Delete(int sectionId) + { + var result = await _sectionService.Delete(sectionId); + if (result.HasError) + { + return NotFound(result.Message); + } + + return Ok(); + } + + [HttpPost("ChangeOrder")] + public async Task<IActionResult> ChangeOrder(List<OrderDto> orderDtos) + { + var result = await _sectionService.OrderSections(orderDtos); + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + } +} diff --git a/Tsi1.Api/Tsi1.Api/Controllers/SectionItemController.cs b/Tsi1.Api/Tsi1.Api/Controllers/SectionItemController.cs new file mode 100644 index 0000000000000000000000000000000000000000..4e278ca49c8c101e03e2c593a2cc5a895c3196d1 --- /dev/null +++ b/Tsi1.Api/Tsi1.Api/Controllers/SectionItemController.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; + +namespace Tsi1.Api.Controllers +{ + [Authorize(Roles = UserTypes.Professor)] + [Route("api/[controller]")] + [ApiController] + public class SectionItemController : ControllerBase + { + private readonly ISectionItemService _sectionItemService; + private readonly ISectionItemTypeService _sectionItemTypeService; + + public SectionItemController(ISectionItemService sectionItemService, ISectionItemTypeService sectionItemTypeService) + { + _sectionItemService = sectionItemService; + _sectionItemTypeService = sectionItemTypeService; + } + + [HttpPost("Create")] + public async Task<IActionResult> Create(SectionItemCreateDto sectionItem) + { + var result = await _sectionItemService.Create(sectionItem); + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + + [HttpDelete("Delete/{sectionItemId}")] + public async Task<IActionResult> Delete(int sectionItemId) + { + var result = await _sectionItemService.Delete(sectionItemId); + if (result.HasError) + { + return NotFound(result.Message); + } + + return Ok(); + } + + [HttpPost("ChangeOrder")] + public async Task<IActionResult> ChangeOrder(List<OrderDto> orderDtos) + { + var result = await _sectionItemService.OrderSectionItems(orderDtos); + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + + [HttpGet("GetSectionItemTypes")] + public async Task<IActionResult> GetSectionItemTypes() + { + var result = await _sectionItemTypeService.GetAll(); + return Ok(result.Data); + } + } +} diff --git a/Tsi1.Api/Tsi1.Api/Controllers/TenantController.cs b/Tsi1.Api/Tsi1.Api/Controllers/TenantController.cs index 92a0665ffad2a0892a1365f1b16fbbf9730a92e6..9b597317ccc3eadd4638d7e5e46a72232ed7abc3 100644 --- a/Tsi1.Api/Tsi1.Api/Controllers/TenantController.cs +++ b/Tsi1.Api/Tsi1.Api/Controllers/TenantController.cs @@ -50,8 +50,6 @@ namespace Tsi1.Api.Controllers return BadRequest(result.Message); } - _fileService.CreateFolder(result.Data.Id.ToString()); - return Ok(result.Data); } @@ -90,8 +88,6 @@ namespace Tsi1.Api.Controllers return NotFound(result.Message); } - _fileService.DeleteFolder(tenantId.ToString()); - return Ok(); } diff --git a/Tsi1.Api/Tsi1.Api/Startup.cs b/Tsi1.Api/Tsi1.Api/Startup.cs index 991fdf3c7801ede272682689829eacea0793d2ed..6e94cdd7d44ba06c989ee6ce6c31f4ed44bca6b3 100644 --- a/Tsi1.Api/Tsi1.Api/Startup.cs +++ b/Tsi1.Api/Tsi1.Api/Startup.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; using System.Threading.Tasks; using AutoMapper; @@ -9,8 +7,6 @@ using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.HttpsPolicy; -using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.StaticFiles; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -24,6 +20,7 @@ using Microsoft.OpenApi.Models; using Tsi1.Api.Infrastructure; using Tsi1.Api.SignalR; using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.HostedServices; using Tsi1.BusinessLayer.Interfaces; using Tsi1.BusinessLayer.Services; using Tsi1.DataLayer; @@ -67,7 +64,7 @@ namespace Tsi1.Api services.AddSingleton<IJwtAuthManager, JwtAuthManager>(); services.AddHostedService<JwtRefreshTokenCache>(); services.AddHostedService<JwtVerificationCodeCache>(); - + services.AddHostedService<FileCleaner>(); services.AddSingleton<IMessageService, MessageService>(); @@ -79,6 +76,9 @@ namespace Tsi1.Api services.AddScoped<IPostMessageService, PostMessageService>(); services.AddScoped<ITenantService, TenantService>(); services.AddScoped<IFileService, FileService>(); + services.AddScoped<ISectionService, SectionService>(); + services.AddScoped<ISectionItemService, SectionItemService>(); + services.AddScoped<ISectionItemTypeService, SectionItemTypeService>(); services.Configure<MailSettings>(Configuration.GetSection("MailSettings")); services.AddScoped<IEmailService, EmailService>(); diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/FileDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/FileDto.cs index 977a0596daafe431f74776ab1dca5530a569655b..f16d17fcf63db34a88607f5e2a6b8626f8095bd3 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/FileDto.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/FileDto.cs @@ -6,10 +6,7 @@ namespace Tsi1.BusinessLayer.Dtos { public class FileDto { - public int Id { get; set; } - public string Name { get; set; } - public string Path { get; set; } } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs index b4ebbecf257f0cf9667d615450a776738d3bac0c..4c4d099f672bdb4d3babcfafa870142bfeb385e6 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs @@ -8,7 +8,5 @@ namespace Tsi1.BusinessLayer.Dtos public class ForumCreateDto { public string Name { get; set; } - - public int CourseId { get; set; } } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/OrderDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/OrderDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..b5416344d88a50b8e42ea94771c4233319cad2e5 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/OrderDto.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class OrderDto + { + public int Id { get; set; } + public int Order { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionCreateDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..3eee0e09604a69c76dd551964a95e139f1694f13 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionCreateDto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class SectionCreateDto + { + public int CourseId { get; set; } + public string Name { get; set; } + public int Order { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionItemCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionItemCreateDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..9da60f96c22ec4674298ff8503a8d29b0b70cfb8 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionItemCreateDto.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class SectionItemCreateDto + { + public int Order { get; set; } + public int SectionId { get; set; } + public int SectionItemTypeId { get; set; } + + public ForumCreateDto Forum { get; set; } + public FileDto File { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionItemTypeDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionItemTypeDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..89a6ca311d3eca78d999f4b3c3448e2d21cc56b5 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/SectionItemTypeDto.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class SectionItemTypeDto + { + public int Id { get; set; } + public string Name { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs index 8dc7c9fb645af7ec4886187388f9ec2c5e662b8e..41b7cf04530200739506f9fc996dff91c0ac3b81 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs @@ -42,5 +42,17 @@ namespace Tsi1.BusinessLayer.Helpers public const string ErrorSavingFile = "No se pudo guardar el archivo '{0}'"; public const string ErrorDeletingFile = "No se pudo borrar el archivo '{0}'"; public const string DuplicateFile = "Ya existe el archivo '{0}'"; + public const string FileDoesNotExist = "El archivo '{0}' no existe fisicamente en el file server"; + + public const string SectionDoesNotExist = "La seccion con id '{0}' no existe"; + public const string DuplicateSectionOrder = "Hay secciones con el mismo orden"; + public const string SectionItemDoesNotExist = "El item de seccion con id '{0}' no existe"; + public const string DuplicateSectionItemOrder = "Hay items de seccion con el mismo orden"; + + public const string SectionItemTypeDoesNotExist = "El tipo de item de seccion con id '{0}' no existe"; + public const string InvalidSectionItemType = "El tipo de item de seccion '{0}' es invalido"; + public const string ForumIsNull = "El foro es nulo"; + public const string FileIsNull = "El archivo es nulo"; + public const string InvalidSectionItemData = "El tipo de item de seccion '{0}' no coincide con su contenido '{1}'"; } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs index 70331a3460dc0b13a3efd4f20f128faa0ac94a10..369144617f0eba6df858ecd73c83f401abac94fd 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs @@ -33,6 +33,9 @@ namespace Tsi1.BusinessLayer.Helpers CreateMap<Tenant, TenantCourseDto>().ForMember(x => x.Courses, opt => opt.Ignore()); CreateMap<UserType, UserTypeDto>(); CreateMap<File, FileDto>(); + CreateMap<SectionItem, SectionItemCreateDto>(); + CreateMap<Section, SectionCreateDto>(); + CreateMap<SectionItemType, SectionItemTypeDto>(); CreateMap<ForumCreateDto, Forum>(); CreateMap<ForumPreviewDto, Forum>(); @@ -55,6 +58,9 @@ namespace Tsi1.BusinessLayer.Helpers CreateMap<TenantCourseDto, Tenant>(); CreateMap<UserTypeDto, UserType>(); CreateMap<FileDto, File>(); + CreateMap<SectionItemCreateDto, SectionItem>(); + CreateMap<SectionCreateDto, Section>(); + CreateMap<SectionItemTypeDto, SectionItemType>(); } } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/SectionItemTypes.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/SectionItemTypes.cs new file mode 100644 index 0000000000000000000000000000000000000000..0eee4f0c3bd2dd3c53204e5539652b839534a794 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/SectionItemTypes.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Helpers +{ + public static class SectionItemTypes + { + public const string Forum = nameof(Forum); + public const string File = nameof(File); + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ServiceResult.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ServiceResult.cs index ae294d7826fb64ea7a4037019e9003de5d84f9bc..2e9e2fe41e0fcc76bd20563837898a7e042511b8 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ServiceResult.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ServiceResult.cs @@ -9,5 +9,17 @@ namespace Tsi1.BusinessLayer.Helpers public T Data { get; set; } public string Message { get; set; } public bool HasError { get; set; } + + public void AddMessage(string message) + { + if (string.IsNullOrEmpty(this.Message)) + { + this.Message = message; + } + else + { + this.Message += System.Environment.NewLine + message; + } + } } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/HostedServices/FileCleaner.cs b/Tsi1.Api/Tsi1.BusinessLayer/HostedServices/FileCleaner.cs new file mode 100644 index 0000000000000000000000000000000000000000..7a5df1102adad587acc45fa417539d77993de5fa --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/HostedServices/FileCleaner.cs @@ -0,0 +1,54 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Interfaces; + +namespace Tsi1.BusinessLayer.HostedServices +{ + public class FileCleaner : IHostedService, IDisposable + { + private Timer _timer; + private readonly IServiceScopeFactory _serviceScopeFactory; + + public FileCleaner(IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromDays(1)); + return Task.CompletedTask; + } + + private async void DoWork(object state) + { + using (var scope = _serviceScopeFactory.CreateScope()) + { + var fileService = scope.ServiceProvider.GetRequiredService<IFileService>(); + var dbFileNames = await fileService.GetFileNames(); + var fsFiles = fileService.GetPhysicalFiles(); + + var filesToDelete = fsFiles.Except(dbFileNames); + foreach (var file in filesToDelete) + { + fileService.DeleteFile(file); + } + } + } + + public Task StopAsync(CancellationToken cancellationToken) + { + _timer?.Change(Timeout.Infinite, 0); + return Task.CompletedTask; + } + + public void Dispose() + { + _timer?.Dispose(); + } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IFileService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IFileService.cs index a42bbf693f410735a37715369574479ae29b6551..c0392df3d36d9d1f8f0e6af98659f92b49b1d438 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IFileService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IFileService.cs @@ -10,10 +10,10 @@ namespace Tsi1.BusinessLayer.Interfaces { public interface IFileService { - Task<ServiceResult<FileDto>> Create(IFormFile file, int tenantId, int courseId); - - void CreateFolder(string folderPath); - - void DeleteFolder(string folderPath); + Task<ServiceResult<string>> Create(IFormFile file, string tenantId, string courseId); + Task<List<string>> GetFileNames(); + ServiceResult<bool> DeleteFile(string filePath); + bool ExistFile(string relativePath); + List<string> GetPhysicalFiles(); } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs index 12d94600ab697452919232f3f12239614f811fe2..db95e50fb7187731b47a02cff78439a8ce5ee37a 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs @@ -10,7 +10,7 @@ namespace Tsi1.BusinessLayer.Interfaces { public interface IForumService { - Task<ServiceResult<List<ForumPreviewDto>>> GetForums(int courseId); + Task<ServiceResult<List<ForumPreviewDto>>> GetForums(int sectionId); Task<ServiceResult<Forum>> Create(ForumCreateDto newForum); diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionItemService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionItemService.cs new file mode 100644 index 0000000000000000000000000000000000000000..4834f03114b891bfae163d7d87ac1be83dfced28 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionItemService.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; + +namespace Tsi1.BusinessLayer.Interfaces +{ + public interface ISectionItemService + { + Task<ServiceResult<bool>> Create(SectionItemCreateDto newSectionItem); + Task<ServiceResult<bool>> Delete(int sectionItemId); + Task<ServiceResult<bool>> OrderSectionItems(List<OrderDto> orderDtos); + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionItemTypeService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionItemTypeService.cs new file mode 100644 index 0000000000000000000000000000000000000000..55112eb6f5da721e95ec5fba9da13b28b2e90fef --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionItemTypeService.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; + +namespace Tsi1.BusinessLayer.Interfaces +{ + public interface ISectionItemTypeService + { + Task<ServiceResult<List<SectionItemTypeDto>>> GetAll(); + Task<ServiceResult<SectionItemTypeDto>> GetById(int id); + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionService.cs new file mode 100644 index 0000000000000000000000000000000000000000..4ba20e791f0e16065ba0f14b1d4a5556ff6735ff --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/ISectionService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; + +namespace Tsi1.BusinessLayer.Interfaces +{ + public interface ISectionService + { + Task<ServiceResult<bool>> Create(SectionCreateDto newSection); + Task<ServiceResult<bool>> Delete(int sectionId); + Task<ServiceResult<bool>> OrderSections(List<OrderDto> orderDtos); + Task<ServiceResult<bool>> Modify(int sectionId, string name); + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/FileService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/FileService.cs index 315250148761311cbd020f1da7863798800a7793..74c8fb4ff7b641e327843a8acfdcb1cd6e3bd99b 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Services/FileService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/FileService.cs @@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using System.Threading.Tasks; using Tsi1.BusinessLayer.Dtos; @@ -18,24 +19,28 @@ namespace Tsi1.BusinessLayer.Services public class FileService : IFileService { private readonly Tsi1Context _context; - private readonly IMapper _mapper; - private readonly string _path; public FileService(Tsi1Context context, IMapper mapper, IHostingEnvironment hostingEnvironment) { _context = context; _mapper = mapper; - _path = hostingEnvironment.ContentRootPath + "/StaticFiles"; + _path = Path.Combine(hostingEnvironment.ContentRootPath, "StaticFiles"); } - public async Task<ServiceResult<string>> SaveFile(IFormFile file, string filePath) + public async Task<ServiceResult<string>> Create(IFormFile file, string tenantId, string courseId) { var result = new ServiceResult<string>(); - var fileStream = new FileStream(filePath, FileMode.Create); + var folder = Path.Combine(_path, tenantId, courseId); + Directory.CreateDirectory(folder); + var fileName = GenerateFileName(file); + var relativePath = Path.Combine(tenantId, courseId, fileName); + var filePath = Path.Combine(_path, relativePath); + + var fileStream = new FileStream(filePath, FileMode.Create); try { await file.CopyToAsync(fileStream); @@ -51,60 +56,11 @@ namespace Tsi1.BusinessLayer.Services fileStream.Close(); } + result.Data = relativePath; return result; } - - - public async Task<ServiceResult<FileDto>> Create(IFormFile file, int tenantId, int courseId) - { - var result = new ServiceResult<FileDto>(); - - var tenant = await _context.Tenants - .FirstOrDefaultAsync(x => x.Id == tenantId); - - var course = await _context.Courses - .FirstOrDefaultAsync(x => x.Id == courseId); - - var filePath = Path.Combine(_path, tenant.Name, course.Name, file.FileName); - - var existingFile = await _context.Files.FirstOrDefaultAsync(x => x.Path == filePath); - if (existingFile != null) - { - result.HasError = true; - result.Message = string.Format(ErrorMessages.DuplicateFile, filePath); - return result; - } - - var newFile = new DataLayer.Entities.File - { - Name = file.FileName, - Path = filePath.Replace(_path, ""), - }; - - _context.Add(newFile); - await _context.SaveChangesAsync(); - - var resultSaveFile = await this.SaveFile(file, filePath); - if (resultSaveFile.HasError) - { - result.HasError = true; - result.Message = resultSaveFile.Message; - - _context.Remove(newFile); - await _context.SaveChangesAsync(); - - return result; - } - - var fileDto = _mapper.Map<FileDto>(newFile); - result.Data = fileDto; - - return result; - } - - - public async Task<ServiceResult<bool>> DeleteFile(string filePath) + public ServiceResult<bool> DeleteFile(string filePath) { var result = new ServiceResult<bool>(); @@ -122,18 +78,29 @@ namespace Tsi1.BusinessLayer.Services return result; } - public void CreateFolder(string folderPath) + public bool ExistFile(string relativePath) { - var path = Path.Combine(_path, folderPath); + var path = Path.Combine(_path, relativePath); + return System.IO.File.Exists(path); + } - Directory.CreateDirectory(path); + public async Task<List<string>> GetFileNames() + { + return await _context.Files.Select(x => x.Path).ToListAsync(); } - public void DeleteFolder(string folderPath) + public List<string> GetPhysicalFiles() { - var path = Path.Combine(_path, folderPath); + var fullPaths = Directory.GetFiles(_path, "*", SearchOption.AllDirectories); + return fullPaths.Select(x => Path.GetRelativePath(_path, x)).ToList(); + } - Directory.Delete(path); + private string GenerateFileName(IFormFile file) + { + var ext = file.FileName.Split(".").Last(); + var fileName = Guid.NewGuid().ToString(); + return fileName + "." + ext; } + } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs index 1865a424afa5cce020312e80eb3b5492318ed13f..6418cd586192711626386adcf25d8285a9bd63d0 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs @@ -29,25 +29,12 @@ namespace Tsi1.BusinessLayer.Services public async Task<ServiceResult<Forum>> Create(ForumCreateDto newForum) { var result = new ServiceResult<Forum>(); - - var existingForum = await _context.Forums - .FirstOrDefaultAsync(x => x.Name == newForum.Name && x.CourseId == newForum.CourseId); - - if (existingForum != null) - { - result.HasError = true; - result.Message = string.Format(ErrorMessages.DuplicateForumName, newForum.Name); - return result; - } - var forum = _mapper.Map<Forum>(newForum); _context.Forums.Add(forum); - await _context.SaveChangesAsync(); result.Data = forum; - return result; } @@ -71,13 +58,29 @@ namespace Tsi1.BusinessLayer.Services return result; } - public async Task<ServiceResult<List<ForumPreviewDto>>> GetForums(int courseId) + public async Task<ServiceResult<List<ForumPreviewDto>>> GetForums(int sectionId) { var result = new ServiceResult<List<ForumPreviewDto>>(); - var forums = await _context.Forums - .Where(x => x.CourseId == courseId) - .ToListAsync(); + var section = await _context.Sections + .Where(x => x.Id == sectionId) + .Include(x => x.SectionItems) + .ThenInclude(x => x.SectionItemType) + .Include(x => x.SectionItems) + .ThenInclude(x => x.Forum) + .FirstOrDefaultAsync(); + + if (section == null) + { + result.HasError = true; + result.Message = string.Format(ErrorMessages.SectionDoesNotExist, sectionId); + return result; + } + + var forums = section.SectionItems + .Where(x => x.SectionItemType.Name == SectionItemTypes.Forum) + .Select(x => x.Forum) + .ToList(); var forumDtos = _mapper.Map<List<ForumPreviewDto>>(forums); diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionItemService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionItemService.cs new file mode 100644 index 0000000000000000000000000000000000000000..ae0eedca11130f202ca5cc31688ea5725eea6525 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionItemService.cs @@ -0,0 +1,156 @@ +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; +using Tsi1.DataLayer; +using Tsi1.DataLayer.Entities; + +namespace Tsi1.BusinessLayer.Services +{ + public class SectionItemService : ISectionItemService + { + private readonly IMapper _mapper; + private readonly Tsi1Context _context; + private readonly IFileService _fileService; + + public SectionItemService(IMapper mapper, Tsi1Context context, IFileService fileService) + { + _mapper = mapper; + _context = context; + _fileService = fileService; + } + + public async Task<ServiceResult<bool>> Create(SectionItemCreateDto newSectionItem) + { + var sectionItem = _mapper.Map<SectionItem>(newSectionItem); + + var result = await this.SectionItemValidations(sectionItem); + + if (result.HasError) + { + return result; + } + + _context.SectionItems.Add(sectionItem); + await _context.SaveChangesAsync(); + + return result; + } + + public async Task<ServiceResult<bool>> Delete(int sectionItemId) + { + var result = new ServiceResult<bool>(); + + var sectionItem = await _context.SectionItems.FirstOrDefaultAsync(x => x.Id == sectionItemId); + if (sectionItem == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.SectionItemDoesNotExist, sectionItemId)); + return result; + } + + _context.SectionItems.Remove(sectionItem); + await _context.SaveChangesAsync(); + + return result; + } + + public async Task<ServiceResult<bool>> OrderSectionItems(List<OrderDto> orderDtos) + { + var result = new ServiceResult<bool>(); + + var sectionItemIds = orderDtos.Select(x => x.Id); + var orders = orderDtos.Select(x => x.Order).Distinct(); + + if (orders.Count() != orderDtos.Count()) + { + result.HasError = true; + result.AddMessage(ErrorMessages.DuplicateSectionItemOrder); + return result; + } + + var sectionItems = await _context.SectionItems + .Where(x => sectionItemIds.Contains(x.Id)) + .ToListAsync(); + + foreach (var orderDto in orderDtos) + { + var sectionItem = sectionItems.FirstOrDefault(x => x.Id == orderDto.Id); + if (sectionItem == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.SectionItemDoesNotExist, orderDto.Id)); + } + + sectionItem.Order = orderDto.Order; + } + + if (!result.HasError) + { + await _context.SaveChangesAsync(); + } + + return result; + } + + private async Task<ServiceResult<bool>> SectionItemValidations(SectionItem sectionItem) + { + var result = new ServiceResult<bool>(); + + var sectionItemType = await _context.SectionItemTypes + .FirstOrDefaultAsync(x => x.Id == sectionItem.SectionItemTypeId); + + if (sectionItemType == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.InvalidSectionItemType, sectionItem.SectionItemTypeId)); + return result; + } + + if (sectionItemType.Name == SectionItemTypes.Forum) + { + if (sectionItem.Forum == null) + { + result.HasError = true; + result.AddMessage(ErrorMessages.ForumIsNull); + } + + if (sectionItem.File != null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.InvalidSectionItemData, sectionItemType.Name, SectionItemTypes.File)); + } + } + + if (sectionItemType.Name == SectionItemTypes.File) + { + if (sectionItem.File == null) + { + result.HasError = true; + result.AddMessage(ErrorMessages.FileIsNull); + } + + if (sectionItem.Forum != null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.InvalidSectionItemData, sectionItemType.Name, SectionItemTypes.Forum)); + } + + if (!_fileService.ExistFile(sectionItem.File.Path)) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.FileDoesNotExist, sectionItem.File.Path)); + } + } + + return result; + } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionItemTypeService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionItemTypeService.cs new file mode 100644 index 0000000000000000000000000000000000000000..28b4a6b24f979d8e5cd5ee51a46dd62c7d011091 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionItemTypeService.cs @@ -0,0 +1,49 @@ +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; +using Tsi1.DataLayer; + +namespace Tsi1.BusinessLayer.Services +{ + public class SectionItemTypeService : ISectionItemTypeService + { + private readonly Tsi1Context _context; + private readonly IMapper _mapper; + + public SectionItemTypeService(Tsi1Context context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + public async Task<ServiceResult<List<SectionItemTypeDto>>> GetAll() + { + var result = new ServiceResult<List<SectionItemTypeDto>>(); + var sectionItemTypes = await _context.SectionItemTypes.ToListAsync(); + + result.Data = _mapper.Map<List<SectionItemTypeDto>>(sectionItemTypes); + return result; + } + + public async Task<ServiceResult<SectionItemTypeDto>> GetById(int id) + { + var result = new ServiceResult<SectionItemTypeDto>(); + + var sectionItemType = await _context.SectionItemTypes.FirstOrDefaultAsync(x => x.Id == id); + if (sectionItemType == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.SectionItemTypeDoesNotExist, id)); + return result; + } + + result.Data = _mapper.Map<SectionItemTypeDto>(sectionItemType); + return result; + } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionService.cs new file mode 100644 index 0000000000000000000000000000000000000000..9da29bb8ee10dd2800e7977d86582cc564b7917b --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/SectionService.cs @@ -0,0 +1,118 @@ +using AutoMapper; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; +using Tsi1.DataLayer; +using Tsi1.DataLayer.Entities; + +namespace Tsi1.BusinessLayer.Services +{ + public class SectionService : ISectionService + { + private readonly Tsi1Context _context; + private readonly IMapper _mapper; + + public SectionService(Tsi1Context context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task<ServiceResult<bool>> Create(SectionCreateDto newSection) + { + var result = new ServiceResult<bool>(); + + var course = await _context.Courses.FirstOrDefaultAsync(x => x.Id == newSection.CourseId); + if (course == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.CourseDoesNotExist, newSection.CourseId)); + return result; + } + + var section = _mapper.Map<Section>(newSection); + _context.Sections.Add(section); + await _context.SaveChangesAsync(); + + return result; + } + + public async Task<ServiceResult<bool>> Delete(int sectionId) + { + var result = new ServiceResult<bool>(); + + var section = await _context.Sections.FirstOrDefaultAsync(x => x.Id == sectionId); + if (section == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.SectionDoesNotExist, sectionId)); + return result; + } + + _context.Sections.Remove(section); + await _context.SaveChangesAsync(); + return result; + } + + public async Task<ServiceResult<bool>> Modify(int sectionId, string name) + { + var result = new ServiceResult<bool>(); + + var section = await _context.Sections.FirstOrDefaultAsync(x => x.Id == sectionId); + if (section == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.SectionDoesNotExist, sectionId)); + return result; + } + + section.Name = name; + await _context.SaveChangesAsync(); + return result; + } + + public async Task<ServiceResult<bool>> OrderSections(List<OrderDto> orderDtos) + { + var result = new ServiceResult<bool>(); + + var sectionIds = orderDtos.Select(x => x.Id); + var orders = orderDtos.Select(x => x.Order).Distinct(); + + if (orders.Count() != orderDtos.Count()) + { + result.HasError = true; + result.AddMessage(ErrorMessages.DuplicateSectionOrder); + return result; + } + + var sections = await _context.Sections + .Where(x => sectionIds.Contains(x.Id)) + .ToListAsync(); + + foreach (var orderDto in orderDtos) + { + var section = sections.FirstOrDefault(x => x.Id == orderDto.Id); + if (section == null) + { + result.HasError = true; + result.AddMessage(string.Format(ErrorMessages.SectionDoesNotExist, orderDto.Id)); + } + + section.Order = orderDto.Order; + } + + if (!result.HasError) + { + await _context.SaveChangesAsync(); + } + + return result; + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs index 0f4f050705ec5081ef0cd43de7f76b59f259d269..942858fad3a54d8c23bb6142258eb9bdf7e14b23 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs @@ -10,19 +10,16 @@ namespace Tsi1.DataLayer.Entities { StudentCourses = new HashSet<StudentCourse>(); ProfessorCourses = new HashSet<ProfessorCourse>(); - Forums = new HashSet<Forum>(); + Sections = new HashSet<Section>(); } public int Id { get; set; } - public string Name { get; set; } - public int TenantId { get; set; } public Tenant Tenant { get; set; } - public ICollection<StudentCourse> StudentCourses { get; set; } public ICollection<ProfessorCourse> ProfessorCourses { get; set; } - public ICollection<Forum> Forums { get; set; } + public ICollection<Section> Sections { get; set; } } } diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/File.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/File.cs index 4643d9c27c0f79917b66a41b0bff4435b6cfdc21..ea3324a77bd99ec20579f7aee468186c3c4bd643 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Entities/File.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/File.cs @@ -7,9 +7,9 @@ namespace Tsi1.DataLayer.Entities public class File { public int Id { get; set; } - public string Name { get; set; } - public string Path { get; set; } + + public SectionItem SectionItem { get; set; } } } diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs index 197e1e01af9d0576764a418b53a2e165a0834ada..086df15e9e457f34c6715fb4a79a99b44da5bcb1 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs @@ -13,13 +13,9 @@ namespace Tsi1.DataLayer.Entities } public int Id { get; set; } - public string Name { get; set; } - public int CourseId { get; set; } - - public Course Course { get; set; } - + public SectionItem SectionItem { get; set; } public ICollection<Post> Posts { get; set; } public ICollection<ForumUser> ForumUsers { get; set; } } diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Section.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Section.cs new file mode 100644 index 0000000000000000000000000000000000000000..db0f9d9a724bcadbf044e92cc5742585eb4208e9 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Section.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.DataLayer.Entities +{ + public class Section + { + public Section() + { + SectionItems = new HashSet<SectionItem>(); + } + + public int Id { get; set; } + public int CourseId { get; set; } + public string Name { get; set; } + public int Order { get; set; } + + public Course Course { get; set; } + public ICollection<SectionItem> SectionItems { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/SectionItem.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/SectionItem.cs new file mode 100644 index 0000000000000000000000000000000000000000..3bd1ea22fc82fb58c6cc1015adeeae598bc64c67 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/SectionItem.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.DataLayer.Entities +{ + public class SectionItem + { + public int Id { get; set; } + public int Order { get; set; } + public int SectionId { get; set; } + public int SectionItemTypeId { get; set; } + public int? ForumId { get; set; } + public int? FileId { get; set; } + + public Section Section { get; set; } + public SectionItemType SectionItemType { get; set; } + public Forum Forum { get; set; } + public File File { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/SectionItemType.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/SectionItemType.cs new file mode 100644 index 0000000000000000000000000000000000000000..438d864848fefdcab64360ffd4790474f66f1eb5 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/SectionItemType.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.DataLayer.Entities +{ + public class SectionItemType + { + public SectionItemType() + { + SectionItems = new HashSet<SectionItem>(); + } + + public int Id { get; set; } + public string Name { get; set; } + + public ICollection<SectionItem> SectionItems { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs index ac2d37069880b40303ee5208d896a1b3e1ed968e..777e05129d429060775725fc5e81920c96ddf2e6 100644 --- a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs +++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs @@ -1,30 +1,18 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -using System; -using System.Collections.Generic; -using System.Security.Cryptography.X509Certificates; -using System.Text; using Tsi1.DataLayer.Entities; namespace Tsi1.DataLayer.EntityConfiguration { - class ForumConfiguration : IEntityTypeConfiguration<Forum> + public class ForumConfiguration : IEntityTypeConfiguration<Forum> { public void Configure(EntityTypeBuilder<Forum> builder) { builder.HasKey(x => x.Id); - builder.HasIndex(x => new { x.CourseId, x.Name}) - .IsUnique(); - builder.Property(x => x.Name) .IsRequired() .HasColumnType("character varying(50)"); - - builder.HasOne(x => x.Course) - .WithMany(x => x.Forums) - .HasForeignKey(x => x.CourseId); - } } } diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/SectionConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/SectionConfiguration.cs new file mode 100644 index 0000000000000000000000000000000000000000..b87104c8039f37e3e020ddf226dc1bc73e75177c --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/SectionConfiguration.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using System; +using System.Collections.Generic; +using System.Text; +using Tsi1.DataLayer.Entities; + +namespace Tsi1.DataLayer.EntityConfiguration +{ + public class SectionConfiguration : IEntityTypeConfiguration<Section> + { + public void Configure(EntityTypeBuilder<Section> builder) + { + builder.HasKey(x => x.Id); + + builder.Property(x => x.Name) + .IsRequired() + .HasColumnType("character varying(255)"); + + builder.Property(x => x.Order) + .IsRequired(); + + builder.HasOne(x => x.Course) + .WithMany(x => x.Sections) + .HasForeignKey(x => x.CourseId); + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/SectionItemConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/SectionItemConfiguration.cs new file mode 100644 index 0000000000000000000000000000000000000000..ffcda8dfd6c0f26718219dd2e30e04fcd6a1db81 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/SectionItemConfiguration.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using System; +using System.Collections.Generic; +using System.Text; +using Tsi1.DataLayer.Entities; + +namespace Tsi1.DataLayer.EntityConfiguration +{ + public class SectionItemConfiguration : IEntityTypeConfiguration<SectionItem> + { + public void Configure(EntityTypeBuilder<SectionItem> builder) + { + builder.HasKey(x => x.Id); + + builder.Property(x => x.Order) + .IsRequired(); + + builder.HasOne(x => x.File) + .WithOne(x => x.SectionItem) + .HasForeignKey<SectionItem>(x => x.FileId); + + builder.HasOne(x => x.Forum) + .WithOne(x => x.SectionItem) + .HasForeignKey<SectionItem>(x => x.ForumId); + + builder.HasOne(x => x.SectionItemType) + .WithMany(x => x.SectionItems) + .HasForeignKey(x => x.SectionItemTypeId); + + builder.HasOne(x => x.Section) + .WithMany(x => x.SectionItems) + .HasForeignKey(x => x.SectionId); + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/SectionItemTypeConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/SectionItemTypeConfiguration.cs new file mode 100644 index 0000000000000000000000000000000000000000..fdef28196b29b67daa5bea60219ad4370d7067f9 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/SectionItemTypeConfiguration.cs @@ -0,0 +1,21 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using System; +using System.Collections.Generic; +using System.Text; +using Tsi1.DataLayer.Entities; + +namespace Tsi1.DataLayer.EntityConfiguration +{ + public class SectionItemTypeConfiguration : IEntityTypeConfiguration<SectionItemType> + { + public void Configure(EntityTypeBuilder<SectionItemType> builder) + { + builder.HasKey(x => x.Id); + + builder.Property(x => x.Name) + .IsRequired() + .HasColumnType("character varying(100)"); + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201106232002_section_items.Designer.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201106232002_section_items.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..bffe3f02174a06798dd1fb577ae58969db7a02e8 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201106232002_section_items.Designer.cs @@ -0,0 +1,612 @@ +// <auto-generated /> +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Tsi1.DataLayer; + +namespace Tsi1.DataLayer.Migrations +{ + [DbContext(typeof(Tsi1Context))] + [Migration("20201106232002_section_items")] + partial class section_items + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Connection", b => + { + b.Property<string>("ConnectionId") + .HasColumnType("text"); + + b.Property<string>("GroupName") + .HasColumnType("text"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("ConnectionId"); + + b.HasIndex("GroupName"); + + b.ToTable("Connections"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Course", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("Name", "TenantId") + .IsUnique(); + + b.ToTable("Courses"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.File", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<string>("Path") + .IsRequired() + .HasColumnType("character varying(1000)"); + + b.Property<int>("SectionItemId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("Path") + .IsUnique(); + + b.ToTable("Files"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int?>("CourseId") + .HasColumnType("integer"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("SectionItemId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CourseId"); + + b.ToTable("Forums"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b => + { + b.Property<int>("ForumId") + .HasColumnType("integer"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("ForumId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ForumUsers"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Group", b => + { + b.Property<string>("Name") + .HasColumnType("text"); + + b.HasKey("Name"); + + b.ToTable("Groups"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<DateTime>("Date") + .HasColumnType("timestamp without time zone"); + + b.Property<int>("ForumId") + .HasColumnType("integer"); + + b.Property<string>("Title") + .IsRequired() + .HasColumnType("character varying(100)"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("ForumId", "Title") + .IsUnique(); + + b.ToTable("Posts"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Content") + .IsRequired() + .HasColumnType("character varying(10485760)"); + + b.Property<DateTime>("Date") + .HasColumnType("timestamp without time zone"); + + b.Property<int>("PostId") + .HasColumnType("integer"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.HasIndex("UserId"); + + b.ToTable("PostMessages"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Professor", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("IdentityCard") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("IdentityCard", "TenantId") + .IsUnique(); + + b.ToTable("Professors"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b => + { + b.Property<int>("ProfessorId") + .HasColumnType("integer"); + + b.Property<int>("CourseId") + .HasColumnType("integer"); + + b.HasKey("ProfessorId", "CourseId"); + + b.HasIndex("CourseId"); + + b.ToTable("ProfessorCourses"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Section", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<int>("Order") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Sections"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItem", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int?>("FileId") + .HasColumnType("integer"); + + b.Property<int?>("ForumId") + .HasColumnType("integer"); + + b.Property<int>("Order") + .HasColumnType("integer"); + + b.Property<int>("SectionId") + .HasColumnType("integer"); + + b.Property<int>("SectionItemTypeId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("FileId") + .IsUnique(); + + b.HasIndex("ForumId") + .IsUnique(); + + b.HasIndex("SectionId"); + + b.HasIndex("SectionItemTypeId"); + + b.ToTable("SectionItems"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItemType", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.ToTable("SectionItemTypes"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int>("Age") + .HasColumnType("integer"); + + b.Property<string>("IdentityCard") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("IdentityCard", "TenantId") + .IsUnique(); + + b.ToTable("Students"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b => + { + b.Property<int>("StudentId") + .HasColumnType("integer"); + + b.Property<int>("CourseId") + .HasColumnType("integer"); + + b.HasKey("StudentId", "CourseId"); + + b.HasIndex("CourseId"); + + b.ToTable("StudentCourses"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Tenant", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Tenants"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Email") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<string>("FirstName") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<string>("LastName") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<string>("Password") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<int?>("ProfessorId") + .HasColumnType("integer"); + + b.Property<int?>("StudentId") + .HasColumnType("integer"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.Property<int>("UserTypeId") + .HasColumnType("integer"); + + b.Property<string>("Username") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProfessorId") + .IsUnique(); + + b.HasIndex("StudentId") + .IsUnique(); + + b.HasIndex("TenantId"); + + b.HasIndex("UserTypeId"); + + b.HasIndex("Username", "TenantId") + .IsUnique(); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.UserType", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("UserTypes"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Connection", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Group", "Group") + .WithMany("Connections") + .HasForeignKey("GroupName"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Course", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Courses") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", null) + .WithMany("Forums") + .HasForeignKey("CourseId"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") + .WithMany("ForumUsers") + .HasForeignKey("ForumId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("ForumUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") + .WithMany("Posts") + .HasForeignKey("ForumId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("Posts") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Post", "Post") + .WithMany("PostMessages") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("PostMessages") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Professor", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Professors") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("ProfessorCourses") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor") + .WithMany("ProfessorCourses") + .HasForeignKey("ProfessorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItem", b => + { + b.HasOne("Tsi1.DataLayer.Entities.File", "File") + .WithOne("SectionItem") + .HasForeignKey("Tsi1.DataLayer.Entities.SectionItem", "FileId"); + + b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") + .WithOne("SectionItem") + .HasForeignKey("Tsi1.DataLayer.Entities.SectionItem", "ForumId"); + + b.HasOne("Tsi1.DataLayer.Entities.Section", "Section") + .WithMany("SectionItems") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.SectionItemType", "SectionItemType") + .WithMany("SectionItems") + .HasForeignKey("SectionItemTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Students") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("StudentCourses") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.Student", "Student") + .WithMany("StudentCourses") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor") + .WithOne("User") + .HasForeignKey("Tsi1.DataLayer.Entities.User", "ProfessorId"); + + b.HasOne("Tsi1.DataLayer.Entities.Student", "Student") + .WithOne("User") + .HasForeignKey("Tsi1.DataLayer.Entities.User", "StudentId"); + + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Users") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.UserType", "UserType") + .WithMany() + .HasForeignKey("UserTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201106232002_section_items.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201106232002_section_items.cs new file mode 100644 index 0000000000000000000000000000000000000000..c3b4c6e50eddb56dc2e4f127073d40e3123cf87d --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201106232002_section_items.cs @@ -0,0 +1,191 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace Tsi1.DataLayer.Migrations +{ + public partial class section_items : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Forums_Courses_CourseId", + table: "Forums"); + + migrationBuilder.DropIndex( + name: "IX_Forums_CourseId_Name", + table: "Forums"); + + migrationBuilder.AlterColumn<int>( + name: "CourseId", + table: "Forums", + nullable: true, + oldClrType: typeof(int), + oldType: "integer"); + + migrationBuilder.AddColumn<int>( + name: "SectionItemId", + table: "Forums", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn<int>( + name: "SectionItemId", + table: "Files", + nullable: false, + defaultValue: 0); + + migrationBuilder.CreateTable( + name: "SectionItemTypes", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column<string>(type: "character varying(100)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SectionItemTypes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Sections", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column<string>(type: "character varying(255)", nullable: false), + Order = table.Column<int>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Sections", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SectionItems", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Order = table.Column<int>(nullable: false), + SectionId = table.Column<int>(nullable: false), + SectionItemTypeId = table.Column<int>(nullable: false), + ForumId = table.Column<int>(nullable: true), + FileId = table.Column<int>(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_SectionItems", x => x.Id); + table.ForeignKey( + name: "FK_SectionItems_Files_FileId", + column: x => x.FileId, + principalTable: "Files", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_SectionItems_Forums_ForumId", + column: x => x.ForumId, + principalTable: "Forums", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_SectionItems_Sections_SectionId", + column: x => x.SectionId, + principalTable: "Sections", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_SectionItems_SectionItemTypes_SectionItemTypeId", + column: x => x.SectionItemTypeId, + principalTable: "SectionItemTypes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Forums_CourseId", + table: "Forums", + column: "CourseId"); + + migrationBuilder.CreateIndex( + name: "IX_SectionItems_FileId", + table: "SectionItems", + column: "FileId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_SectionItems_ForumId", + table: "SectionItems", + column: "ForumId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_SectionItems_SectionId", + table: "SectionItems", + column: "SectionId"); + + migrationBuilder.CreateIndex( + name: "IX_SectionItems_SectionItemTypeId", + table: "SectionItems", + column: "SectionItemTypeId"); + + migrationBuilder.AddForeignKey( + name: "FK_Forums_Courses_CourseId", + table: "Forums", + column: "CourseId", + principalTable: "Courses", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Forums_Courses_CourseId", + table: "Forums"); + + migrationBuilder.DropTable( + name: "SectionItems"); + + migrationBuilder.DropTable( + name: "Sections"); + + migrationBuilder.DropTable( + name: "SectionItemTypes"); + + migrationBuilder.DropIndex( + name: "IX_Forums_CourseId", + table: "Forums"); + + migrationBuilder.DropColumn( + name: "SectionItemId", + table: "Forums"); + + migrationBuilder.DropColumn( + name: "SectionItemId", + table: "Files"); + + migrationBuilder.AlterColumn<int>( + name: "CourseId", + table: "Forums", + type: "integer", + nullable: false, + oldClrType: typeof(int), + oldNullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Forums_CourseId_Name", + table: "Forums", + columns: new[] { "CourseId", "Name" }, + unique: true); + + migrationBuilder.AddForeignKey( + name: "FK_Forums_Courses_CourseId", + table: "Forums", + column: "CourseId", + principalTable: "Courses", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107172316_sections.Designer.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107172316_sections.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..8b4eba532c5dfd4c75ef851d9d13941fd7e51edd --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107172316_sections.Designer.cs @@ -0,0 +1,614 @@ +// <auto-generated /> +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Tsi1.DataLayer; + +namespace Tsi1.DataLayer.Migrations +{ + [DbContext(typeof(Tsi1Context))] + [Migration("20201107172316_sections")] + partial class sections + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Connection", b => + { + b.Property<string>("ConnectionId") + .HasColumnType("text"); + + b.Property<string>("GroupName") + .HasColumnType("text"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("ConnectionId"); + + b.HasIndex("GroupName"); + + b.ToTable("Connections"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Course", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("Name", "TenantId") + .IsUnique(); + + b.ToTable("Courses"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.File", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<string>("Path") + .IsRequired() + .HasColumnType("character varying(1000)"); + + b.Property<int>("SectionItemId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("Path") + .IsUnique(); + + b.ToTable("Files"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("SectionItemId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Forums"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b => + { + b.Property<int>("ForumId") + .HasColumnType("integer"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("ForumId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ForumUsers"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Group", b => + { + b.Property<string>("Name") + .HasColumnType("text"); + + b.HasKey("Name"); + + b.ToTable("Groups"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<DateTime>("Date") + .HasColumnType("timestamp without time zone"); + + b.Property<int>("ForumId") + .HasColumnType("integer"); + + b.Property<string>("Title") + .IsRequired() + .HasColumnType("character varying(100)"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("ForumId", "Title") + .IsUnique(); + + b.ToTable("Posts"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Content") + .IsRequired() + .HasColumnType("character varying(10485760)"); + + b.Property<DateTime>("Date") + .HasColumnType("timestamp without time zone"); + + b.Property<int>("PostId") + .HasColumnType("integer"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.HasIndex("UserId"); + + b.ToTable("PostMessages"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Professor", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("IdentityCard") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("IdentityCard", "TenantId") + .IsUnique(); + + b.ToTable("Professors"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b => + { + b.Property<int>("ProfessorId") + .HasColumnType("integer"); + + b.Property<int>("CourseId") + .HasColumnType("integer"); + + b.HasKey("ProfessorId", "CourseId"); + + b.HasIndex("CourseId"); + + b.ToTable("ProfessorCourses"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Section", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int>("CourseId") + .HasColumnType("integer"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<int>("Order") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CourseId"); + + b.ToTable("Sections"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItem", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int?>("FileId") + .HasColumnType("integer"); + + b.Property<int?>("ForumId") + .HasColumnType("integer"); + + b.Property<int>("Order") + .HasColumnType("integer"); + + b.Property<int>("SectionId") + .HasColumnType("integer"); + + b.Property<int>("SectionItemTypeId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("FileId") + .IsUnique(); + + b.HasIndex("ForumId") + .IsUnique(); + + b.HasIndex("SectionId"); + + b.HasIndex("SectionItemTypeId"); + + b.ToTable("SectionItems"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItemType", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.ToTable("SectionItemTypes"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int>("Age") + .HasColumnType("integer"); + + b.Property<string>("IdentityCard") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("IdentityCard", "TenantId") + .IsUnique(); + + b.ToTable("Students"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b => + { + b.Property<int>("StudentId") + .HasColumnType("integer"); + + b.Property<int>("CourseId") + .HasColumnType("integer"); + + b.HasKey("StudentId", "CourseId"); + + b.HasIndex("CourseId"); + + b.ToTable("StudentCourses"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Tenant", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Tenants"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Email") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<string>("FirstName") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<string>("LastName") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<string>("Password") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<int?>("ProfessorId") + .HasColumnType("integer"); + + b.Property<int?>("StudentId") + .HasColumnType("integer"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.Property<int>("UserTypeId") + .HasColumnType("integer"); + + b.Property<string>("Username") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProfessorId") + .IsUnique(); + + b.HasIndex("StudentId") + .IsUnique(); + + b.HasIndex("TenantId"); + + b.HasIndex("UserTypeId"); + + b.HasIndex("Username", "TenantId") + .IsUnique(); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.UserType", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("UserTypes"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Connection", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Group", "Group") + .WithMany("Connections") + .HasForeignKey("GroupName"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Course", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Courses") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") + .WithMany("ForumUsers") + .HasForeignKey("ForumId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("ForumUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") + .WithMany("Posts") + .HasForeignKey("ForumId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("Posts") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Post", "Post") + .WithMany("PostMessages") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("PostMessages") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Professor", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Professors") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("ProfessorCourses") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor") + .WithMany("ProfessorCourses") + .HasForeignKey("ProfessorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Section", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("Sections") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItem", b => + { + b.HasOne("Tsi1.DataLayer.Entities.File", "File") + .WithOne("SectionItem") + .HasForeignKey("Tsi1.DataLayer.Entities.SectionItem", "FileId"); + + b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") + .WithOne("SectionItem") + .HasForeignKey("Tsi1.DataLayer.Entities.SectionItem", "ForumId"); + + b.HasOne("Tsi1.DataLayer.Entities.Section", "Section") + .WithMany("SectionItems") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.SectionItemType", "SectionItemType") + .WithMany("SectionItems") + .HasForeignKey("SectionItemTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Students") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("StudentCourses") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.Student", "Student") + .WithMany("StudentCourses") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor") + .WithOne("User") + .HasForeignKey("Tsi1.DataLayer.Entities.User", "ProfessorId"); + + b.HasOne("Tsi1.DataLayer.Entities.Student", "Student") + .WithOne("User") + .HasForeignKey("Tsi1.DataLayer.Entities.User", "StudentId"); + + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Users") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.UserType", "UserType") + .WithMany() + .HasForeignKey("UserTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107172316_sections.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107172316_sections.cs new file mode 100644 index 0000000000000000000000000000000000000000..5166873d947bef5f921335cb75be228b0314b415 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107172316_sections.cs @@ -0,0 +1,75 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Tsi1.DataLayer.Migrations +{ + public partial class sections : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Forums_Courses_CourseId", + table: "Forums"); + + migrationBuilder.DropIndex( + name: "IX_Forums_CourseId", + table: "Forums"); + + migrationBuilder.DropColumn( + name: "CourseId", + table: "Forums"); + + migrationBuilder.AddColumn<int>( + name: "CourseId", + table: "Sections", + nullable: false, + defaultValue: 0); + + migrationBuilder.CreateIndex( + name: "IX_Sections_CourseId", + table: "Sections", + column: "CourseId"); + + migrationBuilder.AddForeignKey( + name: "FK_Sections_Courses_CourseId", + table: "Sections", + column: "CourseId", + principalTable: "Courses", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Sections_Courses_CourseId", + table: "Sections"); + + migrationBuilder.DropIndex( + name: "IX_Sections_CourseId", + table: "Sections"); + + migrationBuilder.DropColumn( + name: "CourseId", + table: "Sections"); + + migrationBuilder.AddColumn<int>( + name: "CourseId", + table: "Forums", + type: "integer", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_Forums_CourseId", + table: "Forums", + column: "CourseId"); + + migrationBuilder.AddForeignKey( + name: "FK_Forums_Courses_CourseId", + table: "Forums", + column: "CourseId", + principalTable: "Courses", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107181002_fix-section-items.Designer.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107181002_fix-section-items.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..27f320d9ce062b4e979b01b4f86858827274e92b --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107181002_fix-section-items.Designer.cs @@ -0,0 +1,608 @@ +// <auto-generated /> +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Tsi1.DataLayer; + +namespace Tsi1.DataLayer.Migrations +{ + [DbContext(typeof(Tsi1Context))] + [Migration("20201107181002_fix-section-items")] + partial class fixsectionitems + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Connection", b => + { + b.Property<string>("ConnectionId") + .HasColumnType("text"); + + b.Property<string>("GroupName") + .HasColumnType("text"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("ConnectionId"); + + b.HasIndex("GroupName"); + + b.ToTable("Connections"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Course", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("Name", "TenantId") + .IsUnique(); + + b.ToTable("Courses"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.File", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<string>("Path") + .IsRequired() + .HasColumnType("character varying(1000)"); + + b.HasKey("Id"); + + b.HasIndex("Path") + .IsUnique(); + + b.ToTable("Files"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.ToTable("Forums"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b => + { + b.Property<int>("ForumId") + .HasColumnType("integer"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("ForumId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ForumUsers"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Group", b => + { + b.Property<string>("Name") + .HasColumnType("text"); + + b.HasKey("Name"); + + b.ToTable("Groups"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<DateTime>("Date") + .HasColumnType("timestamp without time zone"); + + b.Property<int>("ForumId") + .HasColumnType("integer"); + + b.Property<string>("Title") + .IsRequired() + .HasColumnType("character varying(100)"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("ForumId", "Title") + .IsUnique(); + + b.ToTable("Posts"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Content") + .IsRequired() + .HasColumnType("character varying(10485760)"); + + b.Property<DateTime>("Date") + .HasColumnType("timestamp without time zone"); + + b.Property<int>("PostId") + .HasColumnType("integer"); + + b.Property<int>("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.HasIndex("UserId"); + + b.ToTable("PostMessages"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Professor", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("IdentityCard") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("IdentityCard", "TenantId") + .IsUnique(); + + b.ToTable("Professors"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b => + { + b.Property<int>("ProfessorId") + .HasColumnType("integer"); + + b.Property<int>("CourseId") + .HasColumnType("integer"); + + b.HasKey("ProfessorId", "CourseId"); + + b.HasIndex("CourseId"); + + b.ToTable("ProfessorCourses"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Section", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int>("CourseId") + .HasColumnType("integer"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<int>("Order") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CourseId"); + + b.ToTable("Sections"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItem", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int?>("FileId") + .HasColumnType("integer"); + + b.Property<int?>("ForumId") + .HasColumnType("integer"); + + b.Property<int>("Order") + .HasColumnType("integer"); + + b.Property<int>("SectionId") + .HasColumnType("integer"); + + b.Property<int>("SectionItemTypeId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("FileId") + .IsUnique(); + + b.HasIndex("ForumId") + .IsUnique(); + + b.HasIndex("SectionId"); + + b.HasIndex("SectionItemTypeId"); + + b.ToTable("SectionItems"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItemType", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.ToTable("SectionItemTypes"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int>("Age") + .HasColumnType("integer"); + + b.Property<string>("IdentityCard") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TenantId"); + + b.HasIndex("IdentityCard", "TenantId") + .IsUnique(); + + b.ToTable("Students"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b => + { + b.Property<int>("StudentId") + .HasColumnType("integer"); + + b.Property<int>("CourseId") + .HasColumnType("integer"); + + b.HasKey("StudentId", "CourseId"); + + b.HasIndex("CourseId"); + + b.ToTable("StudentCourses"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Tenant", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("Tenants"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Email") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<string>("FirstName") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<string>("LastName") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<string>("Password") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<int?>("ProfessorId") + .HasColumnType("integer"); + + b.Property<int?>("StudentId") + .HasColumnType("integer"); + + b.Property<int>("TenantId") + .HasColumnType("integer"); + + b.Property<int>("UserTypeId") + .HasColumnType("integer"); + + b.Property<string>("Username") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("ProfessorId") + .IsUnique(); + + b.HasIndex("StudentId") + .IsUnique(); + + b.HasIndex("TenantId"); + + b.HasIndex("UserTypeId"); + + b.HasIndex("Username", "TenantId") + .IsUnique(); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.UserType", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("UserTypes"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Connection", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Group", "Group") + .WithMany("Connections") + .HasForeignKey("GroupName"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Course", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Courses") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") + .WithMany("ForumUsers") + .HasForeignKey("ForumId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("ForumUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") + .WithMany("Posts") + .HasForeignKey("ForumId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("Posts") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Post", "Post") + .WithMany("PostMessages") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.User", "User") + .WithMany("PostMessages") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Professor", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Professors") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("ProfessorCourses") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor") + .WithMany("ProfessorCourses") + .HasForeignKey("ProfessorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Section", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("Sections") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItem", b => + { + b.HasOne("Tsi1.DataLayer.Entities.File", "File") + .WithOne("SectionItem") + .HasForeignKey("Tsi1.DataLayer.Entities.SectionItem", "FileId"); + + b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") + .WithOne("SectionItem") + .HasForeignKey("Tsi1.DataLayer.Entities.SectionItem", "ForumId"); + + b.HasOne("Tsi1.DataLayer.Entities.Section", "Section") + .WithMany("SectionItems") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.SectionItemType", "SectionItemType") + .WithMany("SectionItems") + .HasForeignKey("SectionItemTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Students") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("StudentCourses") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.Student", "Student") + .WithMany("StudentCourses") + .HasForeignKey("StudentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor") + .WithOne("User") + .HasForeignKey("Tsi1.DataLayer.Entities.User", "ProfessorId"); + + b.HasOne("Tsi1.DataLayer.Entities.Student", "Student") + .WithOne("User") + .HasForeignKey("Tsi1.DataLayer.Entities.User", "StudentId"); + + b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") + .WithMany("Users") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.UserType", "UserType") + .WithMany() + .HasForeignKey("UserTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107181002_fix-section-items.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107181002_fix-section-items.cs new file mode 100644 index 0000000000000000000000000000000000000000..8c62edd2ca588155db26ae64cdef48b67efdc034 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201107181002_fix-section-items.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Tsi1.DataLayer.Migrations +{ + public partial class fixsectionitems : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SectionItemId", + table: "Forums"); + + migrationBuilder.DropColumn( + name: "SectionItemId", + table: "Files"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn<int>( + name: "SectionItemId", + table: "Forums", + type: "integer", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn<int>( + name: "SectionItemId", + table: "Files", + type: "integer", + nullable: false, + defaultValue: 0); + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs index 9f2b80da778b9cfc5bb392f6faa481cab6f4eea7..e661f62fc22750b698b1da14d4ac889d01af8e80 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs @@ -91,18 +91,12 @@ namespace Tsi1.DataLayer.Migrations .HasColumnType("integer") .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); - b.Property<int>("CourseId") - .HasColumnType("integer"); - b.Property<string>("Name") .IsRequired() .HasColumnType("character varying(50)"); b.HasKey("Id"); - b.HasIndex("CourseId", "Name") - .IsUnique(); - b.ToTable("Forums"); }); @@ -229,6 +223,83 @@ namespace Tsi1.DataLayer.Migrations b.ToTable("ProfessorCourses"); }); + modelBuilder.Entity("Tsi1.DataLayer.Entities.Section", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int>("CourseId") + .HasColumnType("integer"); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(255)"); + + b.Property<int>("Order") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CourseId"); + + b.ToTable("Sections"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItem", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<int?>("FileId") + .HasColumnType("integer"); + + b.Property<int?>("ForumId") + .HasColumnType("integer"); + + b.Property<int>("Order") + .HasColumnType("integer"); + + b.Property<int>("SectionId") + .HasColumnType("integer"); + + b.Property<int>("SectionItemTypeId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("FileId") + .IsUnique(); + + b.HasIndex("ForumId") + .IsUnique(); + + b.HasIndex("SectionId"); + + b.HasIndex("SectionItemTypeId"); + + b.ToTable("SectionItems"); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItemType", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property<string>("Name") + .IsRequired() + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.ToTable("SectionItemTypes"); + }); + modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b => { b.Property<int>("Id") @@ -382,15 +453,6 @@ namespace Tsi1.DataLayer.Migrations .IsRequired(); }); - modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b => - { - b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") - .WithMany("Forums") - .HasForeignKey("CourseId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b => { b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") @@ -460,6 +522,38 @@ namespace Tsi1.DataLayer.Migrations .IsRequired(); }); + modelBuilder.Entity("Tsi1.DataLayer.Entities.Section", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("Sections") + .HasForeignKey("CourseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Tsi1.DataLayer.Entities.SectionItem", b => + { + b.HasOne("Tsi1.DataLayer.Entities.File", "File") + .WithOne("SectionItem") + .HasForeignKey("Tsi1.DataLayer.Entities.SectionItem", "FileId"); + + b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum") + .WithOne("SectionItem") + .HasForeignKey("Tsi1.DataLayer.Entities.SectionItem", "ForumId"); + + b.HasOne("Tsi1.DataLayer.Entities.Section", "Section") + .WithMany("SectionItems") + .HasForeignKey("SectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Tsi1.DataLayer.Entities.SectionItemType", "SectionItemType") + .WithMany("SectionItems") + .HasForeignKey("SectionItemTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b => { b.HasOne("Tsi1.DataLayer.Entities.Tenant", "Tenant") diff --git a/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs b/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs index d442517b50b82f0ebd6f86812ac69f463cd16239..ba1524c725417ba94a5672a0254a9cd05d66f911 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs @@ -24,6 +24,9 @@ namespace Tsi1.DataLayer public DbSet<Group> Groups { get; set; } public DbSet<Connection> Connections { get; set; } public DbSet<File> Files { get; set; } + public DbSet<Section> Sections { get; set; } + public DbSet<SectionItem> SectionItems { get; set; } + public DbSet<SectionItemType> SectionItemTypes { get; set; } public Tsi1Context(DbContextOptions options) : base(options) { } @@ -45,6 +48,9 @@ namespace Tsi1.DataLayer modelBuilder.ApplyConfiguration(new GroupConfiguration()); modelBuilder.ApplyConfiguration(new ConnectionConfiguration()); modelBuilder.ApplyConfiguration(new FileConfiguration()); + modelBuilder.ApplyConfiguration(new SectionConfiguration()); + modelBuilder.ApplyConfiguration(new SectionItemConfiguration()); + modelBuilder.ApplyConfiguration(new SectionItemTypeConfiguration()); } } }