Get current user logged in in Custom Authentication MVC 4 - sql

I have created a simple login table without simplemembership because in my project i don't need to have a register, the users need to be created automatically in the database. (Made following this tutorial).
I have a model Login:
public class Login
{
public virtual int UserId { get; set; }
public virtual string Username { get; set; }
public virtual string Password { get; set; }
public virtual List<Enrollment> Enrollments { get; set; }
}
and Enrollments:
public class Enrollment
{
public virtual int EnrollmentId { get; set; }
public virtual string Name { get; set; }
public virtual List<Login> Users { get; set; }
}
And i have a table Enrollment_Login because of the many-to-many relationship.
I need to create a view where i show a list of enrollments that the user logged in is "registered".
I have this query:
var query= from name in db.Enrollments
where name.Logins.Any(c=>c.LoginId==??)
select name;
If this query is right, how can i get the current user logged in?

You can't get the LoginId (which I think is a foreign key of your Login entity in Enrollement entity)
When user is authenticated the the name of that user is stored in this.User.Identity.Name if you're in your action method.
The name in your case is the UserName property in Login entity.
So you must write the following code :
var currentLogin = db.Logins.Single(u => u.UserName = this.User.Identity.Name);
var query= from name in db.Enrollments
where name.Logins.Any(c=>c.LoginId==currentLogin.Id)
select name;
Or in one query:
var query= from enrollement in db.Enrollments
join login in db.Logins on enrollement.LoginId equals login.UserId
where login.UserName == this.User.Identity.Name
select enrollement;

Related

Edit Account user and role .Net core Identity

I am using .Net Core Identity 5, I did add Role for the user when registering the account. I want when I Edit the user information of that account, I can change their Role in the system.
I am working in Repo, how can I work with it most effectively?
Viewmodel
public class UserRoleViewModel
{
public string UserId { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public string Role { get; set; }
}

How to Extend Roles for Multiple Locations / Sites with Asp.Net Core Identity

I have an API that is used in a multi-site/multi-location environment. At the moment, each user has roles defined but is locked to only one location. I am needing to extend this out to where a user may have admin roles for one location and then may be standard user at another location. They may also have no roles/no access to a bunch of locations.
Here is what I am working with right now (asp.net core 2.2):
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int? LocationId { get; set; }
public virtual Locations Locations { get; set; }
public int? ContactPersonId { get; set; }
public virtual ContactPerson ContactPerson { get; set; }
}
public class Locations
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
public class ContactPerson
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserId { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
public virtual ICollection<ContactOrganizationPerson> ContactOrganizationPeople { get; set; }
public virtual ICollection<ContactAddress> ContactAddresses { get; set; }
public virtual ICollection<ContactPhone> ContactPhones { get; set; }
public virtual ICollection<ContactEmail> ContactEmails { get; set; }
}
I am planning on changing the ApplicationUser to Locations table relationship to a Many to Many which would link the User to the Locations they are allowed to access. I have though about placing a payload in the M2M relationship table that would specify UserId, LocationId and Roles, but I would rather let Identity handle it if possible.
Is there a way to extend AspNetUserRoles so that I can specify a User to Role relationship for each location? Or is there a better way to accomplish this?
I'm not sure if this is going to help you, but I have extended .Net Core with functionality with IAuthorizationRequirement.
public class CustomRequirement : IAuthorizationRequirement
{
public CustomRequirement ()
{
}
}
Create a new class
public class CustomHandler : AuthorizationHandler<CustomRequirement>
Override HandleRequirementAsync
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequirement requirement)
Here you can extract info about user from DB, compare, etc. If user is not allowed, return
return Task.CompletedTask;
If user is allowed, then use
context.Succeed(requirement);
Before returning. Then in your startup.cs:
services
.AddAuthorization(options =>
{
options.AddPolicy("CustomPolicy", policy =>
policy.Requirements.Add(new CustomRequirement()));
})
And then in your controllers you can add attribute
[Authorize(Policy = "CustomPolicy", Roles = "Admin")]
If requirement is not meet, user will get 401 unauthorized, which might not be what you want.

Cached Fetch for User Roles from NHibernate in an MVC App

Using classes like this...
public class Login
{
public virtual Guid LoginId { get; set; }
public virtual string Name { get; set; }
public virtual string Email { get; set; }
public virtual IList<Group> Groups { get; set; }
}
public class Group
{
public virtual Guid GroupId { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual IList<Role> Roles { get; set; }
public virtual IList<Login> Logins { get; set; }
}
public class Role : ITerminable
{
public virtual Guid RoleId { get; set; }
public virtual string DisplayName { get; set; }
public virtual string RoleName { get; set; }
public virtual string Description { get; set; }
}
And an ERD that looks like this...
This is my current query.
var login = loginRepository.Query().Where(x => x.Name == username).FetchMany(x=>x.Groups).ThenFetchMany(x=>x.Roles).SingleOrDefault();
return login.Groups.SelectMany(x => x.Roles).Distinct().ToList();
The problem is that while the first request to my site is always fine and goes through as a single query for the current user's Roles, subsequent ones result in NHibernate Profiler showing lots of cached queries (one for every role). I'm not entirely sure if this is a red flag or not (I'm using SysCache2, but it's not using Database Dependencies at the moment). But I would like to try and find a way to clear itup.
Is there a way to fix this so that I don't get a cache hit for every single role on every request when the first request was just one database hit? Or as an analogy, am I misinterpreting condensation on a pipe as a leak?
Entity cache is separate from the query cache.
The query cache only stores the ids resulting from the query execution, so retrieving the entities back involves getting that list, and then getting all the values from the entity cache.

Entity Framework Code First - using UserId key of Memberships/Users table as Foreignkey in a custom table

I am trying to create a SQL table to include additional user information.
I want it to be created by Migrations in VS2012 (package console => update-database).
I see that there are two tables using UserId column as key: Memberships and Users tables.
I am trying to define the following class and map it to SQL table via Migrator:
[Key]
[Column(Order = 0)]
[ForeignKey("User")]
public Guid **UserId** { get; set; }
[Key]
[Column(Order = 1)]
[ForeignKey("Category")]
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
**public virtual User User { get; set; }**
Although it is obvious in the Users SQL table that UserId column is the key, I get this error message:
\tSystem.Data.Entity.Edm.EdmEntityType: : EntityType 'User' has no key defined. Define the key for this EntityType.
\tSystem.Data.Entity.Edm.EdmEntitySet: EntityType: EntitySet 'Users' is based on type 'User' that has no keys defined.
What I am missing here? Might be that Microsoft.VisualBasic.ApplicationServices.User / System.Web.Security.MembershipUser classes weren't necessarily mapped to the tables this way and vise versa, and therefore the UserId property is not declared is Key dataannotation?
I am open for other solutions for this problem.
Big Thanks!
I am currently using asp.net mvc4 with Azure db.
When I want to use UserId in other tables from UserProfile. Notice in AccountModels there is class UserProfile:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
Now, let's say your category is created by certain user, you can link category entry to user in following way.
[Table("Category")]
public class Category
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int CategoryId { get; set; }
public UserProfile CreatorUserId { get; set; }
}
Otherwise, you can always use UserProfile as model.

NHibernate: controlling Bidirectional ManyToMany. Adding from one entity and removing from the other entity

I have 2 tables with manyToMany relationship. user can have many groups and groups can have many users.
public class User
{
public virtual Guid Id { get; set; }
public virtual UInt64 UserId { get; set; }
public virtual IList<Group> Groups{ get; set; }
}
public class Group
{
public virtual Guid Id { get; set; }
public virtual Guid GroupGuid { get; set; }
}
I use Fluent NHibernate to AutoMap them as follows:
.Override<User>(obj => obj.HasManyToMany(x => x.Groups).Table("UserToGroup").Cascade.AllDeleteOrphan())
As a result Nhibernate produce 3 tables:
1. Users - Mapped object table
2. Groups Mapped Object table
3. UserToGroup - generated association table
The requirement is to have the following functionality on these tables:
1. AddUser(UInt64 UserId, IEnumerable groups)
2. RemoveGroup(GroupGuid groupGuild)
3. Dictionary> GetGroupToUsers();
AddUser method is work Ok, All table updated OK:
* Insert of new user in User table. OK
* Insert of new group in Group table. OK
* Insert of new relations recods in UserToGroup table. OK
I use the following code to add a User (including groups):
public void AddUser(User userData, IList<Guid> groupIds)
{
User user = new User();
user.UserId = userData.UserId;
IList<User> Users = new List<Users();
Users.Add(user);
IList<Group> groups = new List<Group>();
foreach (Guid groupId in groupIds)
{
Group grp = new Group();
grp.GroupGuid = groupId;
grp.Users = Users;
groups.Add(grp);
}
user.Groups = groups;
Session.Save(user);
}
I use the following code to Remove group:
public void RemoveGroup(GroupGuid groupGuild)
{
IList<Group> groupsToRemove = Session.QueryOver<Group>().Where(
row => row.GroupGuid == groupGuild).List();
foreach (Group group in groupsToRemove)
{
group.Users.Clear();
Session.Delete(group);
}
}
RemoveGroup method failed with the following exception:
threw exception:
NHibernate.Exceptions.GenericADOException: could not delete: [StorageObject.Group#11111111-1111-1111-1111-111111111111][SQL: DELETE FROM "Group" WHERE Id = ?] ---> System.Data.SqlServerCe.SqlCeException: The primary key value cannot be deleted because references to this key still exist. [ Foreign key constraint name = FK4B29424018FA0CD4 ]
I understand that Group table can't be delete since the reference UserToGroup table point to Group table.
1st question: how can I make hibernate to understand that I want to be able to controller this manyToMany relation from both side:
Add users with groups - from user side.
And delete groups - from group side
I tried to move Inverse to the User table but in this case when I add a User the association table is not populate.
What is the best way to define this kind of manyToMany relation?
Update:
Another way I tried is to have List of Users also in Groups in this configuration removeGroup is wokring but addUser in not working for specific scenario:
public class Group
{
public virtual Guid Id { get; set; }
public virtual Guid GroupGuid { get; set; }
public virtual IList<User> Users{ get; set; }
}
public class User
{
public virtual Guid Id { get; set; }
public virtual UInt64 UserId { get; set; }
public virtual IList<Group> Groups{ get; set; }
}
Now I have a bidirectional many to many.
My Fluent mapping is:
.Override<User>(obj => obj.HasManyToMany(x => x.Groups).ParentKeyColumn("UserId").ChildKeyColumn("GroupId").Table("UserToGroup").Cascade.SaveUpdate()
.Override<Group>(obj => obj.HasManyToMany(x => x.Users).ParentKeyColumn("GroupId").ChildKeyColumn("UserId").Table("UserToGroup")
If I use this configuration RemoveGroup works fine but AddUser is not working for the following case:
When adding 2 Users which contains the same Group the association table delete the first relation and holds just the last reference instead of having both relations.
Please advise.
Try to add an inverse collection in Group:
public class Group
{
public virtual Guid Id { get; set; }
public virtual Guid GroupGuid { get; set; }
public virtual IList<User> Users { get; set; }
}
In your mapping:
.Override<Group>(obj => obj.HasManyToMany(x => x.Users).Table("UserToGroup").Inverse().Cascade.SaveUpdate())
Your Remove method:
public void RemoveGroup(GroupGuid groupGuild)
{
IList<Group> groupsToRemove = Session.QueryOver<Group>().Where(
row => row.GroupGuid == groupGuild).List();
foreach (Group group in groupsToRemove)
{
group.Users.Clear(); // Removes references from all users pointing to that group
Session.Delete(group);
}
}
When you commit the transaction, the references should be automatically removed. I never tried this by myself, but it might work for you.