Spring MVC disallowing fields for specific controller/controller's method - spring-mvc

I know that I can set allowed fields within the method that is annotated with #InitBinder by calling setAllowedFields on WebDataBinder object. But can I do the same, but only for a specific controller or controller's method? I have a simple form that allows a guest to create a user account and I have another form that allows the login user to update his/her information. In the first form, I want to allow user to insert all the fields(username, password, etc), but in the second form, I want to disallow user to change one of the fields that are allowed in the first form(for example, I want to disallow user to change his/her username). How can I do that?

Apparently you can do that by just defining in each controller a method annotated with #InitBinder. Each #InitBinder method and the settings you make in this method are dedicated to the method handlers defined in the controller that contains the method annotated with #InitBinder.Thus,in my case,i just could define another method annotated with #InitBinder in another controller and set whatever fields i want to be allowed there.

Related

Spring Data, updating MVC partial entity

I'm new to Spring, Spring data and Spring MVC so I want to make sure I am not missing something.
I have a form for updating a User object, the form posts to a controller and the controller calls my service class that updates/add the entity using a UserDOA which extends CRUDRepository. I think this is a very basic test code.
The issue is that the form doesn't contain all the fields in my User class, so when the object is posted to the controller, only the fields that are contained in the form are populated and the entity fields that are not in the form are null. For example my user has 4 fields, firstname, lastname, age, password. The form only contains the first 3 fields so when the object is posted to the controller, the password field is null, that is as I expect. My issue is that if I then call save(entity) on my DAO it will update the user but that would include nulling the password field, which of course is undesirable.
Of course I could simply retrieve the original entity from the repository and merge it with only the fields that have been updated, but it seems to me this is a lot of work that would be very commonly required and typically spring has a solution to these types of generic tasks.
Did I miss something?
TIA

Trying to obtain the current logged in user's ID for tracking fields

I am following this really good tutorial to setup a BaseEntity class that will contain 5 fields:
Active, DateCreated, UserCreated, DateModified, UserModified.
All of my entities that need these tracking fields will inherit from this class.
In the small tutorial below he shows me how to override the SaveChanges() method in my dbContext so that these fields will be set properly based on Creation/Updating.
I am trying to figure out how I would store the current logged in user's ID rather than the Name to the UserCreated and UserModified fields
Please let me know if the UserID shouldn't be what I am storing. This is always what I used to do in some of the webforms apps I created back in the day.
Also, what would be the best way to setup Active to always be true when adding new records. Should this be done in the db context also or within my BaseEntity class. I'm thinking I would create a function in the BaseEntity class called Disable() that will change Active=False.
Please view the small tutorial that I am using
You could create a custom implementation of IIdentity/IPrincipal which contains the UserID. Then you can retrieve this value from the Context or Thread and cast it to the correct type.
Set HttpContext.Current.User from Thread.CurrentPrincipal

Check if curent user has access to specified MVC path

I need to extend asp:Menu to support linking to MVC routes (my project has a mix of MVC and non-MVC pages). My menu is generated using a custom class which determines if a user should be shown a node based on their priveleges to the file it referes to.
MVC pages are restricted using the AuthorizeAttribute. Avoiding mocking (if possible) I want to
Determine if the path refers to an MVC page or a standard page
If MVC, determine if the user has the rights to access it
Here's my method signature inside the menu generation class:
Private Function CanAccessPage(path As String) As Boolean
Here's the algorithm I used for this,
Based on #SLaks answer here, I was able to determine if the path referred to an MVC route.
If it was MVC, I grabbed the controller type (this required knowing what namespace my controller's were in)
Got the action method by controllerType.GetMethods(actionMethodName) (if you have multiple methods with the same name, you must pick the one your link refers to. Probably the one with an HttpGet attribute).
Used actionMethodInfo.GetCustomAttributes(GetType(AuthorizationAttribute), False) to get a collection of all authorization filters for the specified action
Called OnAuthorization with the fake context info I build in step 1 for each attribute.
Check if TypeOf filterContext.Result Is HttpUnauthorizedResult and return accordingly

Pass additional parameter to Custom Membership provider's ValidateUser()

I have a class "User" that is inherited by two other classes(LocalUser and Donor). I have created a custom membership provider for ASP.net forms authentication and overridden the ValidateUser() method. In the ValidateUser() method of my custom membership provider, I need to pass in a parameter to know whether the "User" to validate is "LocalUser" or "Donor" and accordingly validate the user against the database. The problem is that ValidateUser() takes only two parameters (username and password). So there is no scope for me to push in another one. One thing that came to my mind was to set a session variable but then I was looking for a cleaner approach. Any suggestions?
Just create an overridden version of your Validate method, taking 3 parameters and call it directly like:
((MyCustomMembershipProvider)Membership.Provider).Validate( username, pass, anything );
The only drawback of such approach is that you can no longer rely on the automatic invocation of the two-parameter version of the Validate method, if and only if it is automatically called from somewhere (for example from the asp:Login control)
You could send both username and usertype in username field and then parse it in ValidateUser method? Like this: username|userType. Of course, you should forbid entering delimiter in username field.

ASP.Net MVC elegant UI and ModelBinder authorization

We know that authorization's stuff is a cross cutting concern, and we do anything we could to avoid merge business logic in our views.
But I still not find an elegant way to filter UI components (e.g. widgets, form elements, tables, etc) using the current user roles without contaminate the view with business logic. same applies for model binding.
Example
Form: Product Creation
Fields:
Name
Price
Discount
Roles:
Role Administrator
Is allowed to see and modify the Name field
Is allowed to see and modify the Price field
Is allowed to see and modify the Discount
Role Administrator assistant
Is allowed to see and modify the Name
Is allowed to see and modify the Price
Fields shown in each role are different, also model binding needs to ignore the discount field for 'Administrator assistant' role.
How would you do it?
On way I could think to do this is create your own versions of the input extension methods. For example instead of TextBox you could create TextBoxRoles and define it like this:
public static MvcHtmlString TextBoxRoles(
this HtmlHelper htmlHelper,
string name,
string RolesEdit,
string RolesView
)
Then in code it would look like this:
<%= Html.TextBoxRoles("Price", "Administrator","Administrator,Assistant") %>
Then your implementation of TextBoxRoles would check the roles of the current user via User.IsInRole() to determine what should appear on the page.
Of course you would have to do this for every input extension method you use.
Since you already have both the current user and access to the authorization provider in your controllers this is an ideal responsibility for them. Using a naive implementation you might pass a collection of widgets to your view after you filtered which widgets the current user has access to. In the case of your form field, things might get hairy when you consider client side validation.
The binding part would be the most straight forward of all, having a custom binder for these special cases will do the trick specially well since it will have access to the controller context and you can grab the current user from there and bind the values according to your role definitions.
What about something like LinFu, an AOP framework? If it's crosscutting, then declare it is so and treat it as such.

Resources