visual validar usuarios usuario tipos privilegios permisos net mvc control contraseña con autenticación autenticacion asp c# asp.net entity-framework asp.net-mvc-4 asp.net-identity

c# - validar - Crear usuarios de herencia desde el usuario de identidad asp.net base



usuarios roles y permisos c# mvc (2)

Como otros también lo hacen, creo que este es un problema de diseño. Hay algunos enfoques alternativos, como:

  1. use roles para definir el "tipo de usuario" (un usuario puede ser el proveedor Y el cliente)
  2. hacer que las entidades de Supplier y Customer una relación, no una extensión del usuario

p.ej:

public class ApplicationUser : IdentityUser { public virtual Customer Customer { get; set; } public virtual Supplier Supplier { get; set; } } public class Customer { [Key] public int Id { get; set; } public virtual ApplicationUser User { get; set; } public string CustomerProperty { get; set; } } public class Supplier { [Key] public int Id { get; set; } public virtual ApplicationUser User { get; set; } public string SupplierProperty { get; set; } } public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public DbSet<Customer> Customers { get; set; } public DbSet<Supplier> Suppliers { get; set; } } public class ApplicationDbInitializer : DropCreateDatabaseAlways<ApplicationDbContext> { protected override void Seed(ApplicationDbContext context) { var userStore = new UserStore(context); var userManager = new UserManager(userStore); var roleManager = new RoleManager(roleStore); var user = userManager.FindByEmail("[email protected]"); if (user == null) { user = new ApplicationUser() { UserName = "[email protected]", Email = "[email protected]" Customer = new Customer() { CustomerProperty = "Additional Info" } }; userManager.Create(user, userPassword); roleManager.AddUserToRole("Customer"); } user = userManager.FindByEmail("[email protected]"); if (user == null) { user = new ApplicationUser() { UserName = "[email protected]", Email = "[email protected]", Supplier = new Supplier() { IBAN = "212323424342234", Relationship = "OK" } }; userManager.Create(user, userPassword); roleManager.AddUserToRole("Supplier"); } } }

y en tu lógica puedes hacer algo como:

if (User.IsInRole("Customer")) { // do something }

DESCARGO DE RESPONSABILIDAD : Este no es un ejemplo de "copiar y pegar" y debería darle una idea de un enfoque diferente.

Tengo un problema en el que me gustaría crear N, dos en el ejemplo, objetos de usuario (por ejemplo, Cliente y Proveedor) que son todos inherentes desde el objeto IdentityUser de asp.net. Estos objetos tienen datos adicionales muy diferentes además de los datos de IdentityUser. Me gustaría utilizar el usuario de IdentityUser, ya que esto me brinda una forma flexible de encargarme de la autenticación y la autorización.

Este ejemplo ha sido muy simplificado, pero debe proporcionar suficiente información sobre la imposibilidad de crear un usuario concreto (por ejemplo, Cliente del Proveedor). Parece que necesito usar el objeto UserManager ya que también se encarga de crear, por ejemplo, el hash de la contraseña y la información de seguridad adicional.

Me aparece el siguiente error:

{"Falló la conexión de una entidad de tipo ''Proveedor'' porque otra entidad del mismo tipo ya tiene el mismo valor de clave primaria. Esto puede suceder cuando se usa el método ''Adjuntar'' o se establece el estado de una entidad en ''Sin cambios'' o ''Modificado'' "si alguna entidad en el gráfico tiene valores clave conflictivos. Esto puede deberse a que algunas entidades son nuevas y aún no han recibido valores clave generados por la base de datos. En este caso, use el método ''Agregar'' o ''Agregado'' para seguir el gráfico y luego establecer el estado de las entidades no nuevas en ''Sin cambios'' o ''Modificado'' según corresponda. "}

Clases inherentes desde Identity User

public class Customer : IdentityUser { public string CustomerProperty { get; set; } } public class Supplier : IdentityUser { public string SupplierProperty { get; set; } }

Clase de contexto de base

public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext() : base("ApplicationDbContext") { Database.SetInitializer(new ApplicationDbInitializer()); } public DbSet<Customer> CustomerCollection { get; set; } public DbSet<Supplier> SupplierCollection { get; set; } }

Clase de siembra que arroja la excepción

public class ApplicationDbInitializer : DropCreateDatabaseAlways<ApplicationDbContext> { protected override void Seed(ApplicationDbContext context) { var userStore = new UserStore(context); var userManager = new UserManager(userStore); // Seed customer user which inherents from asp.net IdentityUser var user = userManager.FindByEmail("[email protected]"); if (user == null) { user = new User() { UserName = "[email protected]", Email = "[email protected]" }; userManager.Create(user, userPassword); var customerUser = new Customer() { Id = user.Id, CustomerProperty = "Additional Info" }; context.Entry(customerUser).State = EntityState.Modified; context.SaveChanges(); } // Seed supplier user which inherents from asp.net IdentityUser var user = userManager.FindByEmail("[email protected]"); if (user == null) { user = new User() { UserName = "[email protected]", Email = "[email protected]" }; userManager.Create(user, userPassword); var supplierUser = new Supplier() { Id = user.Id, IBAN = "212323424342234", Relationship = "OK" }; context.Entry(supplierUser).State = EntityState.Modified; context.SaveChanges(); } } }

**** ACTUALIZACIÓN ****

La siguiente solución funciona, pero todavía estoy luchando con dos problemas:

  1. Siempre me gustaría tener un tipo de usuario (por ejemplo, Cliente del Proveedor) asociado con IdentityUser. Pensé en usar una interfaz, pero esto no funciona.
  2. Si también agrego la referencia virtual hacia IdentityUser en los tipos de usuario obtengo un ''No se puede determinar el extremo principal de una asociación entre los tipos'' ApplicaitonUser ''y'' Supplier ''. El extremo principal de esta asociación debe configurarse explícitamente utilizando la relación API o anotaciones de datos con fluidez. excepción.

Clases

public class Customer { [Key] public int CustomerId { get;set; } public string CustomerProperty { get; set; } *public virtual User User { get; set; }* } public class Supplier { [Key] public int SupplierId { get;set; } public string SupplierProperty { get; set; } *public virtual User User { get; set; }* }

** Class IdentityUser (que funciona) **

public class User : IdentityUser { public virtual Supplier Supplier { get; set; } public virtual Customer Customer { get; set; } }

** Class IdentityUser (lo que me gustaría) **

public class User : IdentityUser { public virtual IConcreteUser ConcreteUser{ get; set; } }

Clase de contexto de base

public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext() : base("ApplicationDbContext") { Database.SetInitializer(new ApplicationDbInitializer()); } public DbSet<Customer> CustomerCollection { get; set; } public DbSet<Supplier> SupplierCollection { get; set; } }

** Clase de siembra **

public class ApplicationDbInitializer : DropCreateDatabaseAlways<ApplicationDbContext> { protected override void Seed(ApplicationDbContext context) { var userStore = new UserStore(context); var userManager = new UserManager(userStore); var roleManager = new RoleManager(roleStore); var user = userManager.FindByEmail("[email protected]"); if (user == null) { user = new ApplicationUser() { UserName = "[email protected]", Email = "[email protected]" Customer = new Customer() { CustomerProperty = "Additional Info" } }; userManager.Create(user, userPassword); roleManager.AddUserToRole("Customer"); } user = userManager.FindByEmail("[email protected]"); if (user == null) { user = new ApplicationUser() { UserName = "[email protected]", Email = "[email protected]", Supplier = new Supplier() { IBAN = "212323424342234", Relationship = "OK" } }; userManager.Create(user, userPassword); roleManager.AddUserToRole("Supplier"); } }

}


Acabo de resolver un problema similar. Creé una propiedad de navegación de tipo abstracto DomainUser en mi AppUser (que hereda de Identity User)

public class AppUser : IdentityUser { public DomainUser DomainUser { get; set; } }

DomainUser se ve así:

public abstract class DomainUser : IAggregateRoot { public Guid Id { get; set; } public AppUser IdentityUser { get; set; } }

Yo heredo de DomainUser en todos los tipos concretos de usuarios de dominio:

public class AdministrationUser : DomainUser { public string SomeAdministrationProperty { get; set; } } public class SupplierUser : DomainUser { public string SomeSupplierProperty { get; set; } } public class Customer : DomainUser { public string SomeCustomerProperty { get; set; } }

Y en DbContext en el método OnModelCreating, configuré Entity Framework para almacenar todas las entidades heredadas de DomainUser en tablas separadas (se llama Table for Concrete Type ). Y se configuró una relación de uno a uno entre IdentityUser y DomainUser:

modelBuilder.Entity<DomainUser>() .Map<AdministrationUser>(m => { m.MapInheritedProperties(); m.ToTable("AdministrationUsers"); }) .Map<SupplierUser>(m => { m.MapInheritedProperties(); m.ToTable("SupplierUsers"); }) .Map<Customer>(m => { m.MapInheritedProperties(); m.ToTable("Customers"); }); modelBuilder.Entity<DomainUser>() .HasRequired(domainUser => domainUser.IdentityUser) .WithRequiredPrincipal(groomUser => groomUser.DomainUser);

Este código agregó la columna "DomainUser_Id" a la tabla AspNetUsers y ahora puedo acceder a la propiedad de navegación IdentityUser en cada usuario de dominio y a la propiedad de navegación UserUser en AppUser.