Closed randeep80 closed 10 years ago
Hi @randeep80 the User.Identity
property is a Microsoft core interface of type IIdentity
, I cannot add a property to that interface. What are you looking to achieve? Was it something like the IdentityExtensions
methods? Currently the solution makes no attempt to save the Tenant Id as part of the claim.
The ApplicationUser class
derives from MultitenantIdentityUser
which has a TenantId
property.
Also, the MultitenantUserStore
also has a TenantId
property, you can see it being set here in the example project.
Could you please give me a hand here : How can I call the Mutlitenant class here?
public static int GetTenantID(this IIdentity identity)
{
if (identity == null)
throw new ArgumentNullException("identity");
var userStore = new MultitenantUserStore<ApplicationUser>(new ApplicationDbContext());
string stringTenantID = userStore.TenantId;
int tenantID;
if (string.IsNullOrWhiteSpace(stringTenantID) || !int.TryParse(stringTenantID, out tenantID))
{
return default(int);
}
return tenantID;
}
Also I'm planning to use this with MySQL database. Do you foresee any issue with that?
Hi @randeep80 looking at what you're attempting that wont work, MultitenantUserStore
has a TenantId
property to use it with one of the custom queries, it needs to be set by your implementation.
The IdentityExtensions
methods are there to provide simple access to the claim data, have a look at the source. As I said above:
Currently the solution makes no attempt to save the Tenant Id as part of the claim.
Maybe you're going about this the wrong way, presumably your system is multi-tenant in more than just user access, how are you differentiating tenants in other parts of your system?
Regarding using this with MySQL, I don't know how well Entity Framework works on MySql as I've never tried it, it appears Microsoft.AspNet.Identity.EntityFramework works on MySql, at least according to this blog. I'm not doing anything special with Entity Framework in adding the TenantId
columns, so it may work just fine.
Hi James, I'm using multi tenant on same database tables with a TenantID column in each table to associate the records. And currently we associate tenant id with a user as per your approach. I applied automatic filtering in EF, so that data is always filtered by logged in user TenantID. And certain times I need to manually pass TenantID back to database, for filtering, e.g. to stored procedures. So I need flexibility to access User Tenant ID across Model, Views and Controller. (Am now using HTTP Context to store the value)
Currently a user account can belong to only one tenant. But am trying to change the approach, where a user can belong to multiple tenants (will create a intermediary table for 1:N relationship). So if user belongs to multiple tenants; upon login we will prompt another page to select which tenant user want to access. And will store back this selected tenant in User table as default selection. Hence am able to retrieve back the current TenantID from your Multitenant Identity model.
Hi James, Appreciate if you can point me to a sample on how I can save and retrieve Tenant ID using custom implementation.
public static int TenantID(this IIdentity identity)
{
if (identity == null)
throw new ArgumentNullException("identity");
ApplicatonUserStore userStore = new ApplicatonUserStore(new ApplicationDbContext());
return userStore.TenantId;
}
Hi @randeep80 then I think you need to manually add the TenantId
as a claim upon sign-in/registration.
I've created a gist as an example. Use the SetTenantId()
extension upon successful sign-in, then use GetTenantId()
to get the TenantId
during authenticated requests.
Beyond that there's plenty of information on ASP.NET Identity and claims.
Hope that helps.
Thanks for above James, but I can't really retrieve back the value from GetTenantID functions - it always returns null. Anyway, I will explore more on that.
But I have another serious problem. I defaulted my tenantID as 1. And now if I manually change the value to anything but 1 in AspnetUser table, FindAsync will not return result.
var user = await UserManager.FindAsync(model.UserName, model.Password);
public UserManager<ApplicationUser, int> UserManager { get; private set; }
public AccountController()
: this(new UserManager<ApplicationUser, int>(new ApplicatonUserStore(new ApplicationDbContext()) { TenantId = 1 }))
{
}
Hi @randeep80 That's by design, it's frankly why I created this solution in the first place.
Users are unique (by user name) within a Tenant, but not across tenants. For instance, the user randeep80 under tenant 1 is a different user than one with the same user name under tenant 2. Therefore users created under tenant 1 do not exist under tenant 2 unless recreated, and still then they are different users.
Also, if you do have "another serious problem" again, can raise a separate issue?
Unless you object I'm going to close this issue.
I downloaded the sample solution and played around with it. I notice that there is TenantID column created in User table. But how can I refer this in my solution? I can't find any reference; e.g. User.Identity.TenantID? Could you advise method of retrieving it in Model, Views or Controllers?