在身份模块上播种初始用户而无需双重播种

时间:2019-08-19 07:29:16

标签: c# asp.net-identity abp

我正在尝试使用ABP的身份模块,并为我的第一个(管理员)用户提供种子。

在身份模块种子提供者的源代码中,我看到以下内容:

public Task SeedAsync(DataSeedContext context)
{
    return _identityDataSeeder.SeedAsync(
        context["AdminEmail"] as string ?? "admin@abp.io",
        context["AdminPassword"] as string ?? "1q2w3E*",
        context.TenantId
    );
}

因此,在我的迁移器模块中,我添加了以下内容:

public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
    using (var scope = context.ServiceProvider.CreateScope())
    {
        var dataSeeder = scope.ServiceProvider.GetRequiredService<IDataSeeder>();
        var dsCtx = new DataSeedContext
        {
            ["AdminEmail"] = "my@admin-email", 
            ["AdminPassword"] = "my-admin-password"
        };
        AsyncHelper.RunSync(() => dataSeeder.SeedAsync(dsCtx));
    }
    base.OnApplicationInitialization(context);
}

这行得通...但是,可能还有另一个模块创建了一个数据播种器(更可能是在迁移器上实际执行的,但我找不到它),所以我所有的贡献者(也可能是模块贡献者) )执行两次(这是可以预期的)。

有什么方法可以更改种子上下文而无需实际运行IDataSeeder?并且如果无法完成......有什么方法可以“注销”我之前的所有IDataSeeder,以便仅执行我的操作?

1 个答案:

答案 0 :(得分:0)

这个特定问题的解决方案(尽管我希望找到一个更“通用”的解决方案)是改变实际的贡献者。在您的域模块上(或您认为合适的任何地方:您的迁移器或其他),只需:

// Remove the contributor for the module
context.Services.RemoveAll(t => t.ImplementationType == typeof(IdentityDataSeedContributor));
// Add my custom constributor
context.Services.AddTransient<IDataSeedContributor, MyCustomConstributor>();

其中贡献者的实现只是默认值的副本:

public class MyCustomConstributor : IDataSeedContributor
{
    private readonly IIdentityDataSeeder _identityDataSeeder;

    public IdentityDataSeedContributor(IIdentityDataSeeder identityDataSeeder)
    {
        _identityDataSeeder = identityDataSeeder;
    }

    public Task SeedAsync(DataSeedContext context)
    {
        return _identityDataSeeder.SeedAsync(
            context["AdminEmail"] as string ?? "my@admin-email",
            context["AdminPassword"] as string ?? "my-admin-password",
            context.TenantId
        );
    }
}

请注意,您仍然可以在此处获得用户名admin ...如果要更改用户名,也可以只替换IIdentityDataSeeder实现(使用相同的方法,或更简单的{{1 }},您可以使用它,因为只有Services.Replace的一种实现,并且可以从默认的实现中复制自己的实现,从而更改搜索到的用户名。

就目前而言,替换模块上的服务似乎是路要走。将来的版本中可能会存在直接拦截其他模块的初始化阶段的可能性,但目前为止我还没有看到。