From 0c4190252d13954ced288c4491dc72f7284a65c8 Mon Sep 17 00:00:00 2001 From: esantangelo <enzo020895@gmail.com> Date: Tue, 20 Oct 2020 21:59:26 -0300 Subject: [PATCH] agregado- subscripcion a Foro- envio de mail creaciob de post --- .../Tsi1.Api/Controllers/ForumController.cs | 21 +- .../Tsi1.Api/Controllers/PostController.cs | 14 +- Tsi1.Api/Tsi1.Api/Startup.cs | 5 +- Tsi1.Api/Tsi1.Api/appsettings.json | 7 + .../Helpers/ErrorMessages.cs | 4 + .../Helpers/MailSettings.cs | 19 + .../Interfaces/IEmailService.cs | 18 + .../Interfaces/IForumService.cs | 4 + .../Interfaces/IUserService.cs | 1 + .../Services/EmailService.cs | 94 +++++ .../Services/ForumService.cs | 41 ++ .../Tsi1.BusinessLayer.csproj | 2 + Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs | 2 + Tsi1.Api/Tsi1.DataLayer/Entities/ForumUser.cs | 15 + Tsi1.Api/Tsi1.DataLayer/Entities/User.cs | 8 + .../ForumUserConfiguration.cs | 25 ++ ...0233929_add-ForumUser-relation.Designer.cs | 384 ++++++++++++++++++ .../20201020233929_add-ForumUser-relation.cs | 45 ++ .../Migrations/Tsi1ContextModelSnapshot.cs | 30 ++ Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs | 2 + 20 files changed, 737 insertions(+), 4 deletions(-) create mode 100644 Tsi1.Api/Tsi1.BusinessLayer/Helpers/MailSettings.cs create mode 100644 Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IEmailService.cs create mode 100644 Tsi1.Api/Tsi1.BusinessLayer/Services/EmailService.cs create mode 100644 Tsi1.Api/Tsi1.DataLayer/Entities/ForumUser.cs create mode 100644 Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumUserConfiguration.cs create mode 100644 Tsi1.Api/Tsi1.DataLayer/Migrations/20201020233929_add-ForumUser-relation.Designer.cs create mode 100644 Tsi1.Api/Tsi1.DataLayer/Migrations/20201020233929_add-ForumUser-relation.cs diff --git a/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs b/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs index c0e99fb..a34cad3 100644 --- a/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs +++ b/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs @@ -36,7 +36,7 @@ namespace Tsi1.Api.Controllers return Ok(result.Data); } - [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] + [Authorize(UserTypes.Professor)] [HttpPost("Create")] public async Task<IActionResult> Create(ForumCreateDto newForum) { @@ -50,7 +50,7 @@ namespace Tsi1.Api.Controllers return Ok(); } - [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] + [Authorize(UserTypes.Professor)] [HttpDelete("Delete/{forumId}")] public async Task<IActionResult> Delete(int forumId) { @@ -63,5 +63,22 @@ namespace Tsi1.Api.Controllers return Ok(); } + + [Authorize(Roles = UserTypes.Student)] + [HttpGet("Subscribe/{forumId}")] + public async Task<IActionResult> Subscribe(int forumId) + { + var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value); + + var result = await _forumService.Subscribe(forumId, userId); + + 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 index eb1c19e..7c64c6c 100644 --- a/Tsi1.Api/Tsi1.Api/Controllers/PostController.cs +++ b/Tsi1.Api/Tsi1.Api/Controllers/PostController.cs @@ -17,11 +17,19 @@ namespace Tsi1.Api.Controllers { private readonly IPostService _postService; - public PostController(IPostService postService) + private readonly IForumService _forumService; + + private readonly IEmailService _emailService; + + public PostController(IPostService postService, IForumService forumService, + IEmailService emailService) { _postService = postService; + _forumService = forumService; + _emailService = emailService; } + [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] [HttpGet("GetPosts/{forumId}")] public async Task<IActionResult> GetPosts(int forumId) @@ -51,6 +59,10 @@ namespace Tsi1.Api.Controllers return BadRequest(result.Message); } + var userEmails = await _forumService.GetSubscribedUsers(newPost.ForumId); + + await _emailService.NotifyNewPostOrMessage(newPost, userEmails.Data); + return Ok(); } diff --git a/Tsi1.Api/Tsi1.Api/Startup.cs b/Tsi1.Api/Tsi1.Api/Startup.cs index c6a4f5f..c2039f8 100644 --- a/Tsi1.Api/Tsi1.Api/Startup.cs +++ b/Tsi1.Api/Tsi1.Api/Startup.cs @@ -55,7 +55,10 @@ namespace Tsi1.Api services.AddScoped<ICourseService, CourseService>(); services.AddScoped<IForumService, ForumService>(); services.AddScoped<IPostService, PostService>(); - services.AddScoped<IPostMessageService, PostMessageService>(); + services.AddScoped<IPostMessageService, PostMessageService>(); + + services.Configure<MailSettings>(Configuration.GetSection("MailSettings")); + services.AddScoped<IEmailService, EmailService>(); services.AddCors(); diff --git a/Tsi1.Api/Tsi1.Api/appsettings.json b/Tsi1.Api/Tsi1.Api/appsettings.json index 8de3212..e637ca6 100644 --- a/Tsi1.Api/Tsi1.Api/appsettings.json +++ b/Tsi1.Api/Tsi1.Api/appsettings.json @@ -14,6 +14,13 @@ "accessTokenExpiration": 20, "refreshTokenExpiration": 60 }, + "MailSettings": { + "Mail": "tsi1.grupo2.2020@gmail.com", + "DisplayName": "tsi1 grupo 2 2020", + "Password": "VamoTSI.2020", + "Host": "smtp.gmail.com", + "Port": 587 + }, "Logging": { "LogLevel": { "Default": "Information", diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs index 31f2b3b..0dbeef4 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs @@ -13,5 +13,9 @@ namespace Tsi1.BusinessLayer.Helpers 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"; + + public const string CannotConnectToSmtpServer = "No se pudo conectar al servidor SMTP"; + public const string CannotAuthenticateToSmtpServer = "No se pudo autenticar en el servidor SMTP"; + public const string CannotSendEmail = "No se pudo mandar el mail con asunto {0}"; } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MailSettings.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MailSettings.cs new file mode 100644 index 0000000..c750038 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MailSettings.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Helpers +{ + public class MailSettings + { + public string Mail { get; set; } + + public string DisplayName { get; set; } + + public string Password { get; set; } + + public string Host { get; set; } + + public int Port { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IEmailService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IEmailService.cs new file mode 100644 index 0000000..4f68ea6 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IEmailService.cs @@ -0,0 +1,18 @@ +using MimeKit; +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 IEmailService + { + Task<ServiceResult<bool>> SendEmailAsync(MimeMessage message); + + Task<ServiceResult<bool>> NotifyNewPostOrMessage(PostCreateDto postCreateDto, List<string> users); + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs index 254f08f..12d9460 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs @@ -15,5 +15,9 @@ namespace Tsi1.BusinessLayer.Interfaces Task<ServiceResult<Forum>> Create(ForumCreateDto newForum); Task<ServiceResult<Forum>> Delete(int forumId); + + Task<ServiceResult<List<string>>> GetSubscribedUsers(int forumId); + + Task<ServiceResult<List<bool>>> Subscribe(int forumId, int userId); } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IUserService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IUserService.cs index fb5470f..6a5abda 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IUserService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IUserService.cs @@ -12,5 +12,6 @@ namespace Tsi1.BusinessLayer.Interfaces { Task<ServiceResult<User>> Authenticate(string username, string password); Task<ServiceResult<User>> Create(UserRegisterDto dto, string type); + } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/EmailService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/EmailService.cs new file mode 100644 index 0000000..fad2cf7 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/EmailService.cs @@ -0,0 +1,94 @@ +using MailKit; +using MailKit.Net.Smtp; +using MailKit.Security; +using Microsoft.Extensions.Options; +using MimeKit; +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.Entities; + +namespace Tsi1.BusinessLayer.Services +{ + public class EmailService : IEmailService + { + private readonly MailSettings _mailSettings; + + public EmailService(IOptions<MailSettings> mailSettings) + { + _mailSettings = mailSettings.Value; + } + + public async Task<ServiceResult<bool>> SendEmailAsync(MimeMessage message) + { + ServiceResult<bool> result = new ServiceResult<bool>(); + + message.Sender = MailboxAddress.Parse(_mailSettings.Mail); + + var client = new SmtpClient(); + client.CheckCertificateRevocation = false; + + try + { + await client.ConnectAsync(_mailSettings.Host, _mailSettings.Port, SecureSocketOptions.StartTls); + } + catch (Exception e) + { + result.HasError = true; + result.Message = ErrorMessages.CannotConnectToSmtpServer; + return result; + } + + try + { + await client.AuthenticateAsync(_mailSettings.Mail, _mailSettings.Password); + } + catch (Exception) + { + result.HasError = true; + result.Message = ErrorMessages.CannotAuthenticateToSmtpServer; + return result; + } + + try + { + await client.SendAsync(message); + } + catch (Exception) + { + result.HasError = true; + result.Message = string.Format(ErrorMessages.CannotSendEmail, message.Subject); + return result; + } + + await client.DisconnectAsync(true); + + return result; + } + + public async Task<ServiceResult<bool>> NotifyNewPostOrMessage(PostCreateDto postCreateDto, List<string> users) + { + var message = new MimeMessage(); + + foreach (var user in users) + { + message.To.Add(MailboxAddress.Parse(user)); + } + + message.Subject = $"Nuevo Post: {postCreateDto.Title}"; + message.Body = new TextPart("html") + { + Text = $"<p> Hay un nuevo post perteneciente al foro suscripto." + }; + + var result = await SendEmailAsync(message); + + return result; + } + + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs index e17d9c8..827cd38 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs @@ -1,5 +1,6 @@ using AutoMapper; using Microsoft.EntityFrameworkCore; +using Org.BouncyCastle.Math.EC.Rfc7748; using System; using System.Collections.Generic; using System.Linq; @@ -73,5 +74,45 @@ namespace Tsi1.BusinessLayer.Services return result; } + + public async Task<ServiceResult<List<string>>> GetSubscribedUsers(int forumId) + { + var result = new ServiceResult<List<string>>(); + + var userEmails = await _context.ForumUsers + .Where(x => x.ForumId == forumId) + .Select(x => x.User.Email) + .ToListAsync(); + + result.Data = userEmails; + + return result; + } + + public async Task<ServiceResult<List<bool>>> Subscribe(int forumId, int userId) + { + var result = new ServiceResult<List<bool>>(); + + 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; + } + + var forumUser = new ForumUser + { + ForumId = forumId, + UserId = userId, + }; + + _context.ForumUsers.Add(forumUser); + + await _context.SaveChangesAsync(); + + return result; + } } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Tsi1.BusinessLayer.csproj b/Tsi1.Api/Tsi1.BusinessLayer/Tsi1.BusinessLayer.csproj index bf03c35..a21bff7 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Tsi1.BusinessLayer.csproj +++ b/Tsi1.Api/Tsi1.BusinessLayer/Tsi1.BusinessLayer.csproj @@ -7,6 +7,8 @@ <ItemGroup> <PackageReference Include="AutoMapper" Version="10.1.1" /> <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.0" /> + <PackageReference Include="MailKit" Version="2.9.0" /> + <PackageReference Include="MimeKit" Version="2.9.2" /> </ItemGroup> <ItemGroup> diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs index 8c36203..197e1e0 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs @@ -9,6 +9,7 @@ namespace Tsi1.DataLayer.Entities public Forum() { Posts = new HashSet<Post>(); + ForumUsers = new HashSet<ForumUser>(); } public int Id { get; set; } @@ -20,5 +21,6 @@ namespace Tsi1.DataLayer.Entities public Course Course { get; set; } public ICollection<Post> Posts { get; set; } + public ICollection<ForumUser> ForumUsers { get; set; } } } diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/ForumUser.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/ForumUser.cs new file mode 100644 index 0000000..1559edb --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/ForumUser.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.DataLayer.Entities +{ + public class ForumUser + { + public int ForumId { get; set; } + public int UserId { get; set; } + + public Forum Forum { get; set; } + public User User { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/User.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/User.cs index 22d5a18..dd7e804 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Entities/User.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/User.cs @@ -6,6 +6,13 @@ namespace Tsi1.DataLayer.Entities { public class User { + public User() + { + Posts = new HashSet<Post>(); + PostMessages = new HashSet<PostMessage>(); + ForumUsers = new HashSet<ForumUser>(); + } + public int Id { get; set; } public int UserTypeId { get; set; } public int? StudentId { get; set; } @@ -22,5 +29,6 @@ namespace Tsi1.DataLayer.Entities public ICollection<Post> Posts { get; set; } public ICollection<PostMessage> PostMessages { get; set; } + public ICollection<ForumUser> ForumUsers { get; set; } } } diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumUserConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumUserConfiguration.cs new file mode 100644 index 0000000..e1baf07 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumUserConfiguration.cs @@ -0,0 +1,25 @@ +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 ForumUserConfiguration : IEntityTypeConfiguration<ForumUser> + { + public void Configure(EntityTypeBuilder<ForumUser> builder) + { + builder.HasKey(x => new { x.ForumId, x.UserId }); + + builder.HasOne(x => x.Forum) + .WithMany(x => x.ForumUsers) + .HasForeignKey(x => x.ForumId); + + builder.HasOne(x => x.User) + .WithMany(x => x.ForumUsers) + .HasForeignKey(x => x.UserId); + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201020233929_add-ForumUser-relation.Designer.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201020233929_add-ForumUser-relation.Designer.cs new file mode 100644 index 0000000..1043ddf --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201020233929_add-ForumUser-relation.Designer.cs @@ -0,0 +1,384 @@ +// <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("20201020233929_add-ForumUser-relation")] + partial class addForumUserrelation + { + 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.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.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.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.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/20201020233929_add-ForumUser-relation.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201020233929_add-ForumUser-relation.cs new file mode 100644 index 0000000..6774e6c --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201020233929_add-ForumUser-relation.cs @@ -0,0 +1,45 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Tsi1.DataLayer.Migrations +{ + public partial class addForumUserrelation : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ForumUsers", + columns: table => new + { + ForumId = table.Column<int>(nullable: false), + UserId = table.Column<int>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ForumUsers", x => new { x.ForumId, x.UserId }); + table.ForeignKey( + name: "FK_ForumUsers_Forums_ForumId", + column: x => x.ForumId, + principalTable: "Forums", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ForumUsers_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_ForumUsers_UserId", + table: "ForumUsers", + column: "UserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ForumUsers"); + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs index 3cbd29d..993f66e 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs @@ -60,6 +60,21 @@ namespace Tsi1.DataLayer.Migrations 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.Post", b => { b.Property<int>("Id") @@ -270,6 +285,21 @@ namespace Tsi1.DataLayer.Migrations .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") diff --git a/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs b/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs index 5781632..1ed9f61 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs +++ b/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs @@ -19,6 +19,7 @@ namespace Tsi1.DataLayer public DbSet<Forum> Forums { get; set; } public DbSet<Post> Posts { get; set; } public DbSet<PostMessage> PostMessages { get; set; } + public DbSet<ForumUser> ForumUsers { get; set; } public Tsi1Context(DbContextOptions options) : base(options) { } @@ -35,6 +36,7 @@ namespace Tsi1.DataLayer modelBuilder.ApplyConfiguration(new ForumConfiguration()); modelBuilder.ApplyConfiguration(new PostConfiguration()); modelBuilder.ApplyConfiguration(new PostMessageConfiguration()); + modelBuilder.ApplyConfiguration(new ForumUserConfiguration()); } } } -- GitLab