slider1578
slider1578

Reputation: 11

MVC5: Allow user to only view and edit their own information

I created a scaffold based on one of my tables. I'm now trying to figure out how to allow the user to only view/edit data that is the same as their userID.

Right now it displays all the data from that table and allows for editing of all users. I need to be able to limit it to only the user that is currently logged in.

Please let me know if I can give any more details.

Controller

    public class ClientViewStaffController : Controller
{
    private TpsEntities db = new TpsEntities();

    // GET: ClientViewStaff
    public ActionResult Index()
    {
        return View(db.staffTables.ToList());
    }

    // GET: ClientViewStaff/Details/5
    public ActionResult Details(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        staffTable staffTable = db.staffTables.Find(id);
        if (staffTable == null)
        {
            return HttpNotFound();
        }
        return View(staffTable);
    }

    // GET: ClientViewStaff/Create
    public ActionResult Create()
    {
        return View();
    }

    // POST: ClientViewStaff/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]
    public ActionResult Create([Bind(Include = "staffID,staffFirstName,staffLastName,staffTitle,staffAddress,staffCity,staffState,staffZip,staffExperience,staffEducation,desiredSalary,staffProfession,staffAvailibity,staffPhoto,staffEmail,staffPhoneNum,userID")] staffTable staffTable)
    {
        if (ModelState.IsValid)
        {
            db.staffTables.Add(staffTable);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(staffTable);
    }

    // GET: ClientViewStaff/Edit/5
    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        staffTable staffTable = db.staffTables.Find(id);
        if (staffTable == null)
        {
            return HttpNotFound();
        }
        return View(staffTable);
    }

    // POST: ClientViewStaff/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]
    public ActionResult Edit([Bind(Include = "staffID,staffFirstName,staffLastName,staffTitle,staffAddress,staffCity,staffState,staffZip,staffExperience,staffEducation,desiredSalary,staffProfession,staffAvailibity,staffPhoto,staffEmail,staffPhoneNum,userID")] staffTable staffTable)
    {
        if (ModelState.IsValid)
        {
            db.Entry(staffTable).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(staffTable);
    }

    // GET: ClientViewStaff/Delete/5
    public ActionResult Delete(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        staffTable staffTable = db.staffTables.Find(id);
        if (staffTable == null)
        {
            return HttpNotFound();
        }
        return View(staffTable);
    }

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

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

View (Index.cshtml)

<table class="table">
<tr>
    <th>
        First Name
    </th>
    <th>
        Last Name
    </th>
    <th>
        @Html.DisplayNameFor(model => model.staffState)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.staffExperience)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.staffEducation)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.desiredSalary)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.staffProfession)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.staffAvailibity)
    </th>
    <th></th>
</tr>

@foreach (var item in Model)
{
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.staffFirstName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.staffLastName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.staffState)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.staffExperience)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.staffEducation)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.desiredSalary)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.staffProfession)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.staffAvailibity)
        </td>
        <td>
            @Html.ActionLink("Details", "Details", new { id = item.staffID }) |

        </td>
    </tr>
}

View (Details.cshtml)

<div>
<h4>Staff View</h4>
<hr />
<dl class="dl-horizontal">
    <dt>
        First Name
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffFirstName)
    </dd>

    <dt>
        Last Name
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffLastName)
    </dd>

    <dt>
        Title
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffTitle)
    </dd>

    <dt>
        Address
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffAddress)
    </dd>

    <dt>
        City
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffCity)
    </dd>

    <dt>
        State
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffState)
    </dd>

    <dt>
        Zip Code
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffZip)
    </dd>

    <dt>
        Experience
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffExperience)
    </dd>

    <dt>
        Education
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffEducation)
    </dd>

    <dt>
        Salary
    </dt>

    <dd>
        @Html.DisplayFor(model => model.desiredSalary)
    </dd>

    <dt>
        Profession
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffProfession)
    </dd>

    <dt>
        Availability
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffAvailibity)
    </dd>

    <dt>
        Photo
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffPhoto)
    </dd>

    <dt>
        Email
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffEmail)
    </dd>

    <dt>
        Phone Number
    </dt>

    <dd>
        @Html.DisplayFor(model => model.staffPhoneNum)
    </dd>

    <dt>
        User ID
    </dt>

    <dd>
        @Html.DisplayFor(model => model.userID)
    </dd>

</dl>
</div>
<p>
    @Html.ActionLink("Edit", "Edit", new { id = Model.staffID }) |
   @Html.ActionLink("Back to List", "Index")
</p>

Upvotes: 1

Views: 4968

Answers (3)

Ric .Net
Ric .Net

Reputation: 5550

I think your missing something about entity framework in combination with Linq aka Linq-to-entities.

Your can write queries against your ef model using Linq. For details see MSDN.

What your basically doing is writing a query in c# and entity framework will convert this query to a sql select statement and run this against your database.

Using this approach your question becomes real simple. Just write a query which fits your needs. Something like this could work

public IEnumerable<> FetchData(string userId)
{
    return (
       from item in this.db.staffTables
       where item.UserId == userId
       select item
       ).ToArray();
}

A far better approach would be to hide your entity framework model from your controller and use a repository in between. The repository would typically implement four functions: GetData()', 'Create()', 'Update() and Delete(). In each method you would check if the user is authorized for the action to perform or return only data that the user is authorized to get.

Upvotes: 1

DSR
DSR

Reputation: 4668

Decorate your Edit action with [Authorize] attribute

[Authorize]
public ActionResult Edit(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    staffTable staffTable = db.staffTables.Find(id);
    if (staffTable == null)
    {
        return HttpNotFound();
    }
    return View(staffTable);
}

Then hide your edit action for non-logged in users.

First add @using Microsoft.AspNet.Identity to top of your view and then use below code on view.

@if (Request.IsAuthenticated)
{
    @Html.ActionLink("Edit", "Edit", new { id = Model.staffID })
}

Edited for comment

As you know that anything you need to restrict non-authenticated users (non-logged in), you have to use [Authorize] attribute as I mentioned.

You didn't mentioned what you exactly restrict access in your question.

If you want to restrict access all your content to the non authenticate user, then add [Authorize] attribute to your controller as below.

[Authorize]
public class ClientViewStaffController : Controller
{

}

Then all the actions restricted for logged in users only. Is that what you looking for?

Upvotes: 1

beautifulcoder
beautifulcoder

Reputation: 11340

You can implement something like this in the Edit, Details GET action.

var loggedInUser = GetUserId(HttpContext.Current.User.Identity.Name);
if (id != loggedInUser)
{
    return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
}

You can also abstract this away from the controller and put in an Action Filter. Action filters in ASP.NET MVC are C# attributes that separate specific concerns such as security.

Upvotes: 1

Related Questions