Update custom attributes asp.net mvc membership - asp.net-mvc

I´ve added some custom attributes to UserProfile asp.net membership table, lastname, address, cellphone, etc. So
I can create new users using.
WebSecurity.CreateUserAndAccount(UserName, Password,
propertyValues: new
{
UserId = model.userId,
UserLastName = model.lastName,
UserAddress = model.address,
.
.
}
);
So I want to know if it´s possible in similar way achieve an update query, including this custom attributes.
Thank you.

Yes you can. However I do not think WebSecurity provides a way to update extra column in membership tables e.g. UserProfile through its API.
This is how we did it, we have MVC4 ASP.NET internet application project and we are using EF5.0 Code First.
You already know how to add extra column in the UserProfile table (table name can be anything).
Once we have a class (that has all required extra columns along with UserId and UserName),
Added a controller UserController dedicated to facilitate CRUD operation for UserProfile.
UserController uses a UserService class in business layer that is taking care of all CRUD operation on UserProfile class (entity).
On Edit Post operation, controller call UserService class UpdateUser() method which looks like below:
public void UpdateUser(UserProfile user)
{
Guard.ArgumentNotNull(user, "user");
if (_roleWrapper.GetRolesForUser(user.UserName).Any())
{
_roleWrapper.RemoveUserFromRoles(user.UserName, _roleWrapper.GetRolesForUser(user.UserName));
}
if (!_roleWrapper.IsUserInRole(user.UserName, user.Role))
{
_roleWrapper.AddUserToRole(user.UserName, user.Role);
}
_dataContext.Update<UserProfile>(user);
}
Above text and sample is for example only, you can simplify it. Basically you need to get hold of UserProfile class and using DbContext to update it manually. WebSecurity has limited APIs keeping simplicity in mind.
Hope that helps (if anything confusing please let me know, i will expand further).

Related

Jhipster, prevent user to update entities created by other users

I have been implementing Jhipster at my work and loving it. I was asked to implement a security validation that one user should not be allowed to edit the entity created by other user. For this I need two things:
First, in all entities, add a ManytoOne relation with User entity.
In Backend put a validation in controller while updating the entity to check if current logged in user is same as what is stored in DB. In front end also same logic to show/hide edit button.
I have done a POC for this and it works but is little ugly, check the code:
public ResponseEntity<Entry> updateEntry(#RequestBody Entry entry) throws URISyntaxException {
log.debug("REST request to update Entry : {}", entry);
if (entry.getId() == null) {
throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull");
}
//here is my logic
Optional<Entry> entry_db = entryRepository.findOneWithEagerRelationships(entry.getId());
if(!entry_db.get().getUser().getId().equals(userService.getUserWithAuthorities().get().getId())) {
//throw someexception
}
//
Entry result = entryRepository.save(entry);
return ResponseEntity.ok()
.headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, entry.getId().toString()))
.body(result);
}
Is there any better or OOTB way of doing this??? may be something in spring security i am not aware of??
Thanks for help!!
This is a job for Spring Security Expression-Based Access Control, in particular you could annotate your method with #PreFilter and a custom PermissionEvaluator you would implement with similar logic as in your POC. The PermissionEvaluator could be generic and applied to several entity types if you define an Owned interface that models the ownership with a method like User getOwner() and that all your entity classes would implement.
See https://docs.spring.io/spring-security/site/docs/current/reference/html5/#el-access
The annotated method should be in a service rather than in a resource controller.
Also, UserService alone will not help you in finding the current authenticated user, you should use JHipster's SecurityUtils first and then ÙserService if you need more data about it.

How to call model methods in controller in asp.net mvc

I am working on an asp.net mvc application.
This is the approach that i am following right through the application.
Here is my model:
public class EmployeeModel
{
//Properties
// Constructors
// Methods
}
My View: (strongly typed with model Properties) for example : Some Edit View
My Controller:
[httppost]
public void save(Employeemodel m) // ajax call that gets updated model details
{
m.update() // making database call from controller action
}
Are there any serious design issues with my approach of MVC. May be i mis understood MVC?
Is it appropriate to call model methods(m.update() ) in controller action?
Model contains methods that manipulate data ? IS it correct?
please help/suggest the correct approach to follow in MVC
I would recommend you to have separate layer to save data to the database, because its not just MVC that one should follow.
You should use Model(with function only) as a provider whose duty is to perform database task.
ViewModel that hold your entities (properties only)
Controller that can handle your application logic.
View to render HTML/UI.
So its not about MVC rather the best practice one should follow to architect an application.
Further we have several options that we must consider before planning architecture of an application.
Service/Business Layer - Interact b/w Application layer and Repository
Providers/Repository Layer - Interact b/w Service layer and Database
So, it depends on the level of abstraction you want, but as far as MVC concern I would recommend you to have extra layer of separation of ViewModel MVVM.
Its better to ask these type of questions in stachexchange chat.
Example
ViewModel
public class User
{
public Guid Id {get;set;}
public string Name {get;set;}
}
Model
public class UserModel
{
public void AddUser(User user)
{
//add to the database
}
public void UpdateUser(User user)
{
//update in the database
}
}
Controller
[HttpPost]
public ActionResult UpdateUser(User user)
{
UserModel user = new UserModel();
user.UpdateUser(user);
}
In general practice you should now follow this methodology.
Although this is the default MVC behavior of accepting entire model as an argument you should have a middle layer called as DTO(Data Transfer Object) or ViewModel which represents UI.
And after accepting and validating View model you can transform it to your main business entity.
Offcouse it depends how you have written code in your update method but the main hack is this case is that.... any body can pass any known property value to this method and can hack your system. for example suppose you have following values in your Employeemodel
{
Id,
Name,
SecurityCode,
...
}
and your edit screen just have Name input to update it. Any body can add extra html for SecurityCode and can add bad value to it :)
I hope i didn't confused you.
For start try to implement Repository pattern MVC... Google it and you'll find the basic usage of it. :)
Cheers
Your logic is fine. But as K D said, you should have viewmodel that represents view. I would suggest you write your methods in view model since you will pass only model entity to database or anywhere else.
public class Employee
{
//Properties
}
public class EmployeeViewmodel
{
// Employee model object
//Constructors
//Methods
}
return view("View name", EmployeeViewModel);
So you can update model, pass Employee alone to Database via OR/M ..This is basic flexible approach. You can have a utility model class which contains common data retrival like City, state, gender .. so you wont mix entity with other models.

.NET MVC preventing forged POST

SITUATION:
I have a Model and based on a users Role I want to allow the user to only update certain parts of the model. Lets say the Model has three fields. (My Model is obviously more complex than this)
MyObject
Field1
Field2
Field3
My View looks something like this:
Html.TextBoxFor(#Model.Field1)
Html.TextBoxFor(#Model.Field2)
#if(UserIsAdmin())
Html.TextBoxFor(#Model.Field3)
else
#Model.Field3
Bearing with me on the syntax (and the poor design of the example), you can see what I'm trying to do. Upon the user posting the form my controller would just take the MyObject and save it back to the database, we are using EF.
QUESTION:
My question is, is there a way to stop a user from forging a POST to be able to save data he/she should not be able to. My current idea would be to do a check in the controller to see if the user modified values he should not have. Or I could save fields individually, but neither is a convient solution.
Is there a better one?
Thanks!
Additional Info:
Not sure if this artical is relevant at all: http://blog.stevensanderson.com/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/
All three fields are from the same database table and I'm using EF to get and save the entity.
You want to make sure the user is only able to update permitted fields.
You decided that the way to achieve this is to prevent the user "forging" a response using e.g. firebug, or F12 developer tools, or GreaseMonkey, and have asked how to do this.
But the correct/best method is to check which fields the user is attempting to update, and only update those which he is permitted to update. Then it doesn't matter if they forge the request or not, they still won't be able to access anything they shouldn't. In other words, check access rights at the point of access.
Anti-forgery tokens are there to solve a separate problem, namely XSRF.
Use a viewmodel that accepts only the fields that should be updated and then populate the model with those values. You could use something like AutoMapper for mapping between the two.
My current idea would be to do a check in the controller to see if the user modified values he should not have. Or I could save fields individually, but neither is a convient solution.
You're on the right track with that idea. A typical Add() operation would look like this:
public class FooController : Controller
{
public ActionResult Add(FooViewModel viewModel)
{
if (ModelState.IsValid)
{
FooDataModel dataModel = FooMapper.MapToDataModel(viewModel, User);
FooRepository.Add(dataModel);
}
}
}
Like #VimalStan said, your FooViewModel is then a model that contains only the fields you want to let the user update. Also this still doesn't solve your problem, which should be done in your mapper (in this case FooMapper) and still check every field as #Ben suggested:
public static class FooMapper
{
public static FooDataModel Map(FooViewModel viewModel, IPrincipal user)
{
var dataModel = new FooDataModel();
dataModel.Field1 = viewModel.Field1;
dataModel.Field2 = viewModel.Field2;
if (IsAllowedToUpdateField3(user))
{
dataModel.Field3 = viewModel.Field3;
}
return dataModel;
}
public static bool IsAllowedToUpdateField3(IPrincipal user)
{
return false; // your logic
}
}

asp.net mvc3, which layer should I put my code in?

I am building an applicaiton using asp.net mvc3. I added two layers to this project, repository and service layer. some of my code, I am not sure which layer I should put them in.
on my register page, to create an account, I only ask user to enter their email and password, its using UserRegisterViewModel. before I add it to the database, my user table need more info.
I need to create an User entity from the UserRegisterViewModel:
user.ip= "1.1.1.1";
user.createddate="11/11/1911";
....
so above code, where should I put them? webui, repoistory or service layer.
I would add the 'CreatedDate' in the constructor of your 'User' entity, and add the IP address in the controller that receives the ViewModel object.
I case you didn't know: you can map ViewModels to Entities using AutoMapper.
You can only get the IP address from the request so you have 'get' it there in the Action
Something like this
[HttpPost]
public ActionResult Login(UserRegisterViewModel model) {
if(ModelState.IsValid) {
SaveLogonToAudit(model.Username);
}
return View(model);
}
private void SaveLogonToAudit(string username) {
var user = new UserAccount(username, Request.Browser.Browser, Request.Browser.Type, Request.UserHostAddress);
user.Save();
}
The User entity could live in another layer, your UserRegisterViewModel will live in the MVC UI layer. It's perfectly normal to have a ViewModel that represents the data in your view and a completely separate class in another layer that represents your User entity. That's good design. Your User entity can be in the ServiceLayer and have business rules associated to it. That class will then call into your repository layer to save its data.
I agree with Leon Cullens, the CreateDate should live in the User entity, that's why you don't see me setting it. The User entity should handle it's own CRUD actions that call into your RepositoryLayer. Set the CreateDate in the ctor or better yet, have a base class that has CreateDate, CreatedBy, LastUpdateDate, LastUpdatedBy that the User will use internally.

ASP.NET MVC validation of uniqueness

Rails has a very convenient uniqueness validation.
ASP.NET MVC doesn't.
I need to make sure that the e-mail address a user has entered hasn't been registered by anyone yet.
I can see only one way of doing this kind of validation: create a new data context object in the UniqueAttribute class.
But I'm afraid that wasting memory on a new data context object just for one validation is dangerous.
Am I wrong? Is there a better way to do that?
Update
This is what I got so far
public class UniqueEmailAttribute : ValidationAttribute {
public override bool IsValid(object value) {
DataContext db = new DataContext();
var userWithTheSameEmail = db.Users.SingleOrDefault(
u => u.Email == (string)value);
return userWithTheSameEmail == null;
}
}
// Usage
[UniqueEmail(ErrorMessage="This e-mail is already registered")]
public string Email { get; set; }
There are two problems.
It would be good to have just one UniqueAttribute class, not separate classes for e-mails, usernames etc. How can I do that?
Creating a new data context every time you need to validate a single attribute.
SOLUTION
So in the end I created a unique constraint on the table and now I just have to intercept SqlException in Users repository. Works great and is probably more efficient than searching for the same node in the whole table. Thanks!
Mvc 3 Relaease candidate has new New Validation Attributes as a remotevalidation -where you can register a method for validation on clientside(jquery).
see below example-
RemoteAttribute
The new RemoteAttribute validation attribute takes advantage of the jQuery Validation plug-in's remote validator, which enables client-side validation to call a method on the server that performs the actual validation logic.
In the following example, the UserName property has the RemoteAttribute applied. When editing this property in an Edit view, client validation will call an action named UserNameAvailable on the UsersController class in order to validate this field.
public class User {
[Remote("UserNameAvailable", "Users")]
public string UserName { get; set; }
}
The following example shows the corresponding controller.
public class UsersController {
public bool UserNameAvailable(string username) {
return !MyRepository.UserNameExists(username);
}
}
Mvc 3
UPDATE
public bool UserNameAvailable(string Propertyname)
{
if (Request.QueryString[0]= "UserName")
{
//validate username
}
elseif (Request.QueryString[0]= "Email")
{
//Validate Email
}
}
ASP.Net does have a feature that can automatically check the uniqueness of a user's email address when a user registers. It is the ASP.Net Membership service and you can use it to do what you want even if you don't use all of the features of it.
If you are not using the full Membership feature in your MVC application, then all you need to do is use
Membership.FindUsersByEmail(emailYouAreLookingFor);
If any values come back, you know that the address is not unique. If you ARE using the Membership service to create users, then the Membership service will check AUTOMATICALLY and return a code to you if the user's email address is not unique.
The Membership service sits in the System.Web.Security area so you would need a
using System.Web.Security;
reference in your controller.
Here is an example
MembershipCreateStatus createStatus = MembershipService.CreateUser(UserName, Password, Email);
if (createStatus == MembershipCreateStatus.DuplicateEmail)
{
//do something here
}
else
{
//do something here
}
I hope this helps!
The right way to make a generic remote unique validator in MVC can be found in this MVC forum. by counsellorben. It's based on my MVC unique remote validator article http://msdn.microsoft.com/en-us/library/gg508808(VS.98).aspx
A foolproof way of doing this is to create a validation attribute that would query the database for the email address. It would certainly add latency.
An alternative would be to create a unique constraint on the table and intercept SqlException.

Resources