using Dpz.Core.Public.ViewModel;
using Microsoft.AspNetCore.Identity;

namespace Dpz.Core.Web.Jobs.Security;

public class VmUserInfoStore : IUserStore<VmUserInfo>
{
    public void Dispose() { }

    public Task<string> GetUserIdAsync(VmUserInfo user, CancellationToken cancellationToken)
    {
        return Task.FromResult(user.Id);
    }

    public Task<string?> GetUserNameAsync(VmUserInfo user, CancellationToken cancellationToken)
    {
        return Task.FromResult<string?>(user.Id);
    }

    public Task SetUserNameAsync(
        VmUserInfo user,
        string? userName,
        CancellationToken cancellationToken
    )
    {
        throw new NotImplementedException();
    }

    public Task<string?> GetNormalizedUserNameAsync(
        VmUserInfo user,
        CancellationToken cancellationToken
    )
    {
        return Task.FromResult<string?>(user.Id.ToUpper());
    }

    public Task SetNormalizedUserNameAsync(
        VmUserInfo user,
        string? normalizedName,
        CancellationToken cancellationToken
    )
    {
        throw new NotImplementedException();
    }

    public Task<IdentityResult> CreateAsync(VmUserInfo user, CancellationToken cancellationToken)
    {
        throw new NotImplementedException();
    }

    public Task<IdentityResult> UpdateAsync(VmUserInfo user, CancellationToken cancellationToken)
    {
        throw new NotImplementedException();
    }

    public Task<IdentityResult> DeleteAsync(VmUserInfo user, CancellationToken cancellationToken)
    {
        throw new NotImplementedException();
    }

    public Task<VmUserInfo?> FindByIdAsync(string userId, CancellationToken cancellationToken)
    {
        throw new NotImplementedException();
    }

    public Task<VmUserInfo?> FindByNameAsync(
        string normalizedUserName,
        CancellationToken cancellationToken
    )
    {
        throw new NotImplementedException();
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

下面我把这段代码的作用和问题分块说明,便于理解和后续改进。

总体作用(高层次)

  • 这个类 VmUserInfoStore 实现了 ASP.NET Core Identity 的 IUserStore 接口。IUserStore 是用户持久化存取的抽象,负责 Create/Update/Delete/Find 等操作,供 UserManager 使用。
  • 也就是说,这个类应该负责把 VmUserInfo(位于 Dpz.Core.Public.ViewModel)对象保存、查询和更新(例如从数据库、内存或其他存储)。

具体方法说明(逐个)

  • Dispose()

    • 目前是空实现:不释放任何资源。若持有 DB 连接等可释放资源,应在这里释放。
  • GetUserIdAsync(VmUserInfo user, CancellationToken cancellationToken)

    • 返回 user.Id(以 Task 包装)。这是正确的:UserManager 会用这个返回值作为用户的 Id。
  • GetUserNameAsync(VmUserInfo user, CancellationToken cancellationToken)

    • 当前实现返回 user.Id —— 这通常是错误的。应返回用户可显示的用户名(通常是 user.UserName 或类似属性),而不是 Id。
  • SetUserNameAsync(VmUserInfo user, string? userName, CancellationToken cancellationToken)

    • 抛出 NotImplementedException,尚未实现设置用户名的逻辑。UserManager 在某些场景会调用它来更改用户名。
  • GetNormalizedUserNameAsync(VmUserInfo user, CancellationToken cancellationToken)

    • 当前实现返回 user.Id.ToUpper() —— 这也不合理。NormalizedUserName 应该是对用户名(如 UserName)做标准化(通常 ToUpperInvariant 或 culture-insensitive 处理),用于不区分大小写的查找。用 Id 来做标准化会导致查找逻辑紊乱。
  • SetNormalizedUserNameAsync(VmUserInfo user, string? normalizedName, CancellationToken cancellationToken)

    • 抛出 NotImplementedException,尚未实现。
  • CreateAsync/UpdateAsync/DeleteAsync

    • 都抛出 NotImplementedException,表示没有实现持久化增删改。UserManager 依赖这些方法把用户写入存储(数据库、表等)。
  • FindByIdAsync(string userId, CancellationToken cancellationToken)

    • 抛出 NotImplementedException。应实现按 Id 查找并返回 VmUserInfo 对象。
  • FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)

    • 抛出 NotImplementedException。应实现按标准化后的用户名查找用户(注意:参数传入的已是 normalizedUserName)。

其他注意事项

  • 目前代码对 cancellationToken 都未使用(也是常见的简化)。真正实现时应尊重取消令牌,例如在异步 DB 操作中传递它。
  • 返回 Task.FromResult 是同步包装异步的短路实现,适合简单返回值。对真正的异步 IO,应使用 async/await 并返回真实异步任务。
  • 若要支持完整的身份验证流程,通常还需实现其他接口,例如 IUserPasswordStore(存取密码哈希)、IUserEmailStore(邮箱)、IUserRoleStore 等,或使用更完整的存储实现。

存在的问题(总结)

  • 将 Id 用作 UserName 和 NormalizedUserName 是不正确或至少可疑的实现(可能是占位或临时实现)。
  • 大量方法未实现,因此当前类不能在真实应用中用于用户管理,会在运行时抛出 NotImplementedException。
  • 未处理取消、并发和错误返回(Create/Update/Delete 应返回 IdentityResult.Success/Failed)。

建议和下一步

  • 正确区分 Id、UserName、NormalizedUserName,使用 VmUserInfo 的相应属性(如果没有,考虑在 ViewModel 中加入 UserName/NormalizedUserName)。
  • 实现 CreateAsync/UpdateAsync/DeleteAsync/FindByIdAsync/FindByNameAsync,通常是访问数据库(例如通过 EF Core)或内存集合。
  • 返回合适的 IdentityResult(例如 IdentityResult.Success 或 IdentityResult.Failed(...))。
  • 考虑实现 IUserPasswordStore(若要支持密码)或其它需要的接口。
  • 在实现中传递并检查 cancellationToken,以及处理并发(例如 ConcurrencyStamp)。

示例(简短示例,说明 SetUserName 与 GetUserName 的修正思路):

  • GetUserNameAsync 应返回 user.UserName(而不是 user.Id)。
  • SetUserNameAsync 应该把 user.UserName = userName 并返回 Task.CompletedTask。

如果你需要,我可以:

  • 基于某种存储(例如 EF Core、Dapper 或内存)给出完整实现样例;
  • 或者帮你改正上述明显错误并补全必须的方法。
评论加载中...