合并请求:从 develop 到 master

Reviewed-on: #4
This commit is contained in:
罗澜大帅哥 2025-07-10 00:17:32 +08:00
commit 9a0bba59b5
26 changed files with 449 additions and 1075 deletions

View File

@ -5,73 +5,72 @@
ViewData["Title"] = "登录";
}
<h1>@ViewData["Title"]</h1>
<div class="row">
<div class="col-md-4">
<section>
<form id="account" method="post">
<h2>使用本地账户登录。</h2>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
<div class="form-floating mb-3">
<input asp-for="Input.Email" class="form-control" autocomplete="username" aria-required="true" placeholder="name@example.com" />
<label asp-for="Input.Email" class="form-label">电子邮件</label>
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-floating mb-3">
<input asp-for="Input.Password" class="form-control" autocomplete="current-password" aria-required="true" placeholder="password" />
<label asp-for="Input.Password" class="form-label">密码</label>
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="checkbox mb-3">
<label asp-for="Input.RememberMe" class="form-label">
<h1 class="text-center">@ViewData["Title"]</h1>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<section>
<form id="account" method="post" class="card p-4">
<h2 class="text-center">使用本地账户登录。</h2>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
<div class="form-outline mb-4">
<input asp-for="Input.Email" type="email" id="email" class="form-control" autocomplete="username" aria-required="true" placeholder="name@example.com" />
<label asp-for="Input.Email" class="form-label">电子邮件</label>
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-outline mb-4">
<input asp-for="Input.Password" type="password" id="password" class="form-control" autocomplete="current-password" aria-required="true" placeholder="password" />
<label asp-for="Input.Password" class="form-label">密码</label>
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-check mb-4">
<input class="form-check-input" asp-for="Input.RememberMe" />
记住我
</label>
</div>
<div>
<button id="login-submit" type="submit" class="w-100 btn btn-lg btn-primary">登录</button>
</div>
<div>
<p>
<a id="forgot-password" asp-page="./ForgotPassword">忘记密码?</a>
</p>
<p>
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">注册为新用户</a>
</p>
<p>
<a id="resend-confirmation" asp-page="./ResendEmailConfirmation">重新发送电子邮件确认</a>
</p>
</div>
</form>
</section>
</div>
<div class="col-md-6 col-md-offset-2">
<section>
<h3>使用其他服务登录。</h3>
<hr />
@{
if ((Model.ExternalLogins?.Count ?? 0) == 0)
{
<div>
<label class="form-check-label" asp-for="Input.RememberMe">记住我</label>
</div>
<div class="d-grid gap-2">
<button id="login-submit" type="submit" class="btn btn-primary btn-block">登录</button>
</div>
<div class="text-center mt-3">
<p>
没有配置外部身份验证服务。请参阅<a href="https://go.microsoft.com/fwlink/?LinkID=532715">关于设置此ASP.NET应用程序以支持通过外部服务登录的文章</a>。
<a id="forgot-password" asp-page="./ForgotPassword">忘记密码?</a>
</p>
<p>
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">注册为新用户</a>
</p>
<p>
<a id="resend-confirmation" asp-page="./ResendEmailConfirmation">重新发送电子邮件确认</a>
</p>
</div>
}
else
{
<form id="external-account" asp-page="./ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" method="post" class="form-horizontal">
<div>
<p>
@foreach (var provider in Model.ExternalLogins!)
{
<button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
}
</p>
</div>
</form>
}
</form>
</section>
</div>
</div>
</div>
<div class="row justify-content-end">
<div class="col-md-6">
<section>
<h3 class="text-center">使用其他服务登录。</h3>
<hr />
@if ((Model.ExternalLogins?.Count ?? 0) == 0)
{
<div>
<p class="text-center">
没有配置外部身份验证服务。请参阅<a href="https://go.microsoft.com/fwlink/?LinkID=532715">关于设置此ASP.NET应用程序以支持通过外部服务登录的文章</a>。
</p>
</div>
}
else
{
<form id="external-account" asp-page="./ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" method="post" class="card p-4">
<div class="d-grid gap-2">
@foreach (var provider in Model.ExternalLogins!)
{
<button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="使用您的 @provider.DisplayName 账户登录">@provider.DisplayName</button>
}
</div>
</form>
}
</section>
</div>
@ -79,4 +78,4 @@
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
}

View File

@ -127,7 +127,8 @@ namespace AGSS.Areas.Identity.Pages.Account
_logger.LogInformation("User logged in.");
var user = await _userManager.FindByEmailAsync(Input.Email);
var token = _jwt.GenerateJwtToken(user);
var roles = await _userManager.GetRolesAsync(user);
var token = _jwt.GenerateJwtToken(user,roles);
var frontendCallback = $"{Request.Query["frontendCallback"]}?token={token}";

View File

@ -49,5 +49,8 @@
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
@await Html.PartialAsync("_ValidationScriptsPartial")
<script type="text/javascript" src="~/lib/qrcode/qrcode.js"></script>
<script type="text/javascript" src="~/js/qr.js"></script>
}

View File

@ -18,15 +18,20 @@
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-floating mb-3">
<input asp-for="Input.Password" class="form-control" autocomplete="new-password" aria-required="true" placeholder="password" />
<input asp-for="Input.Password" class="form-control" autocomplete="new-password" aria-required="true" placeholder="请输入密码" />
<label asp-for="Input.Password">密码</label>
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-floating mb-3">
<input asp-for="Input.ConfirmPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="password" />
<input asp-for="Input.ConfirmPassword" class="form-control" autocomplete="new-sex" aria-required="true" placeholder="确认密码" />
<label asp-for="Input.ConfirmPassword">确认密码</label>
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div>
<div class="form-floating mb-3">
<input asp-for="Input.Sex" class="form-control" autocomplete="username" aria-required="true" placeholder="男/女" />
<label asp-for="Input.Sex">性别</label>
<span asp-validation-for="Input.Sex" class="text-danger"></span>
</div>
<button id="registerSubmit" type="submit" class="w-100 btn btn-lg btn-primary">注册</button>
</form>
</div>

View File

@ -104,6 +104,12 @@ namespace AGSS.Areas.Identity.Pages.Account
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
[MaxLength(10)]
[Display(Name = "Confirm password")]
public string Sex { get; set; }
}
@ -120,7 +126,8 @@ namespace AGSS.Areas.Identity.Pages.Account
if (ModelState.IsValid)
{
var user = CreateUser();
user.Id = Guid.NewGuid().ToString();
user.Sex = Input.Sex;
await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
var result = await _userManager.CreateAsync(user, Input.Password);
@ -128,8 +135,8 @@ namespace AGSS.Areas.Identity.Pages.Account
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var user1 = await _userManager.FindByEmailAsync(Input.Email);
var token = _jwt.GenerateJwtToken(user1);
var roles = await _userManager.GetRolesAsync(user);
var token = _jwt.GenerateJwtToken(user,roles);
var frontendCallback = $"{Request.Query["frontendCallback"]}?token={token}";

View File

@ -0,0 +1,240 @@
using AGSS.Models.DTOs;
using AGSS.Models.Entities;
using AGSS.Models.Template;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace AGSS.Controllers.Admin;
/// <summary>
/// 控制器类,用于管理角色相关的操作,包括添加角色、分配角色给用户以及通过角色查询用户。
/// 该控制器仅限具有"Admin"角色的用户访问。
/// </summary>
[Authorize(Roles = "Admin")]
[Route("api/v1/[controller]/[action]")]
public class AdminRoleControllers:ControllerBase
{
/// <summary>
/// 角色管理器,用于处理角色相关的操作,如创建、查询等。
/// 此角色管理器实例主要用于与RoleModel类型的实体进行交互
/// 支持添加新角色、为用户分配角色等功能。
/// </summary>
private readonly RoleManager<RoleModel> _roleManager;
/// <summary>
/// 用户管理器实例,用于处理用户相关的操作如添加角色、查询用户等。
/// 此实例通过依赖注入的方式在构造函数中初始化,并在整个控制器生命周期内可用。
/// </summary>
private readonly UserManager<UserModel> _userManager; // Assuming UserModel is the type of user
/// <summary>
/// 管理员角色控制器,用于处理与角色相关的操作,如添加角色、分配角色给用户以及通过角色查询用户。
/// 该控制器下的所有方法都需要管理员权限才能访问。
/// </summary>
public AdminRoleControllers(RoleManager<RoleModel> roleManager, UserManager<UserModel> userManager)
{
_roleManager = roleManager;
_userManager = userManager;
}
/// <summary>
/// 添加新角色
/// </summary>
/// <param name="role">要添加的角色信息</param>
/// <returns>返回操作结果,包含状态码、消息和数据</returns>
[HttpPost]
public async Task<IActionResult> AddRole([FromBody] RoleModel role)
{
if (role == null || string.IsNullOrWhiteSpace(role.Name))
{
return Ok(new ReturnTemplate(400,"创建失败,请提供名字",""));
}
var result = await _roleManager.CreateAsync(role);
if (result.Succeeded)
{
return Ok(new ReturnTemplate(200,"创建成功",role));
}
else
{
return Ok(new ReturnTemplate(StatusCodes.Status500InternalServerError,"创建失败","Failed to create role: " + string.Join(", ", result.Errors.Select(e => e.Description))));
}
}
/// <summary>
/// 为指定用户分配角色
/// </summary>
/// <param name="userId">用户的唯一标识符</param>
/// <param name="roleName">要分配的角色名称</param>
/// <returns>返回一个包含操作结果的ReturnTemplate对象其中Code表示状态码Msg表示消息Data表示附加数据如果有的话</returns>
[HttpPost]
public async Task<IActionResult> EndowRole(string userId, string roleName)
{
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
{
return Ok(new ReturnTemplate(400, "用户不存在", ""));
}
var role = await _roleManager.FindByNameAsync(roleName);
if (role == null)
{
return Ok(new ReturnTemplate(400, "角色不存在", ""));
}
var result = await _userManager.AddToRoleAsync(user, role.Name);
if (result.Succeeded)
{
return Ok(new ReturnTemplate(200, "角色分配成功", user));
}
else
{
return Ok(new ReturnTemplate(StatusCodes.Status500InternalServerError, "角色分配失败", "Failed to endow role: " + string.Join(", ", result.Errors.Select(e => e.Description))));
}
}
/// <summary>
/// 删除指定用户。
/// </summary>
/// <param name="userId">要删除的用户的唯一标识符。</param>
/// <returns>返回操作结果包含状态码、消息和数据。如果删除成功则返回200状态码如果用户ID为空或未找到指定用户则分别返回400或404状态码若删除过程中出现错误则返回500状态码并附带错误信息。</returns>
[HttpPost]
public async Task<IActionResult> DelUser(string userId)
{
if (string.IsNullOrWhiteSpace(userId))
{
return Ok(new ReturnTemplate(400, "你填写的用户ID是空的~", null));
}
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
{
return Ok(new ReturnTemplate(404, "未找到指定用户哦·~", null));
}
// 删除用户
var result = await _userManager.DeleteAsync(user);
if (result.Succeeded)
{
return Ok(new ReturnTemplate(200, "用户删除成功,不要留念这个用户哦~", null));
}
else
{
return StatusCode(500, new ReturnTemplate(500, "发生了一些不可预料的错误555", result.Errors));
}
}
[HttpPost]
public async Task<IActionResult> SetMenu([FromBody]MenuRequest request)
{
if (string.IsNullOrWhiteSpace(request.Id) || string.IsNullOrWhiteSpace(request.MenuName))
{
return Ok(new ReturnTemplate(400, "请求参数无效(有的参数是空的哦~", ""));
}
var user=await _userManager.FindByIdAsync(request.Id);
if (user==null)
{
return Ok(new ReturnTemplate(404, "Sorry你输入的用户我们找不到", ""));
}
user.MenuCode = request.MenuCode;
user.MenuName = request.MenuName;
var result= await _userManager.UpdateAsync(user);
if (result.Succeeded)
{
return Ok(new ReturnTemplate(200, "配置成功啦!", ""));
}
else
{
return StatusCode(500, new ReturnTemplate(500, "删除用户时发生错误", result.Errors));
}
}
/// <summary>
/// 通过角色查询用户,支持分页
/// </summary>
/// <param name="request">包含角色名称、页码和每页大小的请求对象</param>
/// <returns>返回包含总用户数和当前页用户的响应对象</returns>
[HttpPost]
public async Task<IActionResult> SearchUserFromRole([FromBody] SearchUserFromRoleRequest request)
{
if (string.IsNullOrWhiteSpace(request.RoleName))
{
return Ok(new ReturnTemplate(400, "角色名称不能为空", null));
}
var role = await _roleManager.FindByNameAsync(request.RoleName);
if (role == null)
{
return Ok(new ReturnTemplate(400, "角色不存在", null));
}
var usersInRole = await _userManager.GetUsersInRoleAsync(role.Name);
var totalUsers = usersInRole.Count;
var pagedUsers = usersInRole
.Skip((request.Page - 1) * request.PageSize)
.Take(request.PageSize)
.ToList();
var response = new SearchUserFromRoleResponse
{
TotalCount = totalUsers,
Users = pagedUsers
};
return Ok(new ReturnTemplate(200, "查询成功", response));
}
/// <summary>
/// 用于通过角色名称查询用户列表的请求模型。支持分页功能。
/// </summary>
public class SearchUserFromRoleRequest
{
/// <summary>
/// 表示角色的名称。此属性用于指定或获取与用户管理相关的角色名称。
/// 在进行角色分配、查询等操作时,需要提供正确的角色名称以确保操作的成功执行。
/// </summary>
public string RoleName { get; set; }
/// <summary>
/// 表示当前请求的页码默认为1。用于分页查询用户时指定从哪一页开始获取数据。
/// </summary>
public int Page { get; set; } = 1;
/// <summary>
/// 每页显示的用户数量。默认值为10。
/// 该属性用于分页查询中指定每一页应包含的用户条目数。
/// </summary>
public int PageSize { get; set; } = 10;
}
/// <summary>
/// 表示通过角色查询用户后返回的响应数据。
/// 该类用于封装查询结果,包括总用户数和分页后的用户列表。
/// </summary>
public class SearchUserFromRoleResponse
{
/// <summary>
/// 表示属于特定角色的用户总数。
/// </summary>
/// <remarks>此属性用于分页查询中,返回匹配给定角色名称的所有用户的数量。</remarks>
public int TotalCount { get; set; }
/// <summary>
/// 表示属于特定角色的用户列表。该属性用于存储和返回在给定角色下的所有用户。
/// </summary>
/// <remarks>此列表通常作为查询结果的一部分,例如通过角色名搜索用户时返回的数据。</remarks>
public List<UserModel> Users { get; set; }
}
}

View File

@ -1,3 +1,4 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using AGSS.Models.Entities;
using AGSS.Models.Template;
@ -7,25 +8,38 @@ using Microsoft.AspNetCore.Mvc;
namespace AGSS.Controllers.User;
/// <summary>
/// 用户控制器提供与用户相关的API接口。
/// </summary>
/// <remarks>此控制器需要授权才能访问其方法。</remarks>
[Authorize]
[Route("api/v1/[controller]")]
[Route("api/v1/[controller]/[action]")]
public class UserControllers:ControllerBase
{
{
/// <summary>
/// 用户服务实例,用于执行与用户相关的操作。
/// 该服务提供了一系列方法来处理用户的查询和更新等操作,
/// 包括但不限于获取用户详细信息、修改用户资料等功能。
/// </summary>
private readonly UserService _userService;
/// <summary>
/// 用户控制器提供用户相关操作的API接口。
/// </summary>
public UserControllers(UserService userService, UserManager<UserModel> userManager)
{
_userService = userService;
}
/// <summary>
/// 获取当前登录用户的个人信息。
/// </summary>
/// <returns>返回一个包含状态码、消息和用户信息的ReturnTemplate对象。如果成功状态码为200如果失败状态码为500。</returns>
[HttpGet]
public async Task<IActionResult> My()
{
string userId = this.User.FindFirst(ClaimTypes.NameIdentifier)!.Value;
string userId = this.User.FindFirst(JwtRegisteredClaimNames.Sub)!.Value;
if (string.IsNullOrEmpty(userId))
{
return Ok(new ReturnTemplate(500,"获取用户失败JWT解析错误",null));

View File

@ -4,11 +4,26 @@ using Microsoft.EntityFrameworkCore;
namespace AGSS.DbSet
{
public class ApplicationDbContext : IdentityDbContext<UserModel>
public class ApplicationDbContext : IdentityDbContext<UserModel,RoleModel,string>
{
public override DbSet<UserModel> Users { get; set; }
public override DbSet<RoleModel> Roles { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// 在这里添加额外的配置,如果需要的话
// 例如:
// modelBuilder.Entity<UserModel>().ToTable("CustomUsers");
// modelBuilder.Entity<RoleModel>().ToTable("CustomRoles");
}
}
}

View File

@ -1,53 +0,0 @@
// <auto-generated />
using System;
using AGSS.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace AGSS.Migrations
{
[DbContext(typeof(DBContext))]
[Migration("20250702100149_Initial")]
partial class Initial
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.6")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("AGSS.Models.Entities.UserModel", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("AuthId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("UserModels");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,36 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace AGSS.Migrations
{
/// <inheritdoc />
public partial class Initial : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "UserModels",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
AuthId = table.Column<string>(type: "text", nullable: false),
Email = table.Column<string>(type: "text", nullable: false),
Password = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_UserModels", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "UserModels");
}
}
}

View File

@ -1,45 +0,0 @@
// <auto-generated />
using System;
using AGSS.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace AGSS.Migrations
{
[DbContext(typeof(DBContext))]
[Migration("20250702110815_usernew")]
partial class usernew
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.6")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("AGSS.Models.Entities.UserModel", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("AuthId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("UserModels");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,40 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace AGSS.Migrations
{
/// <inheritdoc />
public partial class usernew : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Email",
table: "UserModels");
migrationBuilder.DropColumn(
name: "Password",
table: "UserModels");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Email",
table: "UserModels",
type: "text",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Password",
table: "UserModels",
type: "text",
nullable: false,
defaultValue: "");
}
}
}

View File

@ -1,70 +0,0 @@
// <auto-generated />
using System;
using AGSS.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace AGSS.Migrations
{
[DbContext(typeof(DBContext))]
[Migration("20250705081221_newuser")]
partial class newuser
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.6")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("AGSS.Models.Entities.UserModel", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("AuthId")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Birthday")
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.Property<string>("Config")
.HasMaxLength(200)
.HasColumnType("character varying(200)");
b.Property<string>("Description")
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<string>("JobCode")
.HasMaxLength(10)
.HasColumnType("character varying(10)");
b.Property<string>("JobName")
.HasMaxLength(10)
.HasColumnType("character varying(10)");
b.Property<string>("Sex")
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.HasKey("Id");
b.ToTable("UserModels");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,102 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace AGSS.Migrations
{
/// <inheritdoc />
public partial class newuser : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "AuthId",
table: "UserModels",
type: "character varying(50)",
maxLength: 50,
nullable: false,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AddColumn<string>(
name: "Birthday",
table: "UserModels",
type: "character varying(20)",
maxLength: 20,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Config",
table: "UserModels",
type: "character varying(200)",
maxLength: 200,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Description",
table: "UserModels",
type: "character varying(100)",
maxLength: 100,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "JobCode",
table: "UserModels",
type: "character varying(10)",
maxLength: 10,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "JobName",
table: "UserModels",
type: "character varying(10)",
maxLength: 10,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Sex",
table: "UserModels",
type: "character varying(20)",
maxLength: 20,
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Birthday",
table: "UserModels");
migrationBuilder.DropColumn(
name: "Config",
table: "UserModels");
migrationBuilder.DropColumn(
name: "Description",
table: "UserModels");
migrationBuilder.DropColumn(
name: "JobCode",
table: "UserModels");
migrationBuilder.DropColumn(
name: "JobName",
table: "UserModels");
migrationBuilder.DropColumn(
name: "Sex",
table: "UserModels");
migrationBuilder.AlterColumn<string>(
name: "AuthId",
table: "UserModels",
type: "text",
nullable: false,
oldClrType: typeof(string),
oldType: "character varying(50)",
oldMaxLength: 50);
}
}
}

View File

@ -1,300 +0,0 @@
// <auto-generated />
using System;
using AGSS.DbSet;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace AGSS.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20250708111442_user")]
partial class user
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.6")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("AGSS.Models.Entities.UserModel", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("Birthday")
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Config")
.HasMaxLength(200)
.HasColumnType("character varying(200)");
b.Property<string>("Description")
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<string>("JobCode")
.HasMaxLength(10)
.HasColumnType("character varying(10)");
b.Property<string>("JobName")
.HasMaxLength(10)
.HasColumnType("character varying(10)");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<string>("Sex")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("ProviderKey")
.HasColumnType("text");
b.Property<string>("ProviderDisplayName")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("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", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("AGSS.Models.Entities.UserModel", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("AGSS.Models.Entities.UserModel", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("AGSS.Models.Entities.UserModel", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("AGSS.Models.Entities.UserModel", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}

View File

@ -1,229 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace AGSS.Migrations
{
/// <inheritdoc />
public partial class user : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(type: "character varying(256)", 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<string>(type: "text", nullable: false),
Sex = table.Column<string>(type: "text", nullable: true),
Description = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
Config = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
JobCode = table.Column<string>(type: "character varying(10)", maxLength: 10, nullable: true),
JobName = table.Column<string>(type: "character varying(10)", maxLength: 10, nullable: true),
Birthday = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: true),
UserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
Email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(type: "boolean", 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: "boolean", nullable: false),
TwoFactorEnabled = table.Column<bool>(type: "boolean", nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
LockoutEnabled = table.Column<bool>(type: "boolean", 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("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
RoleId = table.Column<string>(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("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
UserId = table.Column<string>(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<string>(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<string>(type: "text", nullable: false),
RoleId = table.Column<string>(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<string>(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);
}
/// <inheritdoc />
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");
}
}
}

View File

@ -22,6 +22,32 @@ namespace AGSS.Migrations
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("AGSS.Models.Entities.RoleModel", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("AGSS.Models.Entities.UserModel", b =>
{
b.Property<string>("Id")
@ -67,6 +93,14 @@ namespace AGSS.Migrations
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("MenuCode")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("MenuName")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
@ -109,32 +143,6 @@ namespace AGSS.Migrations
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
@ -243,7 +251,7 @@ namespace AGSS.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
b.HasOne("AGSS.Models.Entities.RoleModel", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
@ -270,7 +278,7 @@ namespace AGSS.Migrations
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
b.HasOne("AGSS.Models.Entities.RoleModel", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)

View File

@ -1,67 +0,0 @@
// <auto-generated />
using System;
using AGSS.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace AGSS.Migrations
{
[DbContext(typeof(DBContext))]
partial class DBContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.6")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("AGSS.Models.Entities.UserModel", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("AuthId")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Birthday")
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.Property<string>("Config")
.HasMaxLength(200)
.HasColumnType("character varying(200)");
b.Property<string>("Description")
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<string>("JobCode")
.HasMaxLength(10)
.HasColumnType("character varying(10)");
b.Property<string>("JobName")
.HasMaxLength(10)
.HasColumnType("character varying(10)");
b.Property<string>("Sex")
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.HasKey("Id");
b.ToTable("UserModels");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,8 @@
namespace AGSS.Models.DTOs;
public struct MenuRequest
{
public string Id { get; set; }
public string MenuName { get; set; }
public string? MenuCode { get; set; }
}

View File

@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Identity;
namespace AGSS.Models.Entities;
public class UserModel:IdentityUser
public class UserModel:IdentityUser<string>
{
public string? Sex { get; set; }
@ -17,5 +17,14 @@ public class UserModel:IdentityUser
public string? JobName { get; set; }
[MaxLength(20)]
public string? Birthday { get; set; }
[MaxLength(500)]
public string? MenuCode { get; set; }
[MaxLength(500)]
public string? MenuName { get; set; }
}
public class RoleModel : IdentityRole<string>
{
}

View File

@ -33,7 +33,7 @@ builder.Services.AddDbContext<ApplicationDbContext>(opt =>
opt.UseNpgsql(builder.Configuration.GetConnectionString("DBContext")));
// Identity 配置
builder.Services.AddIdentity<UserModel, IdentityRole>()
builder.Services.AddIdentity<UserModel, RoleModel>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders()
.AddDefaultUI();

View File

@ -15,28 +15,30 @@ public class Jwt
_configuration = configuration;
}
public string GenerateJwtToken(UserModel user)
public string BuildToken(IEnumerable<Claim> claims)
{
var claims = new[]
DateTime expires = DateTime.Now.AddDays(int.Parse(_configuration["Jwt:ExpireMinutes"]));
byte[] keyBytes = Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]);
var secKey = new SymmetricSecurityKey(keyBytes);
var credentials = new SigningCredentials(secKey,
SecurityAlgorithms.HmacSha256Signature);
var tokenDescriptor = new JwtSecurityToken(expires: expires,
signingCredentials: credentials, claims: claims);
return new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);
}
public string GenerateJwtToken(UserModel user,IList<string> roles)
{
var claims = new List<Claim>();
claims.Add(new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()));
claims.Add(new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()));
// var roles = await user.GetRolesAsync(user);
foreach (string role in roles)
{
new Claim(JwtRegisteredClaimNames.Sub, user.Email),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(ClaimTypes.NameIdentifier, user.Id)
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(
_configuration["Jwt:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var expires = DateTime.Now.AddMinutes(
Convert.ToDouble(_configuration["Jwt:ExpireMinutes"]));
var token = new JwtSecurityToken(
issuer: _configuration["Jwt:Issuer"],
audience: _configuration["Jwt:Audience"],
claims: claims,
expires: expires,
signingCredentials: creds
);
return new JwtSecurityTokenHandler().WriteToken(token);
claims.Add(new Claim(ClaimTypes.Role, role));
}
string jwtToken = BuildToken(claims);
return jwtToken;
}
}

View File

@ -15,6 +15,7 @@
},
"AllowedHosts": "*",
"Jwt": {
"ExpireMinutes": "4",
"Issuer": "https://api.zeronode.cn/api",
"Audience": "https://api.zeronode.cn/api",
"Key": "7wU9bdVfBsX3jITh0w4bgE6fkvLk8pIcZRSUw6r8HQUnXfslYxlx4c4E0ZAIw4Ak"

View File

@ -9,12 +9,13 @@
"Microsoft": {
"ClientId": "1f0c6ff3-a458-466b-ac92-decaa1d8b132",
"ClientSecret": "TdY8Q~Tsm1nPl6RZMbDGmVsXblJo1xdDKCoH9ayk"
}
},
},
"AllowedHosts": "*",
"Jwt": {
"ExpireMinutes": "4",
"Issuer": "https://api.zeronode.cn/api",
"Audience": "https://api.zeronode.cn/api",
"Key": "7wU9bdVfBsX3jITh0w4bgE6fkvLk8pIcZRSUw6r8HQUnXfslYxlx4c4E0ZAIw4Ak"

View File

@ -0,0 +1 @@
<input asp-for="Input.Email" type="email" class="form-control validate form-outline" autocomplete="username" aria-required="true" placeholder="name@example.com" />

View File

@ -21,6 +21,8 @@ CREATE TABLE "AspNetUsers" (
"JobCode" character varying(10),
"JobName" character varying(10),
"Birthday" character varying(20),
"MenuCode" character varying(500),
"MenuName" character varying(500),
"UserName" character varying(256),
"NormalizedUserName" character varying(256),
"Email" character varying(256),
@ -97,7 +99,7 @@ CREATE INDEX "EmailIndex" ON "AspNetUsers" ("NormalizedEmail");
CREATE UNIQUE INDEX "UserNameIndex" ON "AspNetUsers" ("NormalizedUserName");
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20250708111442_user', '9.0.6');
VALUES ('20250709144855_Initial', '9.0.6');
COMMIT;