如何从ASP.NET Identity 2

时间:2016-06-03 23:02:30

标签: asp.net-mvc-5 asp.net-identity-2

使用默认的ASP.NET MVC 5模板(带有个人帐户)的略微修改版本,我试图基于中间表获取用户的子集。我已经建立了一个可以返回所有用户列表的管理UI,但现在我需要根据当前登录用户在中间表中定义的访问权限来限制返回的用户集。

基本上,每个用户都可以访问一个或多个诊所,因此每个诊所都可以访问一个诊所。

如果当前登录的用户属于某个给定的角色(例如," Clinic Admin"),那么他们应该能够检索属于 any

任何人都可以帮我指出正确的方向吗?这是我的第一个Anything.NET应用程序,所以请随意解释,比如我五岁。 : - )

提前感谢您提供任何帮助。

其他信息:

  • Visual Studio 2013 Update 5
  • 实体框架6
  • MS SQL Server 2008 R2

这是中间表的类(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类:

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列表,根据我们的诊所,仅返回我可以访问的用户列表。常见的。

如果我把它写成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'
            )
    )

2 个答案:

答案 0 :(得分:1)

我回过头来解决了这个问题,但我想我最好回到这里并用答案更新我的问题,以防这可能对其他人有所帮助。

我相应更新了我的Clinic和ClinicUser类:

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类的以下摘录:

[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://stackoverflow.com/users/4089212/archil-labadze)提供了有用的回复。

答案 1 :(得分:1)

首先,不要在ApplicationUser类中使用多个属性,可以管理用户配置文件表并将其与应用程序用户类连接,这样就可以在配置文件表中放入大量有关用户的信息。 下一个任务是组织诊所,分支机构等表......并将应用程序用户与他们联系起来。 接下来你有两种方法: 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; }
}

接下来你需要其他ViewModels来展示它们希望这个帮助。

<强>更新

// 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());
    }