add-aspnet-identity (#26)
add exception filter when user not connected default to needing authentication and apply anonymous to some actions add user in get requests add user relation in link, comment and vote signup and in are ok now!
This commit is contained in:
parent
9c75758921
commit
3cd5133f66
@ -10,15 +10,17 @@ namespace HN.Application
|
|||||||
public class AddLinkCommandHandler : IRequestHandler<AddLinkCommand, Guid>
|
public class AddLinkCommandHandler : IRequestHandler<AddLinkCommand, Guid>
|
||||||
{
|
{
|
||||||
private readonly ILinkRepository _repository;
|
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<Guid> Handle(AddLinkCommand request, CancellationToken cancellationToken)
|
public async Task<Guid> Handle(AddLinkCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var link = Link.FromUrl(request.Url);
|
var link = Link.FromUrl(_executingUserProvider.GetCurrentUserId(), request.Url);
|
||||||
|
|
||||||
await this._repository.AddAsync(link);
|
await this._repository.AddAsync(link);
|
||||||
|
|
||||||
|
|||||||
@ -10,17 +10,19 @@ namespace HN.Application
|
|||||||
{
|
{
|
||||||
private readonly ILinkRepository _linkRepository;
|
private readonly ILinkRepository _linkRepository;
|
||||||
private readonly ICommentRepository _commentRepository;
|
private readonly ICommentRepository _commentRepository;
|
||||||
|
private readonly IExecutingUserProvider _executingUserProvider;
|
||||||
|
|
||||||
public CommentLinkCommandHandler(ILinkRepository linkRepository, ICommentRepository commentRepository)
|
public CommentLinkCommandHandler(ILinkRepository linkRepository, ICommentRepository commentRepository, IExecutingUserProvider executingUserProvider)
|
||||||
{
|
{
|
||||||
_linkRepository = linkRepository;
|
_linkRepository = linkRepository;
|
||||||
_commentRepository = commentRepository;
|
_commentRepository = commentRepository;
|
||||||
|
_executingUserProvider = executingUserProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Guid> Handle(CommentLinkCommand request, CancellationToken cancellationToken)
|
public async Task<Guid> Handle(CommentLinkCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var link = await _linkRepository.GetByIdAsync(request.LinkId);
|
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);
|
await _commentRepository.AddAsync(comment);
|
||||||
|
|
||||||
|
|||||||
@ -18,11 +18,13 @@ namespace HN.Application
|
|||||||
public Task<LinkDto> Handle(GetLinkQuery request, CancellationToken cancellationToken)
|
public Task<LinkDto> Handle(GetLinkQuery request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var result = from link in _context.Links
|
var result = from link in _context.Links
|
||||||
|
join user in _context.Users on link.CreatedBy equals user.Id
|
||||||
where link.Id == request.Id
|
where link.Id == request.Id
|
||||||
select new LinkDto
|
select new LinkDto
|
||||||
{
|
{
|
||||||
Id = link.Id,
|
Id = link.Id,
|
||||||
Url = link.Url,
|
Url = link.Url,
|
||||||
|
CreatedByName = user.UserName,
|
||||||
CreatedAt = link.CreatedAt,
|
CreatedAt = link.CreatedAt,
|
||||||
UpVotes = link.Votes.Count(v => v.Type == VoteType.Up),
|
UpVotes = link.Votes.Count(v => v.Type == VoteType.Up),
|
||||||
DownVotes = link.Votes.Count(v => v.Type == VoteType.Down)
|
DownVotes = link.Votes.Count(v => v.Type == VoteType.Down)
|
||||||
|
|||||||
12
Application/IExecutingUserProvider.cs
Normal file
12
Application/IExecutingUserProvider.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace HN.Application
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Permet de récupérer l'utilisateur courant effectuant une commande.
|
||||||
|
/// </summary>
|
||||||
|
public interface IExecutingUserProvider
|
||||||
|
{
|
||||||
|
Guid GetCurrentUserId();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
using System.Linq;
|
||||||
using HN.Domain;
|
using HN.Domain;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
@ -10,5 +11,6 @@ namespace HN.Application
|
|||||||
{
|
{
|
||||||
DbSet<Link> Links { get; }
|
DbSet<Link> Links { get; }
|
||||||
DbSet<Comment> Comments { get; }
|
DbSet<Comment> Comments { get; }
|
||||||
|
IQueryable<IUser> Users { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
Application/IUser.cs
Normal file
10
Application/IUser.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace HN.Application
|
||||||
|
{
|
||||||
|
public interface IUser
|
||||||
|
{
|
||||||
|
Guid Id { get; }
|
||||||
|
string UserName { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ namespace HN.Application
|
|||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
public string Url { get; set; }
|
public string Url { get; set; }
|
||||||
public DateTime CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public string CreatedByName { get; set; }
|
||||||
public int UpVotes { get; set; }
|
public int UpVotes { get; set; }
|
||||||
public int DownVotes { get; set; }
|
public int DownVotes { get; set; }
|
||||||
|
|
||||||
|
|||||||
@ -46,10 +46,12 @@ namespace HN.Application
|
|||||||
public Task<LinkDto[]> Handle(ListLinksQuery request, CancellationToken cancellationToken)
|
public Task<LinkDto[]> Handle(ListLinksQuery request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var links = from link in _context.Links
|
var links = from link in _context.Links
|
||||||
|
join user in _context.Users on link.CreatedBy equals user.Id
|
||||||
select new LinkDto
|
select new LinkDto
|
||||||
{
|
{
|
||||||
Id = link.Id,
|
Id = link.Id,
|
||||||
Url = link.Url,
|
Url = link.Url,
|
||||||
|
CreatedByName = user.UserName,
|
||||||
CreatedAt = link.CreatedAt,
|
CreatedAt = link.CreatedAt,
|
||||||
UpVotes = link.Votes.Count(v => v.Type == VoteType.Up),
|
UpVotes = link.Votes.Count(v => v.Type == VoteType.Up),
|
||||||
DownVotes = link.Votes.Count(v => v.Type == VoteType.Down)
|
DownVotes = link.Votes.Count(v => v.Type == VoteType.Down)
|
||||||
|
|||||||
@ -8,23 +8,26 @@ namespace HN.Application
|
|||||||
public sealed class VoteForCommentCommandHandler : IRequestHandler<VoteForCommentCommand>
|
public sealed class VoteForCommentCommandHandler : IRequestHandler<VoteForCommentCommand>
|
||||||
{
|
{
|
||||||
private readonly ICommentRepository _commentRepository;
|
private readonly ICommentRepository _commentRepository;
|
||||||
|
private readonly IExecutingUserProvider _executingUserProvider;
|
||||||
|
|
||||||
public VoteForCommentCommandHandler(ICommentRepository commentRepository)
|
public VoteForCommentCommandHandler(ICommentRepository commentRepository, IExecutingUserProvider executingUserProvider)
|
||||||
{
|
{
|
||||||
_commentRepository = commentRepository;
|
_commentRepository = commentRepository;
|
||||||
|
_executingUserProvider = executingUserProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Unit> Handle(VoteForCommentCommand request, CancellationToken cancellationToken)
|
public async Task<Unit> Handle(VoteForCommentCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var comment = await _commentRepository.GetByIdAsync(request.CommentId);
|
var comment = await _commentRepository.GetByIdAsync(request.CommentId);
|
||||||
|
var userId = _executingUserProvider.GetCurrentUserId();
|
||||||
|
|
||||||
switch (request.Type)
|
switch (request.Type)
|
||||||
{
|
{
|
||||||
case VoteType.Up:
|
case VoteType.Up:
|
||||||
comment.Upvote();
|
comment.Upvote(userId);
|
||||||
break;
|
break;
|
||||||
case VoteType.Down:
|
case VoteType.Down:
|
||||||
comment.Downvote();
|
comment.Downvote(userId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,23 +8,26 @@ namespace HN.Application
|
|||||||
public sealed class VoteForLinkCommandHandler : IRequestHandler<VoteForLinkCommand>
|
public sealed class VoteForLinkCommandHandler : IRequestHandler<VoteForLinkCommand>
|
||||||
{
|
{
|
||||||
private readonly ILinkRepository _linkRepository;
|
private readonly ILinkRepository _linkRepository;
|
||||||
|
private readonly IExecutingUserProvider _executingUserProvider;
|
||||||
|
|
||||||
public VoteForLinkCommandHandler(ILinkRepository linkRepository)
|
public VoteForLinkCommandHandler(ILinkRepository linkRepository, IExecutingUserProvider executingUserProvider)
|
||||||
{
|
{
|
||||||
_linkRepository = linkRepository;
|
_linkRepository = linkRepository;
|
||||||
|
_executingUserProvider = executingUserProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Unit> Handle(VoteForLinkCommand request, CancellationToken cancellationToken)
|
public async Task<Unit> Handle(VoteForLinkCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var link = await _linkRepository.GetByIdAsync(request.LinkId);
|
var link = await _linkRepository.GetByIdAsync(request.LinkId);
|
||||||
|
var userId = _executingUserProvider.GetCurrentUserId();
|
||||||
|
|
||||||
switch (request.Type)
|
switch (request.Type)
|
||||||
{
|
{
|
||||||
case VoteType.Up:
|
case VoteType.Up:
|
||||||
link.Upvote();
|
link.Upvote(userId);
|
||||||
break;
|
break;
|
||||||
case VoteType.Down:
|
case VoteType.Down:
|
||||||
link.Downvote();
|
link.Downvote(userId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
17
Apps/Website/Components/LoginViewComponent.cs
Normal file
17
Apps/Website/Components/LoginViewComponent.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Website.Components
|
||||||
|
{
|
||||||
|
public sealed class LoginViewComponent : ViewComponent
|
||||||
|
{
|
||||||
|
public IViewComponentResult Invoke()
|
||||||
|
{
|
||||||
|
if (User.Identity.IsAuthenticated)
|
||||||
|
{
|
||||||
|
return View("LoggedIn");
|
||||||
|
}
|
||||||
|
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
100
Apps/Website/Controllers/AccountsController.cs
Normal file
100
Apps/Website/Controllers/AccountsController.cs
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using HN.Infrastructure;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Website.Models;
|
||||||
|
|
||||||
|
namespace Website.Controllers
|
||||||
|
{
|
||||||
|
public sealed class AccountsController : BaseController
|
||||||
|
{
|
||||||
|
private readonly UserManager<User> _userManager;
|
||||||
|
private readonly SignInManager<User> _signInManager;
|
||||||
|
|
||||||
|
public AccountsController(UserManager<User> userManager, SignInManager<User> signInManager)
|
||||||
|
{
|
||||||
|
_userManager = userManager;
|
||||||
|
_signInManager = signInManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
public IActionResult Register()
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public async Task<IActionResult> Register(RegisterViewModel command)
|
||||||
|
{
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
{
|
||||||
|
return View(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = new User(command.Username);
|
||||||
|
var result = await _userManager.CreateAsync(user, command.Password);
|
||||||
|
|
||||||
|
if (!result.Succeeded)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(nameof(RegisterViewModel.Username), string.Join(", ", result.Errors.Select(e => e.Description)));
|
||||||
|
return View(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetFlash("Account created, you can now sign in!");
|
||||||
|
|
||||||
|
return RedirectToAction(nameof(Login));
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
public IActionResult Login()
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public async Task<IActionResult> Login(LoginViewModel command)
|
||||||
|
{
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = await _userManager.FindByNameAsync(command.Username);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(nameof(LoginViewModel.Username), "Could not verify user identity");
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await _signInManager.PasswordSignInAsync(user, command.Password, true, false);
|
||||||
|
|
||||||
|
if (!result.Succeeded)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(nameof(LoginViewModel.Username), "Could not verify user identity");
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
SetFlash("Successfuly connected!");
|
||||||
|
|
||||||
|
return RedirectToAction(nameof(LinksController.Index), "Links");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[ValidateAntiForgeryToken]
|
||||||
|
public async Task<IActionResult> Logout()
|
||||||
|
{
|
||||||
|
await _signInManager.SignOutAsync();
|
||||||
|
|
||||||
|
SetFlash("Successfuly disconnected!");
|
||||||
|
|
||||||
|
return RedirectToAction(nameof(Login));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,14 +1,12 @@
|
|||||||
using System;
|
using System.Diagnostics;
|
||||||
using System.Collections.Generic;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Website.Models;
|
using Website.Models;
|
||||||
|
|
||||||
namespace Website.Controllers
|
namespace Website.Controllers
|
||||||
{
|
{
|
||||||
|
[AllowAnonymous]
|
||||||
public class HomeController : Controller
|
public class HomeController : Controller
|
||||||
{
|
{
|
||||||
private readonly ILogger<HomeController> _logger;
|
private readonly ILogger<HomeController> _logger;
|
||||||
|
|||||||
@ -5,6 +5,7 @@ using System.Threading.Tasks;
|
|||||||
using System;
|
using System;
|
||||||
using HN.Domain;
|
using HN.Domain;
|
||||||
using Website.Models;
|
using Website.Models;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
namespace Website.Controllers
|
namespace Website.Controllers
|
||||||
{
|
{
|
||||||
@ -18,12 +19,14 @@ namespace Website.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
[AllowAnonymous]
|
||||||
public async Task<IActionResult> Index()
|
public async Task<IActionResult> Index()
|
||||||
{
|
{
|
||||||
return View(await _bus.Send(new ListLinksQuery()));
|
return View(await _bus.Send(new ListLinksQuery()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{controller}/{id:guid}")]
|
[HttpGet("{controller}/{id:guid}")]
|
||||||
|
[AllowAnonymous]
|
||||||
public async Task<IActionResult> Show(Guid id)
|
public async Task<IActionResult> Show(Guid id)
|
||||||
{
|
{
|
||||||
var link = await _bus.Send(new GetLinkQuery(id));
|
var link = await _bus.Send(new GetLinkQuery(id));
|
||||||
@ -31,11 +34,6 @@ namespace Website.Controllers
|
|||||||
return View(new ShowLinkViewModel(link, new CommentLinkCommand(id), comments));
|
return View(new ShowLinkViewModel(link, new CommentLinkCommand(id), comments));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IActionResult Create()
|
|
||||||
{
|
|
||||||
return View(new AddLinkCommand());
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost("{controller}/{id:guid}/vote")]
|
[HttpPost("{controller}/{id:guid}/vote")]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public async Task<IActionResult> Vote(Guid id, string url, VoteType type, string redirectTo)
|
public async Task<IActionResult> Vote(Guid id, string url, VoteType type, string redirectTo)
|
||||||
@ -46,8 +44,14 @@ namespace Website.Controllers
|
|||||||
return Redirect(redirectTo);
|
return Redirect(redirectTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IActionResult Create()
|
||||||
|
{
|
||||||
|
return View(new AddLinkCommand());
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
|
|
||||||
public async Task<IActionResult> Create(AddLinkCommand command)
|
public async Task<IActionResult> Create(AddLinkCommand command)
|
||||||
{
|
{
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
|
|||||||
16
Apps/Website/CustomExceptionFilter.cs
Normal file
16
Apps/Website/CustomExceptionFilter.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
|
||||||
|
namespace Website
|
||||||
|
{
|
||||||
|
public sealed class CustomExceptionFilter : IExceptionFilter
|
||||||
|
{
|
||||||
|
public void OnException(ExceptionContext context)
|
||||||
|
{
|
||||||
|
if (context.Exception is UserNotConnected)
|
||||||
|
{
|
||||||
|
context.Result = new UnauthorizedResult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
Apps/Website/HttpExecutingUserProvider.cs
Normal file
32
Apps/Website/HttpExecutingUserProvider.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
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<User> _userManager;
|
||||||
|
|
||||||
|
public HttpExecutingUserProvider(IHttpContextAccessor httpContextAccessor, UserManager<User> userManager)
|
||||||
|
{
|
||||||
|
_httpContextAccessor = httpContextAccessor;
|
||||||
|
_userManager = userManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Guid GetCurrentUserId()
|
||||||
|
{
|
||||||
|
var uid = _userManager.GetUserId(_httpContextAccessor.HttpContext.User);
|
||||||
|
|
||||||
|
if (!Guid.TryParse(uid, out Guid result))
|
||||||
|
{
|
||||||
|
throw new UserNotConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Apps/Website/Models/LoginViewModel.cs
Normal file
13
Apps/Website/Models/LoginViewModel.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Website.Models
|
||||||
|
{
|
||||||
|
public sealed class LoginViewModel
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string Username { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Password { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
17
Apps/Website/Models/RegisterViewModel.cs
Normal file
17
Apps/Website/Models/RegisterViewModel.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Website.Models
|
||||||
|
{
|
||||||
|
public sealed class RegisterViewModel
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string Username { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string Password { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[Compare(nameof(Password))]
|
||||||
|
public string PasswordConfirm { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,8 +2,11 @@ using HN.Application;
|
|||||||
using HN.Domain;
|
using HN.Domain;
|
||||||
using HN.Infrastructure;
|
using HN.Infrastructure;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Authorization;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
@ -28,15 +31,36 @@ namespace Website
|
|||||||
services.AddScoped<IHNContext, HNDbContext>();
|
services.AddScoped<IHNContext, HNDbContext>();
|
||||||
services.AddScoped<ILinkRepository, LinkRepository>();
|
services.AddScoped<ILinkRepository, LinkRepository>();
|
||||||
services.AddScoped<ICommentRepository, CommentRepository>();
|
services.AddScoped<ICommentRepository, CommentRepository>();
|
||||||
|
services.AddScoped<IExecutingUserProvider, HttpExecutingUserProvider>();
|
||||||
services.AddMediatR(typeof(HN.Application.IHNContext));
|
services.AddMediatR(typeof(HN.Application.IHNContext));
|
||||||
|
|
||||||
|
// Permet d'avoir des routes en lowercase
|
||||||
services.Configure<RouteOptions>(options =>
|
services.Configure<RouteOptions>(options =>
|
||||||
{
|
{
|
||||||
options.LowercaseUrls = true;
|
options.LowercaseUrls = true;
|
||||||
options.LowercaseQueryStrings = true;
|
options.LowercaseQueryStrings = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddControllersWithViews();
|
// Pour permettre l'authentification
|
||||||
|
services.AddIdentity<User, Role>(o =>
|
||||||
|
{
|
||||||
|
o.Password.RequiredLength = o.Password.RequiredUniqueChars = 0;
|
||||||
|
o.Password.RequireDigit = o.Password.RequireLowercase = o.Password.RequireNonAlphanumeric = o.Password.RequireUppercase = false;
|
||||||
|
})
|
||||||
|
.AddEntityFrameworkStores<HNDbContext>();
|
||||||
|
|
||||||
|
// Permet de reconfigurer certaines parties préconfigurées par Identity https://github.com/dotnet/aspnetcore/blob/3ea1fc7aac9d43152908d5d45ae811f3df7ca399/src/Identity/Core/src/IdentityServiceCollectionExtensions.cs#L51
|
||||||
|
services.PostConfigure<CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme, o =>
|
||||||
|
{
|
||||||
|
o.LoginPath = "/accounts/login";
|
||||||
|
o.LogoutPath = "/accounts/logout";
|
||||||
|
});
|
||||||
|
|
||||||
|
services.AddControllersWithViews(o =>
|
||||||
|
{
|
||||||
|
o.Filters.Add<CustomExceptionFilter>();
|
||||||
|
o.Filters.Add(new AuthorizeFilter()); // Nécessite l'authentification par défaut
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
@ -59,6 +83,20 @@ namespace Website
|
|||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
|
||||||
|
// Permet de rediriger selon les codes d'erreurs retournés, notamment par notre CustomExceptionFilter
|
||||||
|
app.UseStatusCodePages(context =>
|
||||||
|
{
|
||||||
|
var request = context.HttpContext.Request;
|
||||||
|
var response = context.HttpContext.Response;
|
||||||
|
if (response.StatusCode == (int)System.Net.HttpStatusCode.Unauthorized)
|
||||||
|
{
|
||||||
|
response.Redirect("/accounts/login");
|
||||||
|
}
|
||||||
|
|
||||||
|
return System.Threading.Tasks.Task.CompletedTask;
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseAuthentication();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
|
|||||||
12
Apps/Website/UserNotConnected.cs
Normal file
12
Apps/Website/UserNotConnected.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Website
|
||||||
|
{
|
||||||
|
public sealed class UserNotConnected : Exception
|
||||||
|
{
|
||||||
|
public UserNotConnected() : base("User not connected!")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Apps/Website/Views/Accounts/Login.cshtml
Normal file
13
Apps/Website/Views/Accounts/Login.cshtml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
@model LoginViewModel
|
||||||
|
|
||||||
|
<form asp-action="Login" method="post">
|
||||||
|
<label asp-for="@Model.Username"></label>
|
||||||
|
<input asp-for="@Model.Username" />
|
||||||
|
<span asp-validation-for="@Model.Username"></span>
|
||||||
|
|
||||||
|
<label asp-for="@Model.Password"></label>
|
||||||
|
<input type="password" asp-for="@Model.Password" />
|
||||||
|
<span asp-validation-for="@Model.Password"></span>
|
||||||
|
|
||||||
|
<button type="submit">Sign in</button>
|
||||||
|
</form>
|
||||||
17
Apps/Website/Views/Accounts/Register.cshtml
Normal file
17
Apps/Website/Views/Accounts/Register.cshtml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@model RegisterViewModel
|
||||||
|
|
||||||
|
<form asp-action="Register" method="post">
|
||||||
|
<label asp-for="@Model.Username"></label>
|
||||||
|
<input asp-for="@Model.Username" />
|
||||||
|
<span asp-validation-for="@Model.Username"></span>
|
||||||
|
|
||||||
|
<label asp-for="@Model.Password"></label>
|
||||||
|
<input type="password" asp-for="@Model.Password" />
|
||||||
|
<span asp-validation-for="@Model.Password"></span>
|
||||||
|
|
||||||
|
<label asp-for="@Model.PasswordConfirm"></label>
|
||||||
|
<input type="password" asp-for="@Model.PasswordConfirm" />
|
||||||
|
<span asp-validation-for="@Model.PasswordConfirm"></span>
|
||||||
|
|
||||||
|
<button type="submit">Register</button>
|
||||||
|
</form>
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
<a asp-action="Register" asp-controller="Accounts">Register</a>
|
||||||
|
<a asp-action="Login" asp-controller="Accounts">Sign in</a>
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
<p>Connected as @User.Identity.Name</p>
|
||||||
|
<form asp-action="Logout" asp-controller="Accounts" method="post">
|
||||||
|
<button type="submit">Sign out</button>
|
||||||
|
</form>
|
||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h2>Add a comment</h2>
|
<h2>Add a comment</h2>
|
||||||
|
@if(User.Identity.IsAuthenticated) {
|
||||||
<form asp-action="Create" asp-controller="Comments" method="post">
|
<form asp-action="Create" asp-controller="Comments" method="post">
|
||||||
<input type="hidden" asp-for="@Model.LinkId" />
|
<input type="hidden" asp-for="@Model.LinkId" />
|
||||||
<textarea asp-for="@Model.Content"></textarea>
|
<textarea asp-for="@Model.Content"></textarea>
|
||||||
@ -9,4 +10,7 @@
|
|||||||
|
|
||||||
<button type="submit">Post a comment</button>
|
<button type="submit">Post a comment</button>
|
||||||
</form>
|
</form>
|
||||||
|
} else {
|
||||||
|
<p>Only logged in users can comment.</p>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
@ -4,8 +4,11 @@
|
|||||||
<div>
|
<div>
|
||||||
👍: @Model.UpVotes / 👎: @Model.DownVotes
|
👍: @Model.UpVotes / 👎: @Model.DownVotes
|
||||||
</div>
|
</div>
|
||||||
<form asp-action="Vote" asp-controller="Comments" asp-route-id="@Model.Id" method="post">
|
|
||||||
|
@if (User.Identity.IsAuthenticated) {
|
||||||
|
<form asp-action="Vote" asp-controller="Comments" asp-route-id="@Model.Id" method="post">
|
||||||
<input type="hidden" name="redirectTo" value="@Context.Request.Path" />
|
<input type="hidden" name="redirectTo" value="@Context.Request.Path" />
|
||||||
<input type="submit" name="type" value="up" />
|
<input type="submit" name="type" value="up" />
|
||||||
<input type="submit" name="type" value="down" />
|
<input type="submit" name="type" value="down" />
|
||||||
</form>
|
</form>
|
||||||
|
}
|
||||||
@ -28,6 +28,8 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<vc:login />
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
@model HN.Application.LinkDto
|
@model HN.Application.LinkDto
|
||||||
|
|
||||||
<a asp-action="Show" asp-controller="Links" asp-route-id="@Model.Id">@Model.Url - created at @Model.CreatedAt.ToLocalTime() (👍: @Model.UpVotes / 👎: @Model.DownVotes)</a>
|
<a asp-action="Show" asp-controller="Links" asp-route-id="@Model.Id">@Model.Url - created at @Model.CreatedAt.ToLocalTime() by @Model.CreatedByName (👍: @Model.UpVotes / 👎: @Model.DownVotes)</a>
|
||||||
|
|
||||||
<form asp-controller="Links" asp-action="Vote" asp-route-id="@Model.Id" asp-route-url="@Model.Url" method="post">
|
@if(User.Identity.IsAuthenticated) {
|
||||||
|
<form asp-controller="Links" asp-action="Vote" asp-route-id="@Model.Id" asp-route-url="@Model.Url" method="post">
|
||||||
<input type="hidden" name="redirectTo" value="@Context.Request.Path" />
|
<input type="hidden" name="redirectTo" value="@Context.Request.Path" />
|
||||||
<input type="submit" name="type" value="up" />
|
<input type="submit" name="type" value="up" />
|
||||||
<input type="submit" name="type" value="down" />
|
<input type="submit" name="type" value="down" />
|
||||||
</form>
|
</form>
|
||||||
|
}
|
||||||
@ -1,34 +1,22 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace HN.Domain
|
namespace HN.Domain
|
||||||
{
|
{
|
||||||
public sealed class Comment
|
public sealed class Comment : Votable
|
||||||
{
|
{
|
||||||
public Guid Id { get; private set; }
|
public Guid Id { get; }
|
||||||
public Guid LinkId { get; private set; }
|
public Guid LinkId { get; }
|
||||||
public string Content { get; private set; }
|
public string Content { get; }
|
||||||
public DateTime CreatedAt { get; private set; }
|
public Guid CreatedBy { get; }
|
||||||
private List<Vote> _votes;
|
public DateTime CreatedAt { get; }
|
||||||
public IReadOnlyList<Vote> Votes => _votes;
|
|
||||||
|
|
||||||
internal Comment(Guid linkId, string content)
|
internal Comment(Guid linkId, Guid createdBy, string content) : base()
|
||||||
{
|
{
|
||||||
Id = Guid.NewGuid();
|
Id = Guid.NewGuid();
|
||||||
LinkId = linkId;
|
LinkId = linkId;
|
||||||
|
CreatedBy = createdBy;
|
||||||
Content = content;
|
Content = content;
|
||||||
CreatedAt = DateTime.UtcNow;
|
CreatedAt = DateTime.UtcNow;
|
||||||
_votes = new List<Vote>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Upvote()
|
|
||||||
{
|
|
||||||
_votes.Add(new Vote(VoteType.Up));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Downvote()
|
|
||||||
{
|
|
||||||
_votes.Add(new Vote(VoteType.Down));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,42 +1,30 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace HN.Domain
|
namespace HN.Domain
|
||||||
{
|
{
|
||||||
public sealed class Link
|
public sealed class Link : Votable
|
||||||
{
|
{
|
||||||
public Guid Id { get; }
|
public Guid Id { get; }
|
||||||
public string Url { get; }
|
public string Url { get; }
|
||||||
public DateTime CreatedAt { get; }
|
public DateTime CreatedAt { get; }
|
||||||
private List<Vote> _votes;
|
public Guid CreatedBy { get; }
|
||||||
public IReadOnlyList<Vote> Votes => _votes;
|
|
||||||
|
|
||||||
private Link(string url)
|
private Link(Guid createdBy, string url) : base()
|
||||||
{
|
{
|
||||||
this.Id = Guid.NewGuid();
|
Id = Guid.NewGuid();
|
||||||
this.CreatedAt = DateTime.UtcNow;
|
CreatedBy = createdBy;
|
||||||
this.Url = url;
|
CreatedAt = DateTime.UtcNow;
|
||||||
this._votes = new List<Vote>();
|
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));
|
return new Comment(Id, userId, content);
|
||||||
}
|
|
||||||
|
|
||||||
public void Downvote()
|
|
||||||
{
|
|
||||||
_votes.Add(new Vote(VoteType.Down));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comment AddComment(string content)
|
|
||||||
{
|
|
||||||
return new Comment(Id, content);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
43
Domain/Votable.cs
Normal file
43
Domain/Votable.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace HN.Domain
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Représente une entité sur laquelle on peut voter.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Votable
|
||||||
|
{
|
||||||
|
private List<Vote> _votes;
|
||||||
|
public IReadOnlyList<Vote> Votes => _votes;
|
||||||
|
|
||||||
|
protected Votable()
|
||||||
|
{
|
||||||
|
_votes = new List<Vote>();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,9 +5,21 @@ namespace HN.Domain
|
|||||||
public sealed class Vote
|
public sealed class Vote
|
||||||
{
|
{
|
||||||
public VoteType Type { get; private set; }
|
public VoteType Type { get; private set; }
|
||||||
|
public Guid CreatedBy { get; }
|
||||||
public DateTime CreatedAt { get; private set; }
|
public DateTime CreatedAt { get; private set; }
|
||||||
|
|
||||||
internal Vote(VoteType type)
|
internal Vote(Guid createdBy, VoteType type)
|
||||||
|
{
|
||||||
|
CreatedBy = createdBy;
|
||||||
|
Type = type;
|
||||||
|
CreatedAt = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Change le type d'un vote
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
public void HasType(VoteType type)
|
||||||
{
|
{
|
||||||
Type = type;
|
Type = type;
|
||||||
CreatedAt = DateTime.UtcNow;
|
CreatedAt = DateTime.UtcNow;
|
||||||
|
|||||||
@ -17,11 +17,14 @@ namespace HN.Infrastructure
|
|||||||
builder.Property(o => o.Content).IsRequired();
|
builder.Property(o => o.Content).IsRequired();
|
||||||
builder.Property(o => o.CreatedAt).IsRequired();
|
builder.Property(o => o.CreatedAt).IsRequired();
|
||||||
|
|
||||||
|
builder.HasOne<User>().WithMany().HasForeignKey(nameof(Comment.CreatedBy)).IsRequired();
|
||||||
|
|
||||||
builder.OwnsMany(o => o.Votes, vote =>
|
builder.OwnsMany(o => o.Votes, vote =>
|
||||||
{
|
{
|
||||||
vote.ToTable("comment_votes");
|
vote.ToTable("comment_votes");
|
||||||
vote.WithOwner().HasForeignKey("CommentId");
|
vote.WithOwner().HasForeignKey("CommentId");
|
||||||
vote.HasKey("CommentId");
|
vote.HasKey("CommentId", nameof(Comment.CreatedBy));
|
||||||
|
vote.HasOne<User>().WithMany().HasForeignKey(nameof(Vote.CreatedBy)).IsRequired();
|
||||||
vote.Property(o => o.Type).IsRequired();
|
vote.Property(o => o.Type).IsRequired();
|
||||||
vote.Property(o => o.CreatedAt).IsRequired();
|
vote.Property(o => o.CreatedAt).IsRequired();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -14,11 +14,14 @@ namespace HN.Infrastructure.EntityTypes
|
|||||||
builder.Property(o => o.CreatedAt).IsRequired();
|
builder.Property(o => o.CreatedAt).IsRequired();
|
||||||
builder.HasIndex(o => o.Url).IsUnique();
|
builder.HasIndex(o => o.Url).IsUnique();
|
||||||
|
|
||||||
|
builder.HasOne<User>().WithMany().HasForeignKey(nameof(Link.CreatedBy)).IsRequired();
|
||||||
|
|
||||||
builder.OwnsMany(o => o.Votes, vote =>
|
builder.OwnsMany(o => o.Votes, vote =>
|
||||||
{
|
{
|
||||||
vote.ToTable("link_votes");
|
vote.ToTable("link_votes");
|
||||||
vote.WithOwner().HasForeignKey("LinkId");
|
vote.WithOwner().HasForeignKey("LinkId");
|
||||||
vote.HasKey("LinkId");
|
vote.HasKey("LinkId", nameof(Link.CreatedBy));
|
||||||
|
vote.HasOne<User>().WithMany().HasForeignKey(nameof(Vote.CreatedBy)).IsRequired();
|
||||||
vote.Property(o => o.Type).IsRequired();
|
vote.Property(o => o.Type).IsRequired();
|
||||||
vote.Property(o => o.CreatedAt).IsRequired();
|
vote.Property(o => o.CreatedAt).IsRequired();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,16 +1,21 @@
|
|||||||
using HN.Application;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using HN.Application;
|
||||||
using HN.Domain;
|
using HN.Domain;
|
||||||
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace HN.Infrastructure
|
namespace HN.Infrastructure
|
||||||
{
|
{
|
||||||
public sealed class HNDbContext : DbContext, IHNContext
|
public sealed class HNDbContext : IdentityDbContext<User, Role, Guid>, IHNContext
|
||||||
{
|
{
|
||||||
private readonly ILoggerFactory _loggerFactory;
|
private readonly ILoggerFactory _loggerFactory;
|
||||||
public DbSet<Link> Links { get; set; }
|
public DbSet<Link> Links { get; set; }
|
||||||
public DbSet<Comment> Comments { get; set; }
|
public DbSet<Comment> Comments { get; set; }
|
||||||
|
|
||||||
|
IQueryable<IUser> IHNContext.Users => Users;
|
||||||
|
|
||||||
public HNDbContext()
|
public HNDbContext()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -21,7 +26,11 @@ namespace HN.Infrastructure
|
|||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder) => modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
base.OnModelCreating(modelBuilder);
|
||||||
|
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.0">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.0">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
|||||||
364
Infrastructure/Migrations/20201211113924_AddNetIdentity.Designer.cs
generated
Normal file
364
Infrastructure/Migrations/20201211113924_AddNetIdentity.Designer.cs
generated
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
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("20201211113924_AddNetIdentity")]
|
||||||
|
partial class AddNetIdentity
|
||||||
|
{
|
||||||
|
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<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("LinkId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("LinkId");
|
||||||
|
|
||||||
|
b.ToTable("comments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("HN.Domain.Link", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Url")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Url")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("links");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("HN.Infrastructure.Role", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("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<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("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<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("RoleId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("UserId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("UserId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("UserId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("RoleId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("UserId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("HN.Domain.Comment", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("HN.Domain.Link", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LinkId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.OwnsMany("HN.Domain.Vote", "Votes", b1 =>
|
||||||
|
{
|
||||||
|
b1.Property<Guid>("CommentId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b1.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b1.Property<int>("Type")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b1.HasKey("CommentId");
|
||||||
|
|
||||||
|
b1.ToTable("comment_votes");
|
||||||
|
|
||||||
|
b1.WithOwner()
|
||||||
|
.HasForeignKey("CommentId");
|
||||||
|
});
|
||||||
|
|
||||||
|
b.Navigation("Votes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("HN.Domain.Link", b =>
|
||||||
|
{
|
||||||
|
b.OwnsMany("HN.Domain.Vote", "Votes", b1 =>
|
||||||
|
{
|
||||||
|
b1.Property<Guid>("LinkId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b1.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b1.Property<int>("Type")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b1.HasKey("LinkId");
|
||||||
|
|
||||||
|
b1.ToTable("link_votes");
|
||||||
|
|
||||||
|
b1.WithOwner()
|
||||||
|
.HasForeignKey("LinkId");
|
||||||
|
});
|
||||||
|
|
||||||
|
b.Navigation("Votes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("HN.Infrastructure.Role", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("HN.Infrastructure.User", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("HN.Infrastructure.User", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", 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<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("HN.Infrastructure.User", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
217
Infrastructure/Migrations/20201211113924_AddNetIdentity.cs
Normal file
217
Infrastructure/Migrations/20201211113924_AddNetIdentity.cs
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
public partial class AddNetIdentity : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetRoles",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||||
|
Name = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true),
|
||||||
|
NormalizedName = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true),
|
||||||
|
ConcurrencyStamp = table.Column<string>(type: "TEXT", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetUsers",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||||
|
UserName = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true),
|
||||||
|
NormalizedUserName = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true),
|
||||||
|
Email = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true),
|
||||||
|
NormalizedEmail = table.Column<string>(type: "TEXT", maxLength: 256, nullable: true),
|
||||||
|
EmailConfirmed = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||||
|
PasswordHash = table.Column<string>(type: "TEXT", nullable: true),
|
||||||
|
SecurityStamp = table.Column<string>(type: "TEXT", nullable: true),
|
||||||
|
ConcurrencyStamp = table.Column<string>(type: "TEXT", nullable: true),
|
||||||
|
PhoneNumber = table.Column<string>(type: "TEXT", nullable: true),
|
||||||
|
PhoneNumberConfirmed = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||||
|
TwoFactorEnabled = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||||
|
LockoutEnd = table.Column<DateTimeOffset>(type: "TEXT", nullable: true),
|
||||||
|
LockoutEnabled = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||||
|
AccessFailedCount = table.Column<int>(type: "INTEGER", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetRoleClaims",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
RoleId = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||||
|
ClaimType = table.Column<string>(type: "TEXT", nullable: true),
|
||||||
|
ClaimValue = table.Column<string>(type: "TEXT", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
|
||||||
|
column: x => x.RoleId,
|
||||||
|
principalTable: "AspNetRoles",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetUserClaims",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
UserId = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||||
|
ClaimType = table.Column<string>(type: "TEXT", nullable: true),
|
||||||
|
ClaimValue = table.Column<string>(type: "TEXT", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetUserLogins",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
LoginProvider = table.Column<string>(type: "TEXT", nullable: false),
|
||||||
|
ProviderKey = table.Column<string>(type: "TEXT", nullable: false),
|
||||||
|
ProviderDisplayName = table.Column<string>(type: "TEXT", nullable: true),
|
||||||
|
UserId = table.Column<Guid>(type: "TEXT", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetUserRoles",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
UserId = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||||
|
RoleId = table.Column<Guid>(type: "TEXT", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
|
||||||
|
column: x => x.RoleId,
|
||||||
|
principalTable: "AspNetRoles",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetUserTokens",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
UserId = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||||
|
LoginProvider = table.Column<string>(type: "TEXT", nullable: false),
|
||||||
|
Name = table.Column<string>(type: "TEXT", nullable: false),
|
||||||
|
Value = table.Column<string>(type: "TEXT", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_AspNetRoleClaims_RoleId",
|
||||||
|
table: "AspNetRoleClaims",
|
||||||
|
column: "RoleId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "RoleNameIndex",
|
||||||
|
table: "AspNetRoles",
|
||||||
|
column: "NormalizedName",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_AspNetUserClaims_UserId",
|
||||||
|
table: "AspNetUserClaims",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_AspNetUserLogins_UserId",
|
||||||
|
table: "AspNetUserLogins",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_AspNetUserRoles_RoleId",
|
||||||
|
table: "AspNetUserRoles",
|
||||||
|
column: "RoleId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "EmailIndex",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
column: "NormalizedEmail");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "UserNameIndex",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
column: "NormalizedUserName",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetRoleClaims");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetUserClaims");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetUserLogins");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetUserRoles");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetUserTokens");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetRoles");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetUsers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
408
Infrastructure/Migrations/20201211144029_AddCreatedBy.Designer.cs
generated
Normal file
408
Infrastructure/Migrations/20201211144029_AddCreatedBy.Designer.cs
generated
Normal file
@ -0,0 +1,408 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
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<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("CreatedBy")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("LinkId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CreatedBy");
|
||||||
|
|
||||||
|
b.HasIndex("LinkId");
|
||||||
|
|
||||||
|
b.ToTable("comments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("HN.Domain.Link", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("CreatedBy")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("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<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("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<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("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<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("RoleId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("UserId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("UserId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("UserId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("RoleId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("UserId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("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<Guid>("CommentId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b1.Property<Guid>("CreatedBy")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b1.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b1.Property<int>("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<Guid>("LinkId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b1.Property<Guid>("CreatedBy")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b1.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b1.Property<int>("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<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("HN.Infrastructure.Role", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("HN.Infrastructure.User", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("HN.Infrastructure.User", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", 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<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("HN.Infrastructure.User", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
178
Infrastructure/Migrations/20201211144029_AddCreatedBy.cs
Normal file
178
Infrastructure/Migrations/20201211144029_AddCreatedBy.cs
Normal file
@ -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<Guid>(
|
||||||
|
name: "CreatedBy",
|
||||||
|
table: "links",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<Guid>(
|
||||||
|
name: "CreatedBy",
|
||||||
|
table: "link_votes",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<Guid>(
|
||||||
|
name: "CreatedBy",
|
||||||
|
table: "comments",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<Guid>(
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -29,11 +29,16 @@ namespace Infrastructure.Migrations
|
|||||||
b.Property<DateTime>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("CreatedBy")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b.Property<Guid>("LinkId")
|
b.Property<Guid>("LinkId")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CreatedBy");
|
||||||
|
|
||||||
b.HasIndex("LinkId");
|
b.HasIndex("LinkId");
|
||||||
|
|
||||||
b.ToTable("comments");
|
b.ToTable("comments");
|
||||||
@ -48,6 +53,9 @@ namespace Infrastructure.Migrations
|
|||||||
b.Property<DateTime>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("CreatedBy")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b.Property<string>("Url")
|
b.Property<string>("Url")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasMaxLength(500)
|
.HasMaxLength(500)
|
||||||
@ -55,14 +63,213 @@ namespace Infrastructure.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CreatedBy");
|
||||||
|
|
||||||
b.HasIndex("Url")
|
b.HasIndex("Url")
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
b.ToTable("links");
|
b.ToTable("links");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("HN.Infrastructure.Role", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("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<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("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<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("RoleId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("UserId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("UserId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("UserId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("RoleId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("UserId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("HN.Domain.Comment", b =>
|
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)
|
b.HasOne("HN.Domain.Link", null)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("LinkId")
|
.HasForeignKey("LinkId")
|
||||||
@ -74,18 +281,29 @@ namespace Infrastructure.Migrations
|
|||||||
b1.Property<Guid>("CommentId")
|
b1.Property<Guid>("CommentId")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b1.Property<Guid>("CreatedBy")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b1.Property<DateTime>("CreatedAt")
|
b1.Property<DateTime>("CreatedAt")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b1.Property<int>("Type")
|
b1.Property<int>("Type")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
b1.HasKey("CommentId");
|
b1.HasKey("CommentId", "CreatedBy");
|
||||||
|
|
||||||
|
b1.HasIndex("CreatedBy");
|
||||||
|
|
||||||
b1.ToTable("comment_votes");
|
b1.ToTable("comment_votes");
|
||||||
|
|
||||||
b1.WithOwner()
|
b1.WithOwner()
|
||||||
.HasForeignKey("CommentId");
|
.HasForeignKey("CommentId");
|
||||||
|
|
||||||
|
b1.HasOne("HN.Infrastructure.User", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CreatedBy")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
});
|
});
|
||||||
|
|
||||||
b.Navigation("Votes");
|
b.Navigation("Votes");
|
||||||
@ -93,27 +311,95 @@ namespace Infrastructure.Migrations
|
|||||||
|
|
||||||
modelBuilder.Entity("HN.Domain.Link", b =>
|
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 =>
|
b.OwnsMany("HN.Domain.Vote", "Votes", b1 =>
|
||||||
{
|
{
|
||||||
b1.Property<Guid>("LinkId")
|
b1.Property<Guid>("LinkId")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b1.Property<Guid>("CreatedBy")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b1.Property<DateTime>("CreatedAt")
|
b1.Property<DateTime>("CreatedAt")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b1.Property<int>("Type")
|
b1.Property<int>("Type")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
b1.HasKey("LinkId");
|
b1.HasKey("LinkId", "CreatedBy");
|
||||||
|
|
||||||
|
b1.HasIndex("CreatedBy");
|
||||||
|
|
||||||
b1.ToTable("link_votes");
|
b1.ToTable("link_votes");
|
||||||
|
|
||||||
|
b1.HasOne("HN.Infrastructure.User", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CreatedBy")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
b1.WithOwner()
|
b1.WithOwner()
|
||||||
.HasForeignKey("LinkId");
|
.HasForeignKey("LinkId");
|
||||||
});
|
});
|
||||||
|
|
||||||
b.Navigation("Votes");
|
b.Navigation("Votes");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("HN.Infrastructure.Role", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("HN.Infrastructure.User", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("HN.Infrastructure.User", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", 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<System.Guid>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("HN.Infrastructure.User", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
#pragma warning restore 612, 618
|
#pragma warning restore 612, 618
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
Infrastructure/Role.cs
Normal file
10
Infrastructure/Role.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
|
||||||
|
namespace HN.Infrastructure
|
||||||
|
{
|
||||||
|
public sealed class Role : IdentityRole<Guid>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Infrastructure/User.cs
Normal file
14
Infrastructure/User.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using HN.Application;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
|
||||||
|
namespace HN.Infrastructure
|
||||||
|
{
|
||||||
|
public sealed class User : IdentityUser<Guid>, IUser
|
||||||
|
{
|
||||||
|
public User(string userName) : base(userName)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
README.md
13
README.md
@ -87,6 +87,19 @@ Proche de ce qui est fait en Blazor mais sans la partie interactivité. Possibil
|
|||||||
|
|
||||||
#### Tag Helpers
|
#### Tag Helpers
|
||||||
|
|
||||||
|
### Authentification avec ASP.Net Identity Core
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ cd Infrastructure
|
||||||
|
$ dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
|
||||||
|
```
|
||||||
|
|
||||||
|
On fait hériter notre `HNDbContext` de `IdentityDbContext`. On peut créer des types customs pour nos User et Role de manière à utiliser des Guid et rester cohérent.
|
||||||
|
|
||||||
|
Côté web, on s'assure d'avoir bien ajouter `AddIdentity` avec les options qui nous intéressent.
|
||||||
|
|
||||||
|
Grâce à ça, nous aurons à notre disposition un `UserManager<User>` et un `SignInManager<User>` nous permettant de réaliser les opérations d'authentification. Bien penser au `UseAuthentication` avant le `UseAuthorization` afin que l'authentification puisse avoir lieu.
|
||||||
|
|
||||||
## Démarche
|
## Démarche
|
||||||
|
|
||||||
On crée un fichier solution avec `dotnet new sln`. On pourra alimenter ce fichier sln avec la commande `dotnet sln add DirProjet`.
|
On crée un fichier solution avec `dotnet new sln`. On pourra alimenter ce fichier sln avec la commande `dotnet sln add DirProjet`.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user