I always shake in horror when it comes to implementing my own user management in an application.
There is so much you can get wrong. And so much we need to reinvent! What about implementing...
- Two Factor Authentication?
- Registration?
- Registration Confirmations?
- Safe Password Hashing?
- Roles and Claims?
Time is money. And time is often a very limiting factor in projects.
That's why I am using the ASP.NET Core Identity package to get a very good starting point for user management.
What's the problem?
The Database Model generated by ASP.NET Core Identity has table and column names, that nicely fit into the SQL
Server Naming Conventions. But in database systems like PostgreSQL you really don't want to quote tables like
myschema."AspNetUserLogins"
when being used in queries.
PostgreSQL is among the databases to use SnakeCase names for entities, so a table like myschema."AspNetUserLogins"
would become something along the lines of myschema.asp_net_user_logins"
. Plus you want the properties like
"Id"
written in snake case like id
.
A solution for PostgreSQL
Microsoft has quite an extensive page on customizing the Identity model:
And here is how I would rename tables and columns of the identity model for Npgsql.
Plus move it into a different schema called myschema
:
// ...
using Npgsql.NameTranslation;
// ...
namespace Database.Context
{
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Move Identity to "myschema" Schema:
modelBuilder.Entity<ApplicationUser>().ToTable("application_user", "myschema");
modelBuilder.Entity<IdentityRole>().ToTable("role", "myschema");
modelBuilder.Entity<IdentityUserToken<string>>().ToTable("user_token", "myschema");
modelBuilder.Entity<IdentityUserRole<string>>().ToTable("user_role", "myschema");
modelBuilder.Entity<IdentityRoleClaim<string>>().ToTable("role_claim", "myschema");
modelBuilder.Entity<IdentityUserClaim<string>>().ToTable("user_claim", "myschema");
modelBuilder.Entity<IdentityUserLogin<string>>().ToTable("user_login", "myschema");
// Apply Snake Case Names for Properties:
ApplySnakeCaseNames(modelBuilder);
}
private void ApplySnakeCaseNames(ModelBuilder modelBuilder)
{
var mapper = new NpgsqlSnakeCaseNameTranslator();
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
foreach (var property in entity.GetProperties())
{
var npgsqlColumnName = mapper.TranslateMemberName(property.GetColumnName());
property.SetColumnName(npgsqlColumnName);
}
}
}
// ... More Code
}
}
Conclusion
There are some entities missing, such as Foreign Key and Constraint names.
If you have a more complete solution to share, please let me know and the solution above could be extended.