diff --git a/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs b/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs new file mode 100644 index 0000000000000000000000000000000000000000..3e8575cc042c03c47236e69f02a24c9b39011b68 --- /dev/null +++ b/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +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; + } + } +} diff --git a/Tsi1.Api/Tsi1.Api/Startup.cs b/Tsi1.Api/Tsi1.Api/Startup.cs index 8dd2b590986be674b348bbee1eeefc22d26c280b..75f0c2ee47cd0d3547f62e94e29bbf3aaa31c62e 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,7 @@ namespace Tsi1.Api services.AddScoped<IUserService, UserService>(); services.AddScoped<IUserTypeService, UserTypeService>(); services.AddScoped<ICourseService, CourseService>(); + services.AddScoped<IForumService, ForumService>(); services.AddCors(); @@ -94,6 +97,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..f9506ddd0750378c205e74dd87db361a93b618fe --- /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 +{ + 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..ae1ca4b9cdcb312a2f2c4fbe5c1610568374be1f --- /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 +{ + class ForumPreviewDto + { + 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 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..1343433604817d83c0fea7a340789d7a34c66e70 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs @@ -0,0 +1,21 @@ +using AutoMapper; +using System; +using System.Collections.Generic; +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<ForumCreateDto, Forum>(); + CreateMap<ForumPreviewDto, Forum>(); + } + } +} 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/IPostService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IPostService.cs new file mode 100644 index 0000000000000000000000000000000000000000..6c31e433187592fbd017feccc0bbf308bd0251d3 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IPostService.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Interfaces +{ + interface IPostService + { + } +} 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.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()); } } }