Reputation: 13995
MVVM is based on bindings and commands. I understand that bindings for IsEnabled
, IsReadOnly
, Visibility
and commands' CanExecute
can help to implement GUI which will take permissions into account.
Yet I have some doubts about this approach.
The first one is the need to accompany each ACL-logic involved property of VM with CanRead
| CanWrite
property that can be bound to the corresponding control. This implies much infrustructure coding and XAML typing for bindings. Dynamic tooltips explaining the reason also can be added to the list.
The second one is that mistyping in XAML can break security especially concerning read permissions: control will stay visible. This problem can be solved in most(not all) cases by the Busines Logic layer which leaves properties with deafult values. But on "the way back" (VM->BL) system must care only about allowed properties.
Security is dubbed a crosscutting concern. I understand how AOP or DI with interception can help with security at BL level but I have no good ideas about implementing all this stuff for GUI in the context of MVVM design pattern.
Could you share your experience of solving this problem, please.
Upvotes: 0
Views: 1445
Reputation: 15705
In my opinion and experience, the UI should never be used to enforce security, merely present to the user what they can and can't do, according your business logic (BL). This prevents the issue of XAML typos causing a breach, and furthermore, there are about a billion utilities and hacks out there to analyze / make a UI do what the user wants it to do.
For example:
http://newtipstrik.wordpress.com/2012/02/06/win-enabler/
http://snoopwpf.codeplex.com/
In summary, yes, your UI should only be 'aware' of the security context, rather than implementing all or part of it.
Upvotes: 0
Reputation: 30498
Depending on your application, this can be somewhat difficult, but I generally solve this sort of concern using Prism modules. Obviously if you aren't using Prism, this won't help at all.
For instance, if a user only has read-only access to certain data, I would load a completely different view in the module responsible. Or, if they have no access, that module wouldn't load anything. That way, you can write separate views for read-only and read-write access.
I suppose you could go further and also swap out the ViewModels, but I haven't needed to do this.
It is important to note that my apps use authenticating using the User's Windows credentials (and membership roles in our corporate AD), so this can be handled at startup. If you have a different login/credentialling system, you would probably have to modify the bootstrap to wait for login before loading the modules.
Upvotes: 0
Reputation: 1405
In my opinion, MVVM is actually a good way of solving the problem you just solved. As MVVM is really a matter of separating the UI from the code, you can really do "whatever" you like in the UI (view) and place all logic to the model. This is logic like privileges and "flow" in the control.
This way, the coder (which often design poorly) can create the logic to the control. Like when can the user save, delete, open, as well as checking privileges and stuff the designer don't need to know. And the designer (which often cannot code good) can decide how the user can use the control. Like wether saving should be done from a button, a contextmenu or a toolbar. The model/logic can even be placed in an own DLL where the designer cannot see it, and only use the available properties available.
The responsibility lies compeltely with the coder, and is placed in the model.
To me, MVVM is not "based on bindings and commands". Bindings and commands can be used very well in a non-MVVM way of coding. But I understand it can be confusing, as MVVM push the programmer to use commands and bindings more than usual. But it's not really about that. It's about separating logic and UI so problems like you explain may be solved the best possible way :-)
That's at least my thoughts around MVVM and privileges and access control.
Hope I didn't misunderstand your question absolutely.
Upvotes: 0
Reputation: 44048
What I did was to create the concept of "fields" at the ViewModel level. These fields are essentially an abstraction of the "properties for each property of the Model".
For example, the field "OrderNumber" in the "Order" ViewModel has its ReadOnly property set to True, and the field "Name" in the "Account" ViewModel has its Required property set to true (which is more a Business Logic thing than a security, but anyways I encapsulate these kind of things in the fields).
Then I created several Attached Properties in a special class for XAML usage, and a special container (the "Field Editor"), which in its default style has a bunch of bindings pointing to these fields in the VM. The container (which is actually a ContentControl), walks down its visual children when, for example, the "IsReadOnly" property is changed, and sets any TextBoxes, ComboBoxes, etc to a read only state (with a huge switch statement, because you might want to set different properties for different controls).
Upvotes: 1