diff --git a/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs b/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs new file mode 100644 index 0000000000000000000000000000000000000000..c0e99fbbcffdbea35382eda2355c5ce83d4ce6f6 --- /dev/null +++ b/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; + +namespace Tsi1.Api.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class ForumController : ControllerBase + { + private readonly IForumService _forumService; + + public ForumController(IForumService forumService) + { + _forumService = forumService; + } + + [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] + [HttpGet("GetForums/{courseId}")] + public async Task<IActionResult> GetForums(int courseId) + { + var result = await _forumService.GetForums(courseId); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(result.Data); + } + + [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] + [HttpPost("Create")] + public async Task<IActionResult> Create(ForumCreateDto newForum) + { + var result = await _forumService.Create(newForum); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + + [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] + [HttpDelete("Delete/{forumId}")] + public async Task<IActionResult> Delete(int forumId) + { + var result = await _forumService.Delete(forumId); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + } +} diff --git a/Tsi1.Api/Tsi1.Api/Controllers/PostController.cs b/Tsi1.Api/Tsi1.Api/Controllers/PostController.cs new file mode 100644 index 0000000000000000000000000000000000000000..eb1c19e5a54fc654f061ea3fea103b473a04ec17 --- /dev/null +++ b/Tsi1.Api/Tsi1.Api/Controllers/PostController.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; + +namespace Tsi1.Api.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class PostController : ControllerBase + { + private readonly IPostService _postService; + + public PostController(IPostService postService) + { + _postService = postService; + } + + [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] + [HttpGet("GetPosts/{forumId}")] + public async Task<IActionResult> GetPosts(int forumId) + { + var result = await _postService.GetPosts(forumId); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(result.Data); + } + + [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] + [HttpPost("Create")] + public async Task<IActionResult> Create(PostCreateDto newPost) + { + var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value); + + newPost.UserId = userId; + + var result = await _postService.Create(newPost); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + + [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] + [HttpDelete("Delete/{postId}")] + public async Task<IActionResult> Delete(int postId) + { + var result = await _postService.Delete(postId); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + } +} diff --git a/Tsi1.Api/Tsi1.Api/Controllers/PostMessageController.cs b/Tsi1.Api/Tsi1.Api/Controllers/PostMessageController.cs new file mode 100644 index 0000000000000000000000000000000000000000..cf2cbb93fc1d54a5af16c361bd62d3d9f17425b2 --- /dev/null +++ b/Tsi1.Api/Tsi1.Api/Controllers/PostMessageController.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; + +namespace Tsi1.Api.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class PostMessageController : ControllerBase + { + private readonly IPostMessageService _postMessageService; + + public PostMessageController(IPostMessageService postMessageService) + { + _postMessageService = postMessageService; + } + + [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] + [HttpGet("GetPostMessages/{postId}")] + public async Task<IActionResult> GetPostMessagesPosts(int postId) + { + var result = await _postMessageService.GetPostMessages(postId); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(result.Data); + } + + [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] + [HttpPost("Create")] + public async Task<IActionResult> Create(PostMessageCreateDto newPostMessage) + { + var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value); + + newPostMessage.UserId = userId; + + var result = await _postMessageService.Create(newPostMessage); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + + [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] + [HttpDelete("Delete/{postMessageId}")] + public async Task<IActionResult> Delete(int postMessageId) + { + var result = await _postMessageService.Delete(postMessageId); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(); + } + } +} diff --git a/Tsi1.Api/Tsi1.Api/Startup.cs b/Tsi1.Api/Tsi1.Api/Startup.cs index 8dd2b590986be674b348bbee1eeefc22d26c280b..0c5c2155f2cabb390a140c0d999df314e08957b1 100644 --- a/Tsi1.Api/Tsi1.Api/Startup.cs +++ b/Tsi1.Api/Tsi1.Api/Startup.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using AutoMapper; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -16,6 +17,7 @@ using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using Tsi1.Api.Infrastructure; +using Tsi1.BusinessLayer.Helpers; using Tsi1.BusinessLayer.Interfaces; using Tsi1.BusinessLayer.Services; using Tsi1.DataLayer; @@ -40,6 +42,9 @@ namespace Tsi1.Api services.AddScoped<IUserService, UserService>(); services.AddScoped<IUserTypeService, UserTypeService>(); services.AddScoped<ICourseService, CourseService>(); + services.AddScoped<IForumService, ForumService>(); + services.AddScoped<IPostService, PostService>(); + services.AddScoped<IPostMessageService, PostMessageService>(); services.AddCors(); @@ -94,6 +99,14 @@ namespace Tsi1.Api {securityScheme, new string[] { }} }); }); + + // Auto Mapper Configurations + var mappingConfig = new MapperConfiguration(mc => { + mc.AddProfile(new MappingProfile()); + }); + + IMapper mapper = mappingConfig.CreateMapper(); + services.AddSingleton(mapper); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..2756562ff74849602f0f89d682c40384ea6d219f --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +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/ForumPreviewDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumPreviewDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..efe56b67319500b2cc0014de56d445304fe488fc --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumPreviewDto.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class ForumPreviewDto + { + public int Id { get; set; } + + public string Name { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostCreateDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..91eae2bf160faca45e869a0f03fb101e337fe85f --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostCreateDto.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json.Serialization; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class PostCreateDto + { + public string Title { get; set; } + + public int ForumId { get; set; } + + [JsonIgnore] + public int UserId { get; set; } + + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostMessageCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostMessageCreateDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..84900b4981cce5bfc66b8608f8b69898b539636a --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostMessageCreateDto.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json.Serialization; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class PostMessageCreateDto + { + public string Content { get; set; } + + [JsonIgnore] + public int UserId { get; set; } + + public int PostId { get; set; } + + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostMessagePreviewDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostMessagePreviewDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..cad57d7938a6e616a89e7d82e5a9d85909364296 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostMessagePreviewDto.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class PostMessagePreviewDto + { + public int Id { get; set; } + + public string Content { get; set; } + + public DateTime Date { get; set; } + + public int UserId { get; set; } + + public int PostId { get; set; } + + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostPreviewDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostPreviewDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..526ca193b0a22f3474086050ffa6c428a4035f46 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostPreviewDto.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class PostPreviewDto + { + public int Id { get; set; } + + public string Title { get; set; } + + public DateTime Date { get; set; } + + public int ForumId { get; set; } + + public int UserId { get; set; } + + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs index e36e8f1980228f519813ae1e19ef6452e8a0a365..31f2b3b0c045864ad893ff0566cf445e4beea5ac 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs @@ -9,5 +9,9 @@ namespace Tsi1.BusinessLayer.Helpers public const string UserDoesNotExist = "El usuario '{0}' no existe"; public const string IncorrectPassword = "Contraseña incorrecta"; public const string UserTypeDoesNotExist = "El tipo de usuario con id '{0}' no existe"; + + public const string ForumDoesNotExist = "El foro con id '{0}' no existe"; + public const string PostDoesNotExist = "El post con id '{0}' no existe"; + public const string PostMessageDoesNotExist = "El mensage con id '{0}' no existe"; } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs new file mode 100644 index 0000000000000000000000000000000000000000..95ed2d6e8f2f1d2e382d4b27728a71c05f72d58a --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs @@ -0,0 +1,30 @@ +using AutoMapper; +using System; +using System.Collections.Generic; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.DataLayer.Entities; + +namespace Tsi1.BusinessLayer.Helpers +{ + public class MappingProfile : Profile + { + public MappingProfile() + { + CreateMap<Forum, ForumCreateDto>(); + CreateMap<Forum, ForumPreviewDto>(); + CreateMap<Post, PostCreateDto>(); + CreateMap<Post, PostPreviewDto>(); + CreateMap<PostMessage, PostMessageCreateDto>(); + CreateMap<PostMessage, PostMessagePreviewDto>(); + + CreateMap<ForumCreateDto, Forum>(); + CreateMap<ForumPreviewDto, Forum>(); + CreateMap<PostCreateDto, Post>(); + CreateMap<PostPreviewDto, Post>(); + CreateMap<PostMessageCreateDto, PostMessage>(); + CreateMap<PostMessagePreviewDto, PostMessage>(); + } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs new file mode 100644 index 0000000000000000000000000000000000000000..254f08f137c110c9c6e6cb8378a0d4432fc0f240 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.DataLayer.Entities; + +namespace Tsi1.BusinessLayer.Interfaces +{ + public interface IForumService + { + Task<ServiceResult<List<ForumPreviewDto>>> GetForums(int courseId); + + Task<ServiceResult<Forum>> Create(ForumCreateDto newForum); + + Task<ServiceResult<Forum>> Delete(int forumId); + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IPostMessageService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IPostMessageService.cs new file mode 100644 index 0000000000000000000000000000000000000000..a1b34f403dc64bc82c1609eaf85f4a7656640308 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IPostMessageService.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.DataLayer.Entities; + +namespace Tsi1.BusinessLayer.Interfaces +{ + public interface IPostMessageService + { + Task<ServiceResult<List<PostMessagePreviewDto>>> GetPostMessages(int postId); + + Task<ServiceResult<PostMessage>> Create(PostMessageCreateDto newPostMessage); + + Task<ServiceResult<PostMessage>> Delete(int postMessageId); + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IPostService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IPostService.cs new file mode 100644 index 0000000000000000000000000000000000000000..40dbc56c173fcd990aa3c43ae8c6c5d8dac8d5ea --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IPostService.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.DataLayer.Entities; + +namespace Tsi1.BusinessLayer.Interfaces +{ + public interface IPostService + { + Task<ServiceResult<List<PostPreviewDto>>> GetPosts(int forumId); + + Task<ServiceResult<Post>> Create(PostCreateDto newPost); + + Task<ServiceResult<Post>> Delete(int postId); + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs new file mode 100644 index 0000000000000000000000000000000000000000..e17d9c881b7de8040e53d692ac4615f877f650f2 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs @@ -0,0 +1,77 @@ +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 ForumService : IForumService + { + private readonly Tsi1Context _context; + + private readonly IMapper _mapper; + + public ForumService(Tsi1Context context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task<ServiceResult<Forum>> Create(ForumCreateDto newForum) + { + var result = new ServiceResult<Forum>(); + + var forum = _mapper.Map<Forum>(newForum); + + _context.Forums.Add(forum); + await _context.SaveChangesAsync(); + + result.Data = forum; + + return result; + } + + public async Task<ServiceResult<Forum>> Delete(int forumId) + { + var result = new ServiceResult<Forum>(); + + var forum = await _context.Forums.FirstOrDefaultAsync(x => x.Id == forumId); + + if (forum == null) + { + result.HasError = true; + result.Message = string.Format(ErrorMessages.ForumDoesNotExist, forumId); + return result; + } + + _context.Forums.Remove(forum); + + await _context.SaveChangesAsync(); + + return result; + } + + public async Task<ServiceResult<List<ForumPreviewDto>>> GetForums(int courseId) + { + var result = new ServiceResult<List<ForumPreviewDto>>(); + + var forums = await _context.Forums + .Where(x => x.CourseId == courseId) + .ToListAsync(); + + var forumDtos = _mapper.Map<List<ForumPreviewDto>>(forums); + + result.Data = forumDtos; + + return result; + } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/PostMessageService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/PostMessageService.cs new file mode 100644 index 0000000000000000000000000000000000000000..067a3317b0b92812470a91b85d613ef5266e440a --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/PostMessageService.cs @@ -0,0 +1,79 @@ +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 PostMessageService : IPostMessageService + { + private readonly Tsi1Context _context; + + private readonly IMapper _mapper; + + public PostMessageService(Tsi1Context context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task<ServiceResult<PostMessage>> Create(PostMessageCreateDto newPostMessage) + { + var result = new ServiceResult<PostMessage>(); + + var postMessage = _mapper.Map<PostMessage>(newPostMessage); + + postMessage.Date = DateTime.Now; + + _context.PostMessages.Add(postMessage); + await _context.SaveChangesAsync(); + + result.Data = postMessage; + + return result; + } + + public async Task<ServiceResult<PostMessage>> Delete(int postMessageId) + { + var result = new ServiceResult<PostMessage>(); + + var postMessage = await _context.PostMessages.FirstOrDefaultAsync(x => x.Id == postMessageId); + + if (postMessage == null) + { + result.HasError = true; + result.Message = string.Format(ErrorMessages.PostMessageDoesNotExist, postMessageId); + return result; + } + + _context.PostMessages.Remove(postMessage); + + await _context.SaveChangesAsync(); + + return result; + } + + public async Task<ServiceResult<List<PostMessagePreviewDto>>> GetPostMessages(int postId) + { + var result = new ServiceResult<List<PostMessagePreviewDto>>(); + + var postMessages = await _context.PostMessages + .Where(x => x.PostId == postId) + .ToListAsync(); + + var postMessageDtos = _mapper.Map<List<PostMessagePreviewDto>>(postMessages); + + result.Data = postMessageDtos; + + return result; + } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/PostService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/PostService.cs new file mode 100644 index 0000000000000000000000000000000000000000..0d625f4d02207dfae95d3c44aac8555516f83b40 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/PostService.cs @@ -0,0 +1,79 @@ +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 PostService : IPostService + { + private readonly Tsi1Context _context; + + private readonly IMapper _mapper; + + public PostService(Tsi1Context context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task<ServiceResult<Post>> Create(PostCreateDto newPost) + { + var result = new ServiceResult<Post>(); + + var post = _mapper.Map<Post>(newPost); + + post.Date = DateTime.Now; + + _context.Posts.Add(post); + await _context.SaveChangesAsync(); + + result.Data = post; + + return result; + } + + public async Task<ServiceResult<Post>> Delete(int postId) + { + var result = new ServiceResult<Post>(); + + var post = await _context.Posts.FirstOrDefaultAsync(x => x.Id == postId); + + if (post == null) + { + result.HasError = true; + result.Message = string.Format(ErrorMessages.PostDoesNotExist, postId); + return result; + } + + _context.Posts.Remove(post); + + await _context.SaveChangesAsync(); + + return result; + } + + public async Task<ServiceResult<List<PostPreviewDto>>> GetPosts(int forumId) + { + var result = new ServiceResult<List<PostPreviewDto>>(); + + var posts = await _context.Posts + .Where(x => x.ForumId == forumId) + .ToListAsync(); + + var postDtos = _mapper.Map<List<PostPreviewDto>>(posts); + + result.Data = postDtos; + + return result; + } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Tsi1.BusinessLayer.csproj b/Tsi1.Api/Tsi1.BusinessLayer/Tsi1.BusinessLayer.csproj index 71bca384a32afadf9f0d5acbb9ad681f05bc0cfa..bf03c351a4e0b3702f4c73b7b986ddf95efa3291 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Tsi1.BusinessLayer.csproj +++ b/Tsi1.Api/Tsi1.BusinessLayer/Tsi1.BusinessLayer.csproj @@ -4,6 +4,11 @@ <TargetFramework>netcoreapp3.1</TargetFramework> </PropertyGroup> + <ItemGroup> + <PackageReference Include="AutoMapper" Version="10.1.1" /> + <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.0" /> + </ItemGroup> + <ItemGroup> <ProjectReference Include="..\Tsi1.DataLayer\Tsi1.DataLayer.csproj" /> </ItemGroup> diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs index c884a8829e830ad5a51d858d4da3300288d039cf..c2ee29e9f389e639bb6e0602e86689d371eba172 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs @@ -10,6 +10,7 @@ namespace Tsi1.DataLayer.Entities { StudentCourses = new HashSet<StudentCourse>(); ProfessorCourses = new HashSet<ProfessorCourse>(); + Forums = new HashSet<Forum>(); } public int Id { get; set; } @@ -17,5 +18,6 @@ namespace Tsi1.DataLayer.Entities public ICollection<StudentCourse> StudentCourses { get; set; } public ICollection<ProfessorCourse> ProfessorCourses { get; set; } + public ICollection<Forum> Forums { get; set; } } } diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs new file mode 100644 index 0000000000000000000000000000000000000000..8c362031bac40111b3975336e3ead073e736c506 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.DataLayer.Entities +{ + public class Forum + { + public Forum() + { + Posts = new HashSet<Post>(); + } + + public int Id { get; set; } + + public string Name { get; set; } + + public int CourseId { get; set; } + + public Course Course { get; set; } + + public ICollection<Post> Posts { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Post.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Post.cs new file mode 100644 index 0000000000000000000000000000000000000000..af9cf84e9998163e934a6ccfbef44e804680cc99 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Post.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.DataLayer.Entities +{ + public class Post + { + public Post() + { + PostMessages = new HashSet<PostMessage>(); + } + + public int Id { get; set; } + + public string Title { get; set; } + + public DateTime Date { get; set; } + + public int ForumId { get; set; } + + public Forum Forum { get; set; } + + public int UserId { get; set; } + + public User User { get; set; } + + public ICollection<PostMessage> PostMessages { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/PostMessage.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/PostMessage.cs new file mode 100644 index 0000000000000000000000000000000000000000..0e73c2ab6ea02ae3122df9a739f404022360cc2b --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/PostMessage.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.DataLayer.Entities +{ + public class PostMessage + { + public int Id { get; set; } + + public string Content { get; set; } + + public DateTime Date { get; set; } + + public int UserId { get; set; } + + public User User { get; set; } + + public int PostId { get; set; } + + public Post Post { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/User.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/User.cs index 637f94585126ec278d5f377993df55565e53e72c..22d5a1802400aa0b6fd99fa74d86842ea22fc3c3 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Entities/User.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/User.cs @@ -19,5 +19,8 @@ namespace Tsi1.DataLayer.Entities public UserType UserType { get; set; } public Student Student { get; set; } public Professor Professor { get; set; } + + public ICollection<Post> Posts { get; set; } + public ICollection<PostMessage> PostMessages { get; set; } } } diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs new file mode 100644 index 0000000000000000000000000000000000000000..0007d57ee4625c7756efa828488bb9034a6fb2bc --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs @@ -0,0 +1,30 @@ +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 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/PostConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/PostConfiguration.cs new file mode 100644 index 0000000000000000000000000000000000000000..6635726cf454e1d916ff57627c04e9e90927f73e --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/PostConfiguration.cs @@ -0,0 +1,34 @@ +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 PostConfiguration : IEntityTypeConfiguration<Post> + { + public void Configure(EntityTypeBuilder<Post> builder) + { + builder.HasKey(x => x.Id); + + builder.HasIndex(x => new { x.ForumId, x.Title }) + .IsUnique(); + + builder.Property(x => x.Title) + .IsRequired() + .HasColumnType("character varying(100)"); + + builder.HasOne(x => x.User) + .WithMany(x => x.Posts) + .HasForeignKey(x => x.UserId); + + builder.HasOne(x => x.Forum) + .WithMany(x => x.Posts) + .HasForeignKey(x => x.ForumId); + + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/PostMessageConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/PostMessageConfiguration.cs new file mode 100644 index 0000000000000000000000000000000000000000..b44d7303e33fa3675f014d87b729de2ee8a28fbf --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/PostMessageConfiguration.cs @@ -0,0 +1,31 @@ +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 PostMessageConfiguration : IEntityTypeConfiguration<PostMessage> + { + public void Configure(EntityTypeBuilder<PostMessage> builder) + { + builder.HasKey(x => x.Id); + + builder.Property(x => x.Content) + .IsRequired() + .HasColumnType("character varying(10485760)"); + + builder.HasOne(x => x.User) + .WithMany(x => x.PostMessages) + .HasForeignKey(x => x.UserId); + + builder.HasOne(x => x.Post) + .WithMany(x => x.PostMessages) + .HasForeignKey(x => x.PostId); + + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201017193719_add-forum-post-postmessage.Designer.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201017193719_add-forum-post-postmessage.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..4e0b7a47b80c66d1a28a19d96e120d66c54c5a81 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201017193719_add-forum-post-postmessage.Designer.cs @@ -0,0 +1,354 @@ +// <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("20201017193719_add-forum-post-postmessage")] + partial class addforumpostpostmessage + { + 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.Course", 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("Courses"); + }); + + 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.HasKey("Id"); + + b.HasIndex("CourseId", "Name") + .IsUnique(); + + b.ToTable("Forums"); + }); + + 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.HasKey("Id"); + + b.HasIndex("IdentityCard") + .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.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.HasKey("Id"); + + b.HasIndex("IdentityCard") + .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.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>("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("UserTypeId"); + + b.HasIndex("Username") + .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.Forum", b => + { + b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") + .WithMany("Forums") + .HasForeignKey("CourseId") + .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.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.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.UserType", "UserType") + .WithMany() + .HasForeignKey("UserTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201017193719_add-forum-post-postmessage.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201017193719_add-forum-post-postmessage.cs new file mode 100644 index 0000000000000000000000000000000000000000..768e30710c3fbfaa2d7b97cea0373c5d15a1b5bd --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201017193719_add-forum-post-postmessage.cs @@ -0,0 +1,127 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace Tsi1.DataLayer.Migrations +{ + public partial class addforumpostpostmessage : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Forums", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column<string>(type: "character varying(50)", nullable: false), + CourseId = table.Column<int>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Forums", x => x.Id); + table.ForeignKey( + name: "FK_Forums_Courses_CourseId", + column: x => x.CourseId, + principalTable: "Courses", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Posts", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Title = table.Column<string>(type: "character varying(100)", nullable: false), + Date = table.Column<DateTime>(nullable: false), + ForumId = table.Column<int>(nullable: false), + UserId = table.Column<int>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Posts", x => x.Id); + table.ForeignKey( + name: "FK_Posts_Forums_ForumId", + column: x => x.ForumId, + principalTable: "Forums", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Posts_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PostMessages", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Content = table.Column<string>(type: "character varying(10485760)", nullable: false), + Date = table.Column<DateTime>(nullable: false), + UserId = table.Column<int>(nullable: false), + PostId = table.Column<int>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PostMessages", x => x.Id); + table.ForeignKey( + name: "FK_PostMessages_Posts_PostId", + column: x => x.PostId, + principalTable: "Posts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_PostMessages_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Forums_CourseId_Name", + table: "Forums", + columns: new[] { "CourseId", "Name" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_PostMessages_PostId", + table: "PostMessages", + column: "PostId"); + + migrationBuilder.CreateIndex( + name: "IX_PostMessages_UserId", + table: "PostMessages", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_Posts_UserId", + table: "Posts", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_Posts_ForumId_Title", + table: "Posts", + columns: new[] { "ForumId", "Title" }, + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "PostMessages"); + + migrationBuilder.DropTable( + name: "Posts"); + + migrationBuilder.DropTable( + name: "Forums"); + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs index ce5698a5c0c92dd12caec2c8cf6bd1e23ed34368..3cbd29d3c18fa4564c466da2e18055065ebb6454 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs @@ -38,6 +38,87 @@ namespace Tsi1.DataLayer.Migrations b.ToTable("Courses"); }); + 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.HasKey("Id"); + + b.HasIndex("CourseId", "Name") + .IsUnique(); + + b.ToTable("Forums"); + }); + + 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") @@ -180,6 +261,45 @@ namespace Tsi1.DataLayer.Migrations b.ToTable("UserTypes"); }); + 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.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.ProfessorCourse", b => { b.HasOne("Tsi1.DataLayer.Entities.Course", "Course") diff --git a/Tsi1.Api/Tsi1.DataLayer/Tsi1.DataLayer.csproj b/Tsi1.Api/Tsi1.DataLayer/Tsi1.DataLayer.csproj index 5b5d0ce158fa6a261517baa9e4efd29e61dd2275..c339529345145ef37fcd12c8db20f2b5385c6bfd 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Tsi1.DataLayer.csproj +++ b/Tsi1.Api/Tsi1.DataLayer/Tsi1.DataLayer.csproj @@ -4,6 +4,13 @@ <TargetFramework>netcoreapp3.1</TargetFramework> </PropertyGroup> + <ItemGroup> + <Compile Remove="Migrations\20201017191517_add-forum-post-postmessage.cs" /> + <Compile Remove="Migrations\20201017191517_add-forum-post-postmessage.Designer.cs" /> + <Compile Remove="Migrations\20201017193319_add-forum-post-postmessage.cs" /> + <Compile Remove="Migrations\20201017193319_add-forum-post-postmessage.Designer.cs" /> + </ItemGroup> + <ItemGroup> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.4"> <PrivateAssets>all</PrivateAssets> diff --git a/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs b/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs index 632d64b29f9a63df47bea3b98e4a4edfd79ddbf4..578163242e61b037f2e80b869c0f2d5af8a4eb3c 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs @@ -16,6 +16,10 @@ namespace Tsi1.DataLayer public DbSet<Professor> Professors { get; set; } public DbSet<ProfessorCourse> ProfessorCourses { get; set; } public DbSet<Course> Courses { get; set; } + public DbSet<Forum> Forums { get; set; } + public DbSet<Post> Posts { get; set; } + public DbSet<PostMessage> PostMessages { get; set; } + public Tsi1Context(DbContextOptions options) : base(options) { } @@ -28,6 +32,9 @@ namespace Tsi1.DataLayer modelBuilder.ApplyConfiguration(new ProfessorConfiguration()); modelBuilder.ApplyConfiguration(new ProfessorCourseConfiguration()); modelBuilder.ApplyConfiguration(new CourseConfiguration()); + modelBuilder.ApplyConfiguration(new ForumConfiguration()); + modelBuilder.ApplyConfiguration(new PostConfiguration()); + modelBuilder.ApplyConfiguration(new PostMessageConfiguration()); } } }