How To Restrict User Entries Only to that Sepcific

2019-08-11 04:02发布

I am trying to restrict user entries so that only that specific user is able to see their entries and not anyone else. In other words, after all I've done, my application still displays every entry that was ever entered; and any user is able to see the entries.

I've created a one-to-many relationship by referencing the foreign key from my Expenses table to the primary key of my AspNetUsers using the Code First convention in Entity Framework, however, when I log in as different users, I am still able to see entries (expenses) that other users have entered.

I'm not sure whether the problem lies in my view, model, or controller.

Here is the code I currently have:

IdentityModel:

 public class ApplicationUser : IdentityUser
{
    public ApplicationUser()
    {
        Expenses = new List<Expense>();
    }

    [Required]
    public string Fullname { get; set; }
    [Required]
    public string Province { get; set; }
    [Required]
    public string Company { get; set; }
    public virtual ICollection<Expense> Expenses { 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
        return userIdentity;
    }


}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("PacificPetEntities", throwIfV1Schema: false)
    {
    }

    public IDbSet<Expense> Expenses { get; set; }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }



}

Expense Model:

public class Expense : IValidatableObject
{
    public Expense() { }

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }
    [Required]
    public string Category { get; set; }
    public string Description { get; set; }

    [Required]
    [Display(Name = "Gross Amount")]
    public double GrossAmount { get; set; }
    [Required]
    [Display(Name = "Tax Amount")]
    public double TaxAmount { get; set; }
    [Required]
    [Display(Name = "Net Amount")]
    public double NetAmount { get; set; }
    public int Mileage { get; set; }
    [Display(Name = "Mileage Rate")]
    public double MileageRate { get; set; }

    [Required]
    [Display(Name = "Date Submitted")]
    public DateTime? DateSubmitted { get; set; }
    [Required]
    [Display(Name = "Expense Date")]
    public DateTime? ExpenseDate { get; set; }


    public string UserId { get; set; }
    [ForeignKey("UserId")]
    public virtual ApplicationUser ApplicationUser { get; set; }



    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Category == "Auto - Mileage" && Mileage == 0)
        {
            yield return new ValidationResult("You must enter a mileage amount if the chosen category is mileage.");
        }
    }

}

Controller:

public class ExpensesController : Controller
{
    private ApplicationDbContext db = new ApplicationDbContext();

    // GET: Expenses
    [Authorize]
    public ActionResult Index()
    {
        var expenses = db.Expenses.Include(e => e.ApplicationUser);
        return View(expenses.ToList());
    }

    // GET: Expenses/Details/5
    [Authorize]
    public ActionResult Details(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Expense expense = db.Expenses.Find(id);
        if (expense == null)
        {
            return HttpNotFound();
        }
        return View(expense);
    }

    // GET: Expenses/Create
    [Authorize]
    public ActionResult Create()
    {
        ViewBag.UserId = new SelectList(db.Users, "Id", "Fullname");
        return View();
    }

    // POST: Expenses/Create
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize]
    public ActionResult Create([Bind(Include = "ID,Category,Description,GrossAmount,TaxAmount,NetAmount,Mileage,MileageRate,DateSubmitted,ExpenseDate,UserId")] Expense expense)
    {
        if (ModelState.IsValid)
        {
            db.Expenses.Add(expense);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        ViewBag.UserId = new SelectList(db.Users, "Id", "Fullname", expense.UserId);
        return View(expense);
    }

    // GET: Expenses/Edit/5
    [Authorize]
    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Expense expense = db.Expenses.Find(id);
        if (expense == null)
        {
            return HttpNotFound();
        }
        ViewBag.UserId = new SelectList(db.Users, "Id", "Fullname", expense.UserId);
        return View(expense);
    }

    // POST: Expenses/Edit/5
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize]
    public ActionResult Edit([Bind(Include = "ID,Category,Description,GrossAmount,TaxAmount,NetAmount,Mileage,MileageRate,DateSubmitted,ExpenseDate,UserId")] Expense expense)
    {
        if (ModelState.IsValid)
        {
            db.Entry(expense).State = System.Data.Entity.EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        ViewBag.UserId = new SelectList(db.Users, "Id", "Fullname", expense.UserId);
        return View(expense);
    }

    // GET: Expenses/Delete/5
    [Authorize]
    public ActionResult Delete(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Expense expense = db.Expenses.Find(id);
        if (expense == null)
        {
            return HttpNotFound();
        }
        return View(expense);
    }

    // POST: Expenses/Delete/5
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    [Authorize]
    public ActionResult DeleteConfirmed(int id)
    {
        Expense expense = db.Expenses.Find(id);
        db.Expenses.Remove(expense);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }
        base.Dispose(disposing);
    }
}

Index.cshtml:

 @model IEnumerable<PacificPetExpenses.Models.Expense>

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.ApplicationUser.Fullname)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Category)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Description)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.GrossAmount)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.TaxAmount)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.NetAmount)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Mileage)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.MileageRate)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.DateSubmitted)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.ExpenseDate)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.ApplicationUser.Fullname)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Category)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Description)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.GrossAmount)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.TaxAmount)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.NetAmount)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Mileage)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.MileageRate)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DateSubmitted)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ExpenseDate)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
            @Html.ActionLink("Details", "Details", new { id=item.ID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ID })
        </td>
    </tr>
}

</table>

Please help.

Thank you.

2条回答
混吃等死
2楼-- · 2019-08-11 04:29

Select your Expenses with the current user id. Like this.

// GET: Expenses
[Authorize]
public ActionResult Index()
{
    var expenses = db.Expenses.Where(e => e.UserId == User.Identity.GetUserId());
    return View(expenses.ToList());
}
查看更多
一夜七次
3楼-- · 2019-08-11 04:48

I have found the answer. Padhraic was really close, but his answer helped me solve my problem.

In my controller, I had:

public ActionResult Index()
{
    var expenses = db.Expenses.Include(e => e.ApplicationUser);
    return View(expenses.ToList());
}

Instead, this should be:

public ActionResult Index()
{
    string currentUserId = User.Identity.GetUserId();
    var expenses = db.Expenses.Where(e => e.UserId == currentUserId);
    return View(expenses.ToList());
}

According to Stephen Muecke's comment on my question, db.Expenses.Include(e => e.ApplicationUser) was returning all rows in my database. Instead I needed to filter the results to the current user.

查看更多
登录 后发表回答