如何从 ASP.NET Identity 2 获取用户的子集
How to get a subset of Users from ASP.NET Identity 2
使用稍微修改过的默认 ASP.NET MVC 5 模板(带有个人帐户),我试图根据中介 table 获取一部分用户。我已经建立了一个管理 UI 可以 return 所有用户的列表,但现在我需要根据当前登录用户的访问权限来限制用户集 returned定义在中介 table.
基本上,每个用户都可以访问 1 个或多个诊所,因此他们可以访问的每个诊所都有一个记录。
如果当前登录的用户属于给定角色(例如,"Clinic Admin"),那么他们应该能够检索属于 any[= 的任何用户的列表39=] 他们可以访问的诊所。
谁能帮我指明正确的方向?这是我的第一个 Anything.NET 应用程序,所以请像我五岁一样随意解释。 :-)
提前感谢您提供的任何帮助。
附加信息:
- Visual Studio 2013 更新 5
- Entity Framework 6
- MS SQL 服务器 2008 R2
这里是中介table的class(ClinicUser):
[Table("clinic_users")]
public class ClinicUser
{
[Key]
public virtual ApplicationUser ApplicationUsers { get; set; }
[Required]
public string Id { get; set; }
[Required]
public System.Guid provider_id { get; set; }
[Required]
public System.Guid health_system_id { get; set; }
[Required]
public System.Guid clinic_id { get; set; }
}
这是我的 ApplicationUser class:
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
get { return FirstName + " " + LastName; }
}
[ForeignKey("ClinicUsers")]
public override string Id
{
get
{
return base.Id;
}
set
{
base.Id = value;
}
}
public virtual ClinicUser ClinicUsers { get; set; }
public IEnumerable<SelectListItem> RolesList { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
userIdentity.AddClaims(ClinicClaimsProvider.GetClaims(userIdentity));
return userIdentity;
}
}
如果不清楚,我真正想做的是将 ApplicationUsers 列表缩小到 return 只有我根据我们拥有的诊所可以访问的用户列表有共同点。
如果我把它写成一个 SQL 查询,这将是完成我想要的东西的一种方法(我似乎无法用 LINQ 完全得到我想要的东西):
SELECT *
FROM AspNetUsers au
WHERE Id IN (
SELECT Id
FROM clinic_users
WHERE clinic_id IN (
SELECT clinic_id
FROM clinic_users
WHERE Id = 'CurrentUserId'
)
)
我不久前解决了这个问题,但我想我最好回到这里并用答案更新我的问题,以防这可能对其他人有所帮助。
我相应地更新了我的 Clinic 和 ClinicUser classes:
Clinic.cs
[Table("clinics")]
public class Clinic
{
[Key]
public System.Guid ClinicId { get; set; }
public List<ClinicUser> ClinicUsers { get; set; }
}
ClinicUser.cs
[Table("clinic_users")]
public class ClinicUser
{
[Key, Column(Order = 0)]
public string UserId { get; set; }
[Key, Column(Order = 1)]
public System.Guid ClinicId { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationUser ApplicationUser { get; set; }
[ForeignKey("ClinicId")]
public Clinic Clinic { get; set; }
}
另外,我更新了我的 ApplicationUser class 的以下摘录:
[ForeignKey("ClinicUsers")]
public override string Id
{
get
{
return base.Id;
}
set
{
base.Id = value;
}
}
public virtual ClinicUser ClinicUsers { get; set; }
对此:
public List<ClinicUser> ClinicUsers { get; set; }
最后,在我的 ApplicationUsersController 的 Index() 操作中,我能够使用这个:
public async Task<ActionResult> Index()
{
if (User.IsInRole("Admin")) return View(await UserManager.Users.ToListAsync());
var userId = User.Identity.GetUserId();
//Get the Ids of the current user's clinics
var userClinics = db.ClinicUsers.Where(cu => cu.UserId == userId).Select(cu => cu.ClinicId).ToList();
//Get all userIds of the user at the current user's clinics
var clinicUserIds = db.ClinicUsers.Where(cu => userClinics.Contains(cu.ClinicId)).ToList().Select(cu => cu.UserId);
var users = UserManager.Users.Where(u => clinicUserIds.Contains(u.Id));
return View(await users.ToListAsync());
}
本质上,如果用户具有 "Admin" 角色,那么他们将获得数据库中所有用户的列表。如果不是,他们将只会获得也属于他们共同诊所的用户列表。
它可能并不完美,但它确实有效。如果有人对如何改进这一点有任何建议,我将很高兴听到。
再次感谢 Archil (https://whosebug.com/users/4089212/archil-labadze) 的有用回复。
首先不要在ApplicationUserclass中使用太多属性,你可以管理用户配置文件table并将其与应用程序用户class连接起来,这样你就可以放很多信息关于个人资料 table 中的用户。
下一个任务是组织 table 诊所、分支机构等...并将应用程序用户与他们联系起来。
接下来你有2种方式:
1. 将应用程序用户与诊所或分支机构相关联。
要么
2. 用角色管理他们。
以下是应用程序用户的示例:
[Table("Clinics")]
public class Clinic
{
[Key]
public string Id { get; set; }
public virtual ICollection<ClinicUser> ClinicUsers { get; set; }
}
[Table("ClinicUsers")]
public class ClinicUser
{
[Key]
[Column(Order = 0)]
public string ClinicId { get; set; }
[Key]
[Column(Order = 1)]
public string UserId { get; set; }
}
接下来您需要其他 ViewModel 来显示它们,希望对您有所帮助。
更新
// GET: ClinicUsers by Clinic
public async Task<ActionResult> ViewCurrentClinicUsers(string id) // This is clinis ID
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Clinic clinic = await db.clinic.FindAsync(id); // Get Selectedclinic
if (clinic == null)
{
return HttpNotFound();
}
ClinicUsers model = new ClinicUsers() // ClinicUsers model
{
clinic = clinic, // View Currentclinic
ClinicUsers = await db.ClinicUsers.Were(x => x.clinicid == clinic.id)ToListAsync()) // Get Users that asigned to current clinic
};
return View(model);
}
更新 2
最后,如果你想显示诊所,则分配给当前登录用户
// GET: Clinics by currentuser
public async Task<ActionResult> ViewClinicsWithCurrentUserAccess()
{
var currentuserId = User.Identity.GetUserId(); // This gets currentloged user id
var currentuser = await db.Users.SingleOrDefaultAsync(x => x.Id == myUserId); // This gets currentloged user virtual
return View(await db.Clinics.Were(x => x.clinicuserid == currentuserId).ToListAsync());
}
使用稍微修改过的默认 ASP.NET MVC 5 模板(带有个人帐户),我试图根据中介 table 获取一部分用户。我已经建立了一个管理 UI 可以 return 所有用户的列表,但现在我需要根据当前登录用户的访问权限来限制用户集 returned定义在中介 table.
基本上,每个用户都可以访问 1 个或多个诊所,因此他们可以访问的每个诊所都有一个记录。
如果当前登录的用户属于给定角色(例如,"Clinic Admin"),那么他们应该能够检索属于 any[= 的任何用户的列表39=] 他们可以访问的诊所。
谁能帮我指明正确的方向?这是我的第一个 Anything.NET 应用程序,所以请像我五岁一样随意解释。 :-)
提前感谢您提供的任何帮助。
附加信息:
- Visual Studio 2013 更新 5
- Entity Framework 6
- MS SQL 服务器 2008 R2
这里是中介table的class(ClinicUser):
[Table("clinic_users")]
public class ClinicUser
{
[Key]
public virtual ApplicationUser ApplicationUsers { get; set; }
[Required]
public string Id { get; set; }
[Required]
public System.Guid provider_id { get; set; }
[Required]
public System.Guid health_system_id { get; set; }
[Required]
public System.Guid clinic_id { get; set; }
}
这是我的 ApplicationUser class:
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
get { return FirstName + " " + LastName; }
}
[ForeignKey("ClinicUsers")]
public override string Id
{
get
{
return base.Id;
}
set
{
base.Id = value;
}
}
public virtual ClinicUser ClinicUsers { get; set; }
public IEnumerable<SelectListItem> RolesList { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
userIdentity.AddClaims(ClinicClaimsProvider.GetClaims(userIdentity));
return userIdentity;
}
}
如果不清楚,我真正想做的是将 ApplicationUsers 列表缩小到 return 只有我根据我们拥有的诊所可以访问的用户列表有共同点。
如果我把它写成一个 SQL 查询,这将是完成我想要的东西的一种方法(我似乎无法用 LINQ 完全得到我想要的东西):
SELECT *
FROM AspNetUsers au
WHERE Id IN (
SELECT Id
FROM clinic_users
WHERE clinic_id IN (
SELECT clinic_id
FROM clinic_users
WHERE Id = 'CurrentUserId'
)
)
我不久前解决了这个问题,但我想我最好回到这里并用答案更新我的问题,以防这可能对其他人有所帮助。
我相应地更新了我的 Clinic 和 ClinicUser classes:
Clinic.cs
[Table("clinics")]
public class Clinic
{
[Key]
public System.Guid ClinicId { get; set; }
public List<ClinicUser> ClinicUsers { get; set; }
}
ClinicUser.cs
[Table("clinic_users")]
public class ClinicUser
{
[Key, Column(Order = 0)]
public string UserId { get; set; }
[Key, Column(Order = 1)]
public System.Guid ClinicId { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationUser ApplicationUser { get; set; }
[ForeignKey("ClinicId")]
public Clinic Clinic { get; set; }
}
另外,我更新了我的 ApplicationUser class 的以下摘录:
[ForeignKey("ClinicUsers")]
public override string Id
{
get
{
return base.Id;
}
set
{
base.Id = value;
}
}
public virtual ClinicUser ClinicUsers { get; set; }
对此:
public List<ClinicUser> ClinicUsers { get; set; }
最后,在我的 ApplicationUsersController 的 Index() 操作中,我能够使用这个:
public async Task<ActionResult> Index()
{
if (User.IsInRole("Admin")) return View(await UserManager.Users.ToListAsync());
var userId = User.Identity.GetUserId();
//Get the Ids of the current user's clinics
var userClinics = db.ClinicUsers.Where(cu => cu.UserId == userId).Select(cu => cu.ClinicId).ToList();
//Get all userIds of the user at the current user's clinics
var clinicUserIds = db.ClinicUsers.Where(cu => userClinics.Contains(cu.ClinicId)).ToList().Select(cu => cu.UserId);
var users = UserManager.Users.Where(u => clinicUserIds.Contains(u.Id));
return View(await users.ToListAsync());
}
本质上,如果用户具有 "Admin" 角色,那么他们将获得数据库中所有用户的列表。如果不是,他们将只会获得也属于他们共同诊所的用户列表。
它可能并不完美,但它确实有效。如果有人对如何改进这一点有任何建议,我将很高兴听到。
再次感谢 Archil (https://whosebug.com/users/4089212/archil-labadze) 的有用回复。
首先不要在ApplicationUserclass中使用太多属性,你可以管理用户配置文件table并将其与应用程序用户class连接起来,这样你就可以放很多信息关于个人资料 table 中的用户。 下一个任务是组织 table 诊所、分支机构等...并将应用程序用户与他们联系起来。 接下来你有2种方式: 1. 将应用程序用户与诊所或分支机构相关联。 要么 2. 用角色管理他们。
以下是应用程序用户的示例:
[Table("Clinics")]
public class Clinic
{
[Key]
public string Id { get; set; }
public virtual ICollection<ClinicUser> ClinicUsers { get; set; }
}
[Table("ClinicUsers")]
public class ClinicUser
{
[Key]
[Column(Order = 0)]
public string ClinicId { get; set; }
[Key]
[Column(Order = 1)]
public string UserId { get; set; }
}
接下来您需要其他 ViewModel 来显示它们,希望对您有所帮助。
更新
// GET: ClinicUsers by Clinic
public async Task<ActionResult> ViewCurrentClinicUsers(string id) // This is clinis ID
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Clinic clinic = await db.clinic.FindAsync(id); // Get Selectedclinic
if (clinic == null)
{
return HttpNotFound();
}
ClinicUsers model = new ClinicUsers() // ClinicUsers model
{
clinic = clinic, // View Currentclinic
ClinicUsers = await db.ClinicUsers.Were(x => x.clinicid == clinic.id)ToListAsync()) // Get Users that asigned to current clinic
};
return View(model);
}
更新 2 最后,如果你想显示诊所,则分配给当前登录用户
// GET: Clinics by currentuser
public async Task<ActionResult> ViewClinicsWithCurrentUserAccess()
{
var currentuserId = User.Identity.GetUserId(); // This gets currentloged user id
var currentuser = await db.Users.SingleOrDefaultAsync(x => x.Id == myUserId); // This gets currentloged user virtual
return View(await db.Clinics.Were(x => x.clinicuserid == currentuserId).ToListAsync());
}