Rails - permissions to view specific attributes - ruby-on-rails

I want to be able to share a link to a Property model whilst setting permissions on which attributes the recipient can see. I've been through a few different ideas but none of them have felt 100% right. The closest I think I've come is this:
Have a Share model that belongs to Property. It also has an attribute called permissions which is a string.
On the create Share page I generate a series of checkboxes using Property.column_names. The benefit of this part is that I can add more attributes to Property without needing to change any code. Before the Share is created it converts the permissions params into a string.
When the user visits the Share page I can convert the string into a hash and then in the view check whether each attribute is present. If it is present I display the data, if not I don't.
Storing this data as a string seems wrong but I haven't been able to come up with a viable alternative. I could store each attribute on the Share model as a boolean but that would mean adding a new attribute to Share every time I add one to Property.
Any suggestions on how to tackle this?
Thanks.

Related

ASP.NET MVC3 model with list

I have a minor problem in MVC 3. I'm creating an application, where my model, a shipment, consists of the following:
a user id (string, required)
a reference id (string, optional)
a list of order ids (strings, cannot be empty)
The index view of the application is where the user creates the shipment (model). Once this is done, the user has no further interaction with it (no edit, detail or list views).
My problem is this. I'm trying to use one form for both adding order ids, and for creating the shipment itself, using two separate buttons for submitting ("Add" for adding order ids, "Send" for creating the shipment). It seems that when I'm using the Create-action of my controller, that pressing "Send" overwrites my list of order ids with an empty one. However, if I'm submitting to the Index-action, and redirecting to Create on a press of "Send", my model validation is gone (ModelState only contains "submit").
Right now I'm using sessions to pass data around my controller actions, which is probably not the best way to do it.
TLDR; I need a way to add items to a list in a model, one at a time, while persisting other form data, and still be able to validate it.
Any suggestions?
It's better to take a look on your Actions, because it's not quite clear what are you doing there, but still it looks like you are tring to use same data structure to pass different tipes of parameters (one contains list, another contains general data). I think it's better to submit different data structures and build required result data object in each action.

MVC4 - getting list of fields in View

Is it possible to safely programmatically get a list of fields that are in the View that has just posted back to a Controller?
I noticed a problem with the default implementation of the scaffolding, in
DB.Entry(model).State = EntityState.Modified
DB.SaveChanges()
The problem is that if I haven't included a field to be edited in the view, it is being overwritten by the default value of the field that .NET assigns when creating the object. eg. If I have a User class with ID, Email and PasswordHash and I want to allow the user to update their Email address only, if I don't include anything for the PasswordHash field, it is reset to NULL as it is passed into the controller as NULL. At the moment, I am working around it by retrieving the current object from the database and updating only the fields which I know are in the View from the model passed in. That isn't such a problem for a small table, but I would like to have a general solution that I can apply across the board, especially for large tables which may during development and I don't want to have to update the code every time.
I know that I could loop through the POST variables and examine them to see what has been posted, but that creates a security issue as the user could inject additional fields that I don't want them to edit. I suppose I could explicitly exclude ones that I don't want them to edit, but then again, I would rather not have to list those if I can avoid it as it is an extra thing to maintain.
I think that there are 2 problems here and I'm not sure either are solvable...
Getting the View that posted back
Establishing which fields are included in that View (I might need to construct it again temporarily to do that?)
I suppose that I can probably get away with ignoring the first one as I could just only ever use that method on the Controller for a single View. That is still a little less neat than I'd like, but it does reduce the issue to just establishing which fields are in the View.
If a view needs only certain properties, create an interface with only those properties. Use this interface in the HttpGet and HttpPost methods.
And then you can use something like AutoMapper to map the viewmodel to your entity.

MVC Razor How to get the model in the Controller on HttpPost when the model is dynamic

I'm working a feature in the application where model will be dynamic in the sense that any settings data could be displayed and the view will get the model based on what tab they clicked on. I use Hidden field to store what the settings name was because they are same as model name. for ex., if tab1-> Settings1 then Model is Settings1[already exists in the Model].So I used # model dynamic in View and used #Html.EditotForModel() to draw the required UI based off the model. My problem is when I do HttpPost on Edit currently I'm using FormCollection to read the data on that page when I declare the model name in the param it will get it for me but I don't know which model is coming back other than by the Hidden variable and I need it because the Model validation is broken because of this issue. Any help or feedback is appreciated? I can give more details if required? Has anybody crossed this issue before??
Dynamics can be a good thing and a bad thing. Using them on models that have a common interface in a controlled manor is best.
There are different options that you can look at:
1)
Have you tried making the action method accept a dynamic type? That might be the easiest way.
You might have to set up a casting helper to cast the object to the correct type based on the hidden field.
2)
I have a similar idea in some code, but I created a viewmetamodel class that contained all my types as nullable properties. My action method accepts this viewmetamodel type and validates the properties that are not null.
In line with this, if your data is not too large, then you could load all the settings tabs and use Jquery apply the tab with on click.
3)
You could also create #sections or use EditorFor(c=>c.settings) for each tab. That way each tab will load a type safe object. You would need to create controllers for each.
I would say pick the easiest method for you. I hope that this at least gives you some ideas.

How can I modify the queryset in the change list view depending on a parameter I set in the URL

My problem is the following and it is related to the change list view of the admin interface.
I have a workorder model with several fields to caracterize the work order.
They are : type, nature, scheduling_type (and others).
When I see the list view, I would like to be able to change the filter (thus be able to create complex ones depending on the values of the different fields of the workorder model - the ones above and dates for example).
I have found post showing how to modify the default queryset (using managers for example) but I can't find a post that will use a value that is given in the url (ex. admin/workorder/planned_corrective). When the parameter planned_corrective is found, it must be used to select the appropriate queryset or manager and render the corresponding list.
As a add on, I want from that list to be able to use the standard admin options (like list filters, search ...) on that query.
Hope it is clear and thanks in advance for your help.
It sounds like you're after a RESTful interface.
You could accomplish much of this just by being clever with your urls.py - ie, defining admin/workoder/planned_corrective and every other possible parameter that could be encoded in the URL.
A lot of this can also be accomplished just by adding a get-absolute-url method to your models.
Or, you could the effort into using something like the django-rest-interface in your app.

Make all form fields readonly in MVC

I am displaying 3 or more versions of a form. One version is an edit form to edit all fields. A second version will be a read only version of the same form which will be used to show all the same fields but with all fields having readonly="true" on the client side so that the user cannot enter data. The readonly fields need to use a different css style. This is to display archived data. I am already hiding the submit button so they can't submit but I want the form to look like it is readonly. A third version will have some fields readonly and some editable for a particular class of users that has limited editing privileges.
I am using ASP.NET MVC 1.0. How do I modify all (or a subset) of the fields displayed so they are readonly. I would like to iterate through the collection of fields in the controller and set them all to readonly and also set the correct css class. I don't want to have to put an if statement on every field in the .aspx file (there are 40-50 fields) and I'd prefer not to have this on client side so I can prevent users from modifying javascript/html to edit things they are not supposed to.
TIA,
Steve Shier
Keep in mind that even if you set the tags as readonly on the server side, users can still change them through a variety of means, and whatever the value on the form is before it gets sent back to you.
Certainly the easiest way is client-side with jQuery:
$(function() {
$('input, select, textarea').attr('disabled', 'disabled');
});
Or, you could do it in your View, but it's ugly. Off the top of my head, you would need some sort of bool passed into the View (via ViewData I suppose), and check that on each Input to see if you should add the disabled attribute. Not my idea of fun...
I would have different views that correspond to your states and then choose the view depending on which state you are in. You could also implement it with partials, breaking down the pieces so that you can easily include editable or read-only versions of the different sets of elements. The read-only view, then, need not even include a form element. You could also present the data in spans, divs, or paragraphs rather than as input elements.
Note: you'll still have to check whether the current user has the ability to update/create data in the actions that process form submits. Just because you limit the ability to view data in a read-only format, that won't stop someone from crafting a form post to mimic your application if they want. You can't rely on hiding/disabling things on the client to prevent a malicious user from trying to enter/modify data.
I usually use partial views to represent forms and/or parts of forms.
I can think of two simple ways to do what you need (as I understood it):
<% Html.RenderPartial(the_right_partial, model); %> where the_right_partial is either a value passed from the controller or a helper (in which case, the_right_partial(something));
pass a bool or enum paramether from controller representing editability and then using a helper to obtain the right htmlAttributes, like:
<%= Html.TextBox("name", value, Html.TheRightHtmlAttributesFor(isReadableOrNot)) %>;
There may be other ways, like creating new helpers for input fields which accept an additional isReadableOrNot arg (but it seems an overkill to me), or like mangling the html/aspx in some odd (and totally unreadable/unmaintainable way), but I'd not suggest them.
Notice that using html attributes like disabled is client side, and with tools like firebug it takes just two seconds to change them.
Others have already said it, but I also have to: always assume that the user will do his/her best effort to do the worst possible thing, so check the user rights to modify stuff on server side, and consider client side checks as a courtesy to the user (to let her/him understand that the form is not supposed to be edited, in this case).
Since I am trying to use a single partial for the different states of the form, I am thinking I will create helper functions which will display correctly based on the state and the user. The helpers will use a dictionary of fields that will indicate under which condition the field is read only. I will still have server side checks to make sure data is valid and the user is authorized to make changes.
Thanks for all of your ideas and help.
Steve

Resources