在身份模块上播种初始用户而不进行双重播种
Seeding initial user on Identity module without double-seeding
我正在尝试使用 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
的情况下更改播种上下文?如果这做不到...有没有办法让我 "unregister" 所有 IDataSeeder
都在我的之前,所以只有我的被执行?
这个特定问题的解决方案(虽然我希望找到更多 "general" 解决方案)是更改实际贡献者。在您的域模块(或您认为合适的任何地方:您的迁移器或其他任何地方),只需执行:
// 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
实现(使用相同的方法,或更简单的 Services.Replace
,你可以使用它,因为 IIdentityDataSeeder
) 应该只有一个实现,并从默认的实现中复制你自己的,更改搜索到的用户名。
目前,替换模块上的服务似乎是可行的方法。也许在未来的版本中可能会直接拦截其他模块的初始化阶段,但我暂时还没有看到。
我正在尝试使用 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
的情况下更改播种上下文?如果这做不到...有没有办法让我 "unregister" 所有 IDataSeeder
都在我的之前,所以只有我的被执行?
这个特定问题的解决方案(虽然我希望找到更多 "general" 解决方案)是更改实际贡献者。在您的域模块(或您认为合适的任何地方:您的迁移器或其他任何地方),只需执行:
// 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
实现(使用相同的方法,或更简单的 Services.Replace
,你可以使用它,因为 IIdentityDataSeeder
) 应该只有一个实现,并从默认的实现中复制你自己的,更改搜索到的用户名。
目前,替换模块上的服务似乎是可行的方法。也许在未来的版本中可能会直接拦截其他模块的初始化阶段,但我暂时还没有看到。