From fb886c5c3369c8debab9820f07612f5ccb90b528 Mon Sep 17 00:00:00 2001 From: YuukanOO Date: Fri, 11 Dec 2020 16:00:29 +0100 Subject: [PATCH] add user relation in link, comment and vote --- Application/AddLink/AddLinkCommandHandler.cs | 8 +- .../CommentLink/CommentLinkCommandHandler.cs | 6 +- Application/IExecutingUserProvider.cs | 12 + .../VoteForCommentCommandHandler.cs | 9 +- .../VoteForLink/VoteForLinkCommandHandler.cs | 9 +- Apps/Website/HttpExecutingUserProvider.cs | 25 ++ Apps/Website/Startup.cs | 1 + Domain/Comment.cs | 28 +- Domain/Link.cs | 34 +- Domain/Votable.cs | 43 ++ Domain/Vote.cs | 14 +- .../EntityTypes/CommentEntityType.cs | 5 +- Infrastructure/EntityTypes/LinkEntityType.cs | 5 +- .../20201211144029_AddCreatedBy.Designer.cs | 408 ++++++++++++++++++ .../Migrations/20201211144029_AddCreatedBy.cs | 178 ++++++++ .../Migrations/HNDbContextModelSnapshot.cs | 48 ++- 16 files changed, 774 insertions(+), 59 deletions(-) create mode 100644 Application/IExecutingUserProvider.cs create mode 100644 Apps/Website/HttpExecutingUserProvider.cs create mode 100644 Domain/Votable.cs create mode 100644 Infrastructure/Migrations/20201211144029_AddCreatedBy.Designer.cs create mode 100644 Infrastructure/Migrations/20201211144029_AddCreatedBy.cs diff --git a/Application/AddLink/AddLinkCommandHandler.cs b/Application/AddLink/AddLinkCommandHandler.cs index f0f3a31..5028da3 100644 --- a/Application/AddLink/AddLinkCommandHandler.cs +++ b/Application/AddLink/AddLinkCommandHandler.cs @@ -10,15 +10,17 @@ namespace HN.Application public class AddLinkCommandHandler : IRequestHandler { private readonly ILinkRepository _repository; + private readonly IExecutingUserProvider _executingUserProvider; - public AddLinkCommandHandler(ILinkRepository repository) + public AddLinkCommandHandler(ILinkRepository repository, IExecutingUserProvider executingUserProvider) { - this._repository = repository; + _repository = repository; + _executingUserProvider = executingUserProvider; } public async Task Handle(AddLinkCommand request, CancellationToken cancellationToken) { - var link = Link.FromUrl(request.Url); + var link = Link.FromUrl(_executingUserProvider.GetCurrentUserId(), request.Url); await this._repository.AddAsync(link); diff --git a/Application/CommentLink/CommentLinkCommandHandler.cs b/Application/CommentLink/CommentLinkCommandHandler.cs index fb455b5..6b3fe08 100644 --- a/Application/CommentLink/CommentLinkCommandHandler.cs +++ b/Application/CommentLink/CommentLinkCommandHandler.cs @@ -10,17 +10,19 @@ namespace HN.Application { private readonly ILinkRepository _linkRepository; private readonly ICommentRepository _commentRepository; + private readonly IExecutingUserProvider _executingUserProvider; - public CommentLinkCommandHandler(ILinkRepository linkRepository, ICommentRepository commentRepository) + public CommentLinkCommandHandler(ILinkRepository linkRepository, ICommentRepository commentRepository, IExecutingUserProvider executingUserProvider) { _linkRepository = linkRepository; _commentRepository = commentRepository; + _executingUserProvider = executingUserProvider; } public async Task Handle(CommentLinkCommand request, CancellationToken cancellationToken) { var link = await _linkRepository.GetByIdAsync(request.LinkId); - var comment = link.AddComment(request.Content); + var comment = link.AddComment(_executingUserProvider.GetCurrentUserId(), request.Content); await _commentRepository.AddAsync(comment); diff --git a/Application/IExecutingUserProvider.cs b/Application/IExecutingUserProvider.cs new file mode 100644 index 0000000..4c3cd48 --- /dev/null +++ b/Application/IExecutingUserProvider.cs @@ -0,0 +1,12 @@ +using System; + +namespace HN.Application +{ + /// + /// Permet de récupérer l'utilisateur courant effectuant une commande. + /// + public interface IExecutingUserProvider + { + Guid GetCurrentUserId(); + } +} \ No newline at end of file diff --git a/Application/VoteForComment/VoteForCommentCommandHandler.cs b/Application/VoteForComment/VoteForCommentCommandHandler.cs index 153ce76..804bc31 100644 --- a/Application/VoteForComment/VoteForCommentCommandHandler.cs +++ b/Application/VoteForComment/VoteForCommentCommandHandler.cs @@ -8,23 +8,26 @@ namespace HN.Application public sealed class VoteForCommentCommandHandler : IRequestHandler { private readonly ICommentRepository _commentRepository; + private readonly IExecutingUserProvider _executingUserProvider; - public VoteForCommentCommandHandler(ICommentRepository commentRepository) + public VoteForCommentCommandHandler(ICommentRepository commentRepository, IExecutingUserProvider executingUserProvider) { _commentRepository = commentRepository; + _executingUserProvider = executingUserProvider; } public async Task Handle(VoteForCommentCommand request, CancellationToken cancellationToken) { var comment = await _commentRepository.GetByIdAsync(request.CommentId); + var userId = _executingUserProvider.GetCurrentUserId(); switch (request.Type) { case VoteType.Up: - comment.Upvote(); + comment.Upvote(userId); break; case VoteType.Down: - comment.Downvote(); + comment.Downvote(userId); break; } diff --git a/Application/VoteForLink/VoteForLinkCommandHandler.cs b/Application/VoteForLink/VoteForLinkCommandHandler.cs index 5c1965c..263d861 100644 --- a/Application/VoteForLink/VoteForLinkCommandHandler.cs +++ b/Application/VoteForLink/VoteForLinkCommandHandler.cs @@ -8,23 +8,26 @@ namespace HN.Application public sealed class VoteForLinkCommandHandler : IRequestHandler { private readonly ILinkRepository _linkRepository; + private readonly IExecutingUserProvider _executingUserProvider; - public VoteForLinkCommandHandler(ILinkRepository linkRepository) + public VoteForLinkCommandHandler(ILinkRepository linkRepository, IExecutingUserProvider executingUserProvider) { _linkRepository = linkRepository; + _executingUserProvider = executingUserProvider; } public async Task Handle(VoteForLinkCommand request, CancellationToken cancellationToken) { var link = await _linkRepository.GetByIdAsync(request.LinkId); + var userId = _executingUserProvider.GetCurrentUserId(); switch (request.Type) { case VoteType.Up: - link.Upvote(); + link.Upvote(userId); break; case VoteType.Down: - link.Downvote(); + link.Downvote(userId); break; } diff --git a/Apps/Website/HttpExecutingUserProvider.cs b/Apps/Website/HttpExecutingUserProvider.cs new file mode 100644 index 0000000..7e8fc64 --- /dev/null +++ b/Apps/Website/HttpExecutingUserProvider.cs @@ -0,0 +1,25 @@ +using System; +using HN.Application; +using HN.Infrastructure; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; + +namespace Website +{ + public sealed class HttpExecutingUserProvider : IExecutingUserProvider + { + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly UserManager _userManager; + + public HttpExecutingUserProvider(IHttpContextAccessor httpContextAccessor, UserManager userManager) + { + _httpContextAccessor = httpContextAccessor; + _userManager = userManager; + } + + public Guid GetCurrentUserId() + { + return Guid.Parse(_userManager.GetUserId(_httpContextAccessor.HttpContext.User)); + } + } +} \ No newline at end of file diff --git a/Apps/Website/Startup.cs b/Apps/Website/Startup.cs index bab0ba6..3e6f979 100644 --- a/Apps/Website/Startup.cs +++ b/Apps/Website/Startup.cs @@ -30,6 +30,7 @@ namespace Website services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddMediatR(typeof(HN.Application.IHNContext)); // Permet d'avoir des routes en lowercase diff --git a/Domain/Comment.cs b/Domain/Comment.cs index 91c688e..2530d4a 100644 --- a/Domain/Comment.cs +++ b/Domain/Comment.cs @@ -1,34 +1,22 @@ using System; -using System.Collections.Generic; namespace HN.Domain { - public sealed class Comment + public sealed class Comment : Votable { - public Guid Id { get; private set; } - public Guid LinkId { get; private set; } - public string Content { get; private set; } - public DateTime CreatedAt { get; private set; } - private List _votes; - public IReadOnlyList Votes => _votes; + public Guid Id { get; } + public Guid LinkId { get; } + public string Content { get; } + public Guid CreatedBy { get; } + public DateTime CreatedAt { get; } - internal Comment(Guid linkId, string content) + internal Comment(Guid linkId, Guid createdBy, string content) : base() { Id = Guid.NewGuid(); LinkId = linkId; + CreatedBy = createdBy; Content = content; CreatedAt = DateTime.UtcNow; - _votes = new List(); - } - - public void Upvote() - { - _votes.Add(new Vote(VoteType.Up)); - } - - public void Downvote() - { - _votes.Add(new Vote(VoteType.Down)); } } } \ No newline at end of file diff --git a/Domain/Link.cs b/Domain/Link.cs index 363d111..8b36aee 100644 --- a/Domain/Link.cs +++ b/Domain/Link.cs @@ -1,42 +1,30 @@ using System; -using System.Collections.Generic; namespace HN.Domain { - public sealed class Link + public sealed class Link : Votable { public Guid Id { get; } public string Url { get; } public DateTime CreatedAt { get; } - private List _votes; - public IReadOnlyList Votes => _votes; + public Guid CreatedBy { get; } - private Link(string url) + private Link(Guid createdBy, string url) : base() { - this.Id = Guid.NewGuid(); - this.CreatedAt = DateTime.UtcNow; - this.Url = url; - this._votes = new List(); + Id = Guid.NewGuid(); + CreatedBy = createdBy; + CreatedAt = DateTime.UtcNow; + Url = url; } - public static Link FromUrl(string url) + public static Link FromUrl(Guid posterId, string url) { - return new Link(url); + return new Link(posterId, url); } - public void Upvote() + public Comment AddComment(Guid userId, string content) { - _votes.Add(new Vote(VoteType.Up)); - } - - public void Downvote() - { - _votes.Add(new Vote(VoteType.Down)); - } - - public Comment AddComment(string content) - { - return new Comment(Id, content); + return new Comment(Id, userId, content); } } } diff --git a/Domain/Votable.cs b/Domain/Votable.cs new file mode 100644 index 0000000..074e360 --- /dev/null +++ b/Domain/Votable.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace HN.Domain +{ + /// + /// Représente une entité sur laquelle on peut voter. + /// + public abstract class Votable + { + private List _votes; + public IReadOnlyList Votes => _votes; + + protected Votable() + { + _votes = new List(); + } + + public void Upvote(Guid userId) + { + UpsertUserVote(userId, VoteType.Up); + } + + public void Downvote(Guid userId) + { + UpsertUserVote(userId, VoteType.Down); + } + + private void UpsertUserVote(Guid userId, VoteType type) + { + var vote = _votes.SingleOrDefault(v => v.CreatedBy == userId); + + if (vote == null) + { + _votes.Add(new Vote(userId, type)); + return; + } + + vote.HasType(type); + } + } +} \ No newline at end of file diff --git a/Domain/Vote.cs b/Domain/Vote.cs index ea28898..dc74f69 100644 --- a/Domain/Vote.cs +++ b/Domain/Vote.cs @@ -5,9 +5,21 @@ namespace HN.Domain public sealed class Vote { public VoteType Type { get; private set; } + public Guid CreatedBy { get; } public DateTime CreatedAt { get; private set; } - internal Vote(VoteType type) + internal Vote(Guid createdBy, VoteType type) + { + CreatedBy = createdBy; + Type = type; + CreatedAt = DateTime.UtcNow; + } + + /// + /// Change le type d'un vote + /// + /// + public void HasType(VoteType type) { Type = type; CreatedAt = DateTime.UtcNow; diff --git a/Infrastructure/EntityTypes/CommentEntityType.cs b/Infrastructure/EntityTypes/CommentEntityType.cs index b6b4a66..dffdd31 100644 --- a/Infrastructure/EntityTypes/CommentEntityType.cs +++ b/Infrastructure/EntityTypes/CommentEntityType.cs @@ -17,11 +17,14 @@ namespace HN.Infrastructure builder.Property(o => o.Content).IsRequired(); builder.Property(o => o.CreatedAt).IsRequired(); + builder.HasOne().WithMany().HasForeignKey(nameof(Comment.CreatedBy)).IsRequired(); + builder.OwnsMany(o => o.Votes, vote => { vote.ToTable("comment_votes"); vote.WithOwner().HasForeignKey("CommentId"); - vote.HasKey("CommentId"); + vote.HasKey("CommentId", nameof(Comment.CreatedBy)); + vote.HasOne().WithMany().HasForeignKey(nameof(Vote.CreatedBy)).IsRequired(); vote.Property(o => o.Type).IsRequired(); vote.Property(o => o.CreatedAt).IsRequired(); }); diff --git a/Infrastructure/EntityTypes/LinkEntityType.cs b/Infrastructure/EntityTypes/LinkEntityType.cs index ad688cc..5fdaa51 100644 --- a/Infrastructure/EntityTypes/LinkEntityType.cs +++ b/Infrastructure/EntityTypes/LinkEntityType.cs @@ -14,11 +14,14 @@ namespace HN.Infrastructure.EntityTypes builder.Property(o => o.CreatedAt).IsRequired(); builder.HasIndex(o => o.Url).IsUnique(); + builder.HasOne().WithMany().HasForeignKey(nameof(Link.CreatedBy)).IsRequired(); + builder.OwnsMany(o => o.Votes, vote => { vote.ToTable("link_votes"); vote.WithOwner().HasForeignKey("LinkId"); - vote.HasKey("LinkId"); + vote.HasKey("LinkId", nameof(Link.CreatedBy)); + vote.HasOne().WithMany().HasForeignKey(nameof(Vote.CreatedBy)).IsRequired(); vote.Property(o => o.Type).IsRequired(); vote.Property(o => o.CreatedAt).IsRequired(); }); diff --git a/Infrastructure/Migrations/20201211144029_AddCreatedBy.Designer.cs b/Infrastructure/Migrations/20201211144029_AddCreatedBy.Designer.cs new file mode 100644 index 0000000..6275b2c --- /dev/null +++ b/Infrastructure/Migrations/20201211144029_AddCreatedBy.Designer.cs @@ -0,0 +1,408 @@ +// +using System; +using HN.Infrastructure; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Infrastructure.Migrations +{ + [DbContext(typeof(HNDbContext))] + [Migration("20201211144029_AddCreatedBy")] + partial class AddCreatedBy + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "5.0.0"); + + modelBuilder.Entity("HN.Domain.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Content") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("LinkId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("LinkId"); + + b.ToTable("comments"); + }); + + modelBuilder.Entity("HN.Domain.Link", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasColumnType("TEXT"); + + b.Property("Url") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("Url") + .IsUnique(); + + b.ToTable("links"); + }); + + modelBuilder.Entity("HN.Infrastructure.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("HN.Infrastructure.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("HN.Domain.Comment", b => + { + b.HasOne("HN.Infrastructure.User", null) + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HN.Domain.Link", null) + .WithMany() + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsMany("HN.Domain.Vote", "Votes", b1 => + { + b1.Property("CommentId") + .HasColumnType("TEXT"); + + b1.Property("CreatedBy") + .HasColumnType("TEXT"); + + b1.Property("CreatedAt") + .HasColumnType("TEXT"); + + b1.Property("Type") + .HasColumnType("INTEGER"); + + b1.HasKey("CommentId", "CreatedBy"); + + b1.HasIndex("CreatedBy"); + + b1.ToTable("comment_votes"); + + b1.WithOwner() + .HasForeignKey("CommentId"); + + b1.HasOne("HN.Infrastructure.User", null) + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + b.Navigation("Votes"); + }); + + modelBuilder.Entity("HN.Domain.Link", b => + { + b.HasOne("HN.Infrastructure.User", null) + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsMany("HN.Domain.Vote", "Votes", b1 => + { + b1.Property("LinkId") + .HasColumnType("TEXT"); + + b1.Property("CreatedBy") + .HasColumnType("TEXT"); + + b1.Property("CreatedAt") + .HasColumnType("TEXT"); + + b1.Property("Type") + .HasColumnType("INTEGER"); + + b1.HasKey("LinkId", "CreatedBy"); + + b1.HasIndex("CreatedBy"); + + b1.ToTable("link_votes"); + + b1.HasOne("HN.Infrastructure.User", null) + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b1.WithOwner() + .HasForeignKey("LinkId"); + }); + + b.Navigation("Votes"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("HN.Infrastructure.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("HN.Infrastructure.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("HN.Infrastructure.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("HN.Infrastructure.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HN.Infrastructure.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("HN.Infrastructure.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Infrastructure/Migrations/20201211144029_AddCreatedBy.cs b/Infrastructure/Migrations/20201211144029_AddCreatedBy.cs new file mode 100644 index 0000000..97834e3 --- /dev/null +++ b/Infrastructure/Migrations/20201211144029_AddCreatedBy.cs @@ -0,0 +1,178 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Infrastructure.Migrations +{ + public partial class AddCreatedBy : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_link_votes", + table: "link_votes"); + + migrationBuilder.DropPrimaryKey( + name: "PK_comment_votes", + table: "comment_votes"); + + migrationBuilder.AddColumn( + name: "CreatedBy", + table: "links", + type: "TEXT", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); + + migrationBuilder.AddColumn( + name: "CreatedBy", + table: "link_votes", + type: "TEXT", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); + + migrationBuilder.AddColumn( + name: "CreatedBy", + table: "comments", + type: "TEXT", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); + + migrationBuilder.AddColumn( + name: "CreatedBy", + table: "comment_votes", + type: "TEXT", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); + + migrationBuilder.AddPrimaryKey( + name: "PK_link_votes", + table: "link_votes", + columns: new[] { "LinkId", "CreatedBy" }); + + migrationBuilder.AddPrimaryKey( + name: "PK_comment_votes", + table: "comment_votes", + columns: new[] { "CommentId", "CreatedBy" }); + + migrationBuilder.CreateIndex( + name: "IX_links_CreatedBy", + table: "links", + column: "CreatedBy"); + + migrationBuilder.CreateIndex( + name: "IX_link_votes_CreatedBy", + table: "link_votes", + column: "CreatedBy"); + + migrationBuilder.CreateIndex( + name: "IX_comments_CreatedBy", + table: "comments", + column: "CreatedBy"); + + migrationBuilder.CreateIndex( + name: "IX_comment_votes_CreatedBy", + table: "comment_votes", + column: "CreatedBy"); + + migrationBuilder.AddForeignKey( + name: "FK_comment_votes_AspNetUsers_CreatedBy", + table: "comment_votes", + column: "CreatedBy", + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_comments_AspNetUsers_CreatedBy", + table: "comments", + column: "CreatedBy", + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_link_votes_AspNetUsers_CreatedBy", + table: "link_votes", + column: "CreatedBy", + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_links_AspNetUsers_CreatedBy", + table: "links", + column: "CreatedBy", + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_comment_votes_AspNetUsers_CreatedBy", + table: "comment_votes"); + + migrationBuilder.DropForeignKey( + name: "FK_comments_AspNetUsers_CreatedBy", + table: "comments"); + + migrationBuilder.DropForeignKey( + name: "FK_link_votes_AspNetUsers_CreatedBy", + table: "link_votes"); + + migrationBuilder.DropForeignKey( + name: "FK_links_AspNetUsers_CreatedBy", + table: "links"); + + migrationBuilder.DropIndex( + name: "IX_links_CreatedBy", + table: "links"); + + migrationBuilder.DropPrimaryKey( + name: "PK_link_votes", + table: "link_votes"); + + migrationBuilder.DropIndex( + name: "IX_link_votes_CreatedBy", + table: "link_votes"); + + migrationBuilder.DropIndex( + name: "IX_comments_CreatedBy", + table: "comments"); + + migrationBuilder.DropPrimaryKey( + name: "PK_comment_votes", + table: "comment_votes"); + + migrationBuilder.DropIndex( + name: "IX_comment_votes_CreatedBy", + table: "comment_votes"); + + migrationBuilder.DropColumn( + name: "CreatedBy", + table: "links"); + + migrationBuilder.DropColumn( + name: "CreatedBy", + table: "link_votes"); + + migrationBuilder.DropColumn( + name: "CreatedBy", + table: "comments"); + + migrationBuilder.DropColumn( + name: "CreatedBy", + table: "comment_votes"); + + migrationBuilder.AddPrimaryKey( + name: "PK_link_votes", + table: "link_votes", + column: "LinkId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_comment_votes", + table: "comment_votes", + column: "CommentId"); + } + } +} diff --git a/Infrastructure/Migrations/HNDbContextModelSnapshot.cs b/Infrastructure/Migrations/HNDbContextModelSnapshot.cs index c2c1b4e..0ce4826 100644 --- a/Infrastructure/Migrations/HNDbContextModelSnapshot.cs +++ b/Infrastructure/Migrations/HNDbContextModelSnapshot.cs @@ -29,11 +29,16 @@ namespace Infrastructure.Migrations b.Property("CreatedAt") .HasColumnType("TEXT"); + b.Property("CreatedBy") + .HasColumnType("TEXT"); + b.Property("LinkId") .HasColumnType("TEXT"); b.HasKey("Id"); + b.HasIndex("CreatedBy"); + b.HasIndex("LinkId"); b.ToTable("comments"); @@ -48,6 +53,9 @@ namespace Infrastructure.Migrations b.Property("CreatedAt") .HasColumnType("TEXT"); + b.Property("CreatedBy") + .HasColumnType("TEXT"); + b.Property("Url") .IsRequired() .HasMaxLength(500) @@ -55,6 +63,8 @@ namespace Infrastructure.Migrations b.HasKey("Id"); + b.HasIndex("CreatedBy"); + b.HasIndex("Url") .IsUnique(); @@ -254,6 +264,12 @@ namespace Infrastructure.Migrations modelBuilder.Entity("HN.Domain.Comment", b => { + b.HasOne("HN.Infrastructure.User", null) + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + b.HasOne("HN.Domain.Link", null) .WithMany() .HasForeignKey("LinkId") @@ -265,18 +281,29 @@ namespace Infrastructure.Migrations b1.Property("CommentId") .HasColumnType("TEXT"); + b1.Property("CreatedBy") + .HasColumnType("TEXT"); + b1.Property("CreatedAt") .HasColumnType("TEXT"); b1.Property("Type") .HasColumnType("INTEGER"); - b1.HasKey("CommentId"); + b1.HasKey("CommentId", "CreatedBy"); + + b1.HasIndex("CreatedBy"); b1.ToTable("comment_votes"); b1.WithOwner() .HasForeignKey("CommentId"); + + b1.HasOne("HN.Infrastructure.User", null) + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); b.Navigation("Votes"); @@ -284,21 +311,38 @@ namespace Infrastructure.Migrations modelBuilder.Entity("HN.Domain.Link", b => { + b.HasOne("HN.Infrastructure.User", null) + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + b.OwnsMany("HN.Domain.Vote", "Votes", b1 => { b1.Property("LinkId") .HasColumnType("TEXT"); + b1.Property("CreatedBy") + .HasColumnType("TEXT"); + b1.Property("CreatedAt") .HasColumnType("TEXT"); b1.Property("Type") .HasColumnType("INTEGER"); - b1.HasKey("LinkId"); + b1.HasKey("LinkId", "CreatedBy"); + + b1.HasIndex("CreatedBy"); b1.ToTable("link_votes"); + b1.HasOne("HN.Infrastructure.User", null) + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + b1.WithOwner() .HasForeignKey("LinkId"); });