pedropaf / saas-ecom

Subscription support for ASP.NET MVC 5 apps using Stripe, including out-of-the-box view helpers. Available via NuGET
http://www.saasecom.org
Apache License 2.0
101 stars 41 forks source link

Roles changed #12

Open chriship opened 9 years ago

chriship commented 9 years ago

Hi,

I have just implemented saas-scom into my project. I was using roles to differentiate between different user roles but it seems to have broken this.

In my AspNetUserRoles table, I now have a SaasEcomUser_Id field which is used by SaasEcomUser to get the role.

In my code, I set the role when someone registers using the following code:

var roleStore = new RoleStore<IdentityRole>(context);
var roleManager = new RoleManager<IdentityRole>(roleStore);

var userStore = new UserStore<ApplicationUser>(context);
var userManager = new UserManager<ApplicationUser>(userStore);
userManager.AddToRole(user.Id, "Manager");

Now, This sets the UserId of AspNetUserRoles instead of the SaasEcomUser_Id and therefore my roles no longer get picked up when logging in.

Is there are way to set the SaasEcomUser_Id using my method above?

Thanks!

pedropaf commented 8 years ago

Hi @chriship, not sure if you managed to fix this already, I've been having a look and I found out why this is happening.

If you look at how ASP.NET Identity 2 works, your application user has to inherit from IdentityUser. This class uses generics so you can specify which class types you want to use as Primary Key, Login, Roles and Claims:

public class IdentityUser<TKey, TLogin, TRole, TClaim> : IUser<TKey>
    where TLogin : Microsoft.AspNet.Identity.EntityFramework.IdentityUserLogin<TKey>
    where TRole : Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole<TKey>
    where TClaim : Microsoft.AspNet.Identity.EntityFramework.IdentityUserClaim<TKey>
{ ... }

At the moment the library SaasEcom.Core doesn't have the user SaasEcomUser implemented as a generic to map all those fields to the parent IdentityUser. It should be something similar to:

public abstract class SaasEcomUser : SaasEcomUser<string, IdentityUserRole>
{
}

public abstract class SaasEcomUser<TKey,TRole> : IdentityUser<TKey, IdentityUserLogin<TKey>,    TRole, IdentityUserClaim<TKey>> 
    where TRole : Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole<TKey>
{ ... }

If you want to implement it and create a pull request I'm happy to merge it.

Thanks, Pedro

chriship commented 8 years ago

Hi Pedro,

Thanks for the help. I had a look at implementing this but my generics knowledge is not up to scratch. Using your code above, I get an error on the GenerateUserIdentityAsync method:

The type 'Microsoft.AspNet.Identity.IUser<TKey>' cannot be used as type parameter 'TUser' in the 
generic type or method 'Microsoft.AspNet.Identity.UserManager<TUser>'. There is no implicit 
reference conversion from 'Microsoft.AspNet.Identity.IUser<TKey>' to 
'Microsoft.AspNet.Identity.IUser<string>'.

I had to change the SaasEcomUser parameter to include TKey and TRole:

public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<SaasEcomUser<TKey, TRole>> manager){...}

Any ideas what I am doing wrong here?