Заменил самописную регистрацию на IdentityCore и поменял миграции

parent 355dfcbe
using System.Security.Claims; using System.Security.Claims;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Store.Models;
using Store.Models.Users; using Store.Models.Users;
using Store.Repositories.Interfaces;
using Store.ViewModels.Auths; using Store.ViewModels.Auths;
namespace Store.Controllers; namespace Store.Controllers;
public class AccountsController : Controller public class AccountsController : Controller
{ {
private readonly IUserRepository _userRepository; private readonly UserManager<User> _userManager;
private readonly SignInManager<User> _signInManager;
public AccountsController(IUserRepository userRepository) public AccountsController(UserManager<User> userManager, SignInManager<User> signInManager)
{ {
_userRepository = userRepository; _userManager = userManager;
_signInManager = signInManager;
} }
[HttpGet] [HttpGet]
...@@ -24,100 +24,91 @@ public class AccountsController : Controller ...@@ -24,100 +24,91 @@ public class AccountsController : Controller
return View(); return View();
} }
// [HttpPost]
// [ValidateAntiForgeryToken]
// public async Task<IActionResult> Login(LoginViewModel model)
// {
// try
// {
// if (ModelState.IsValid)
// {
// var user = _userRepository.GetUserByEmail(model.Email);
// if (user is not null)
// {
// if (user.Password.Equals(model.Password))
// {
// await AuthenticateAsync(user);
// return RedirectToAction("Index", "Home");
// }
// ModelState.AddModelError("", "пароль введен неверно");
// }
// else
// {
// ModelState.AddModelError("", "пользователь не найден");
// }
// }
//
// return View(model);
// }
// catch (Exception e)
// {
// Console.WriteLine(e);
// return View();
// }
// }
[HttpGet]
public IActionResult Register()
{
return View();
}
[HttpPost] [HttpPost]
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model) public async Task<IActionResult> Register(RegisterViewModel viewModel)
{ {
try try
{ {
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
var user = _userRepository.GetUserByEmail(model.Email); var email = await _userManager.FindByEmailAsync(viewModel.Email);
if (user is not null) if (email is null)
{ {
if (user.Password.Equals(model.Password)) var user = new User
{
Email = viewModel.Email,
UserName = viewModel.UserName,
BirthDate = viewModel.BirthDate.Date
};
var result = await _userManager.CreateAsync(user, viewModel.Password);
if (result.Succeeded)
{ {
await AuthenticateAsync(user); await _signInManager.SignInAsync(user, true);
return RedirectToAction("Index", "Home"); return RedirectToAction("Index", "Home");
} }
ModelState.AddModelError("", "пароль введен неверно");
} foreach (var error in result.Errors)
else ModelState.AddModelError(string.Empty, error.Description);
{
ModelState.AddModelError("", "пользователь не найден"); return View(viewModel);
} }
ModelState.AddModelError("", "пользователь с таким email уже существует");
} }
return View(model); return View(viewModel);
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(e); ModelState.AddModelError("", e.Message);
return View(); return View(viewModel);
} }
} }
[HttpGet]
public IActionResult Register()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel viewModel)
{
if (ModelState.IsValid)
{
var user = _userRepository.GetUserByEmail(viewModel.Email);
if (user is null)
{
var role = _userRepository.GetRoles().FirstOrDefault(s => s.Name == "user");
var newUser = new User
{
Email = viewModel.Email,
Password = viewModel.Password,
RoleId = role?.Id,
Role = role
};
_userRepository.Create(newUser);
_userRepository.Save();
await AuthenticateAsync(newUser);
return RedirectToAction("Index", "Home");
}
ModelState.AddModelError("", "пользователь с таким email уже существует");
}
return View(viewModel);
}
public async Task<IActionResult> Logout() public async Task<IActionResult> Logout()
{ {
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToAction("Login"); return RedirectToAction("Login");
} }
private async Task AuthenticateAsync(User user)
{
var claims = new List<Claim>
{
new Claim(ClaimsIdentity.DefaultNameClaimType, user.Email),
new Claim(ClaimsIdentity.DefaultNameClaimType, user.Role?.Name)
};
ClaimsIdentity id = new ClaimsIdentity(
claims,
"ApplicationCookie",
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(id),
new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTime.UtcNow.AddMinutes(1)
}
);
}
} }
\ No newline at end of file
...@@ -19,8 +19,7 @@ public class HomeController : Controller ...@@ -19,8 +19,7 @@ public class HomeController : Controller
{ {
return View(); return View();
} }
[Authorize(Roles = "admin, user")]
public IActionResult Privacy() public IActionResult Privacy()
{ {
return View(); return View();
......
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Store.Models; using Store.Models;
using Store.Repositories; using Store.Models.Users;
using Store.Repositories.Interfaces;
namespace Store.Extensions; namespace Store.Extensions;
...@@ -11,14 +11,8 @@ public static class ServicesAppExtension ...@@ -11,14 +11,8 @@ public static class ServicesAppExtension
public static void AddAppServices(this IServiceCollection services, IConfiguration configuration) public static void AddAppServices(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddDbContext<AppDbContext>(opt => services.AddDbContext<AppDbContext>(opt =>
opt.UseNpgsql(configuration.GetConnectionString("ConnectionString"))); opt.UseNpgsql(configuration.GetConnectionString("ConnectionString")))
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddIdentity<User, IdentityRole>()
.AddCookie(opt => .AddEntityFrameworkStores<AppDbContext>();
{
opt.LoginPath = new PathString("/Accounts/Login");
});
//repositories
services.AddScoped<IUserRepository, UserRepository>();
} }
} }
\ No newline at end of file
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Store.Models;
#nullable disable
namespace Store.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20220718152553_Init")]
partial class Init
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "6.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Store.Models.Users.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Roles");
b.HasData(
new
{
Id = 1,
Name = "admin"
},
new
{
Id = 2,
Name = "user"
});
});
modelBuilder.Entity("Store.Models.Users.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("text");
b.Property<int?>("RoleId")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("Users");
b.HasData(
new
{
Id = 1,
Email = "email@test",
Password = "1234",
RoleId = 1
});
});
modelBuilder.Entity("Store.Models.Users.User", b =>
{
b.HasOne("Store.Models.Users.Role", "Role")
.WithMany("Users")
.HasForeignKey("RoleId");
b.Navigation("Role");
});
modelBuilder.Entity("Store.Models.Users.Role", b =>
{
b.Navigation("Users");
});
#pragma warning restore 612, 618
}
}
}
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Store.Migrations
{
public partial class Init : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Roles",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Name = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Roles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Email = table.Column<string>(type: "text", nullable: false),
Password = table.Column<string>(type: "text", nullable: false),
RoleId = table.Column<int>(type: "integer", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
table.ForeignKey(
name: "FK_Users_Roles_RoleId",
column: x => x.RoleId,
principalTable: "Roles",
principalColumn: "Id");
});
migrationBuilder.InsertData(
table: "Roles",
columns: new[] { "Id", "Name" },
values: new object[,]
{
{ 1, "admin" },
{ 2, "user" }
});
migrationBuilder.InsertData(
table: "Users",
columns: new[] { "Id", "Email", "Password", "RoleId" },
values: new object[] { 1, "email@test", "1234", 1 });
migrationBuilder.CreateIndex(
name: "IX_Users_RoleId",
table: "Users",
column: "RoleId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Users");
migrationBuilder.DropTable(
name: "Roles");
}
}
}
This diff is collapsed.
This diff is collapsed.
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Store.Models.Users; using Store.Models.Users;
namespace Store.Models; namespace Store.Models;
public class AppDbContext : DbContext public class AppDbContext : IdentityDbContext<User>
{ {
public DbSet<User> Users { get; set; } public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public AppDbContext(DbContextOptions<AppDbContext> contextOptions) : base(contextOptions) public AppDbContext(DbContextOptions<AppDbContext> contextOptions) : base(contextOptions)
{ {
...@@ -15,9 +15,7 @@ public class AppDbContext : DbContext ...@@ -15,9 +15,7 @@ public class AppDbContext : DbContext
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
modelBuilder.Entity<Role>().HasData(new Role {Id = 1, Name = "admin"}); base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Role>().HasData(new Role {Id = 2, Name = "user"});
modelBuilder.Entity<User>().HasData(new User {Id = 1, Email = "email@test", Password = "1234", RoleId = 1});
} }
} }
\ No newline at end of file
namespace Store.Models.Users;
public class Role
{
public int Id { get; set; }
public string Name { get; set; }
public List<User> Users { get; set; }
public Role()
{
Users = new List<User>();
}
}
\ No newline at end of file
using Microsoft.AspNetCore.Identity;
namespace Store.Models.Users; namespace Store.Models.Users;
public class User public class User : IdentityUser
{ {
public int Id { get; set; } public DateTime BirthDate { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public int? RoleId { get; set; }
public Role? Role { get; set; }
} }
\ No newline at end of file
using Store.Models;
using Store.Models.Users;
namespace Store.Repositories.Interfaces;
public interface IUserRepository : IRepository<User>
{
User? GetUserById(int id);
User? GetUserByEmail(string email);
List<Role> GetRoles();
}
\ No newline at end of file
using Microsoft.EntityFrameworkCore;
using Store.Models;
using Store.Models.Users;
using Store.Repositories.Interfaces;
namespace Store.Repositories;
public class UserRepository : IUserRepository
{
private readonly AppDbContext _context;
public UserRepository(AppDbContext context)
{
_context = context;
}
public void Create(User item)
{
_context.Users.Add(item);
}
public void Update(User item)
{
_context.Users.Update(item);
}
public void Remove(User item)
{
_context.Users.Remove(item);
}
public void Save()
{
_context.SaveChanges();
}
public User? GetUserById(int id)
{
return _context.Users.Include(u => u.Role).FirstOrDefault(s => s.Id == id);
}
public User? GetUserByEmail(string email)
{
return _context.Users.Include(u => u.Role).FirstOrDefault(s => s.Email == email);
}
public List<Role> GetRoles() => _context.Roles.ToList();
}
\ No newline at end of file
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.7"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.7">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
......
...@@ -6,6 +6,10 @@ public class RegisterViewModel ...@@ -6,6 +6,10 @@ public class RegisterViewModel
{ {
[Required(ErrorMessage = "Введите email")] [Required(ErrorMessage = "Введите email")]
public string Email { get; set; } public string Email { get; set; }
[Required(ErrorMessage = "Введите username")]
public string UserName { get; set; }
[Required]
public DateTime BirthDate { get; set; }
[Required(ErrorMessage = "Введите пароль")] [Required(ErrorMessage = "Введите пароль")]
[DataType(DataType.Password)] [DataType(DataType.Password)]
public string Password { get; set; } public string Password { get; set; }
......
@using Microsoft.AspNetCore.Mvc.TagHelpers @using Microsoft.AspNetCore.Mvc.TagHelpers
@model Store.ViewModels.Auths.RegisterViewModel @model Store.ViewModels.Auths.RegisterViewModel
@{
ViewBag.Title = "Регистрация"; <h2>Регистрация нового пользователя</h2>
} <form method="post" asp-controller="Accounts" asp-action="Register">
<div asp-validation-summary="ModelOnly"></div>
<h2>Регистрация</h2>
<form asp-action="Register" asp-controller="Accounts" asp-anti-forgery="true">
<div class="validation" asp-validation-summary="ModelOnly"></div>
<div> <div>
<div> <label asp-for="Email"></label><br/>
<label asp-for="Email">Введите Email</label><br /> <input asp-for="Email"/>
<input type="text" asp-for="Email" /> <span asp-validation-for="Email"></span>
<span asp-validation-for="Email"></span> </div>
</div> <div>
<div> <label asp-for="UserName"></label><br/>
<label asp-for="Password">Введите пароль</label><br /> <input asp-for="UserName"/>
<input asp-for="Password" /> <span asp-validation-for="UserName"></span>
<span asp-validation-for="Password"></span> </div>
</div> <div>
<div> <label asp-for="BirthDate"></label><br/>
<label asp-for="ConfirmPassword">Повторите пароль</label><br /> <input asp-for="BirthDate" type="date"/>
<input asp-for="ConfirmPassword" /> <span asp-validation-for="BirthDate"></span>
<span asp-validation-for="ConfirmPassword"></span> </div>
</div> <div>
<div> <label asp-for="Password"></label><br/>
<input type="submit" value="Регистрация" /> <input asp-for="Password"/>
</div> <span asp-validation-for="Password"></span>
</div>
<div>
<label asp-for="ConfirmPassword"></label><br/>
<input asp-for="ConfirmPassword"/>
<span asp-validation-for="ConfirmPassword"></span>
</div>
<div>
<input type="submit" value="Регистрация"/>
</div> </div>
</form> </form>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment