You can use the authenticated user's model object to control which ViewModels, actions, and fields a user can see or change; this page is for modelers defining authorization rules in MDriven.
Authentication and authorization
Authentication establishes who the user is. Authorization establishes what that authenticated user may view or do. Your hosting platform performs authentication, using the mechanism chosen for that platform, such as federated authentication, local Active Directory authentication, or forms authentication.
Your MDriven model must then be able to reach the authenticated user. For example, an ASP.NET Identity model can contain a user object and that user's claims. Connect the current user made available by the platform to the corresponding user object in your model before you evaluate authorization rules.
This page covers declarative authorization in the model. For the security boundary and server-side data reduction provided by MDriven Turnkey, see Training:Information security. For deployment and service-authentication settings, see Training:Security concerns for MDriven Server.
Make the current user available to OCL
Object Constraint Language (OCL) expressions can evaluate authorization rules only when they can navigate to the current user. A common model pattern is a singleton: a class that has one object instance for the system.
- Create a class named
SysSingleton. - Add a link from
SysSingletonto your user class and name the roleCurrentUser. - Make the link derived so its expression resolves the user associated with the current session.
- Use
SysSingleton.oclSingletonwherever an OCL expression needs the singleton instance.
The oclSingleton operator returns the sole instance of a class. If no instance exists when it is requested, one is created. With the derived CurrentUser link in place, an expression can test a user property from any relevant model context.
For example, if the user class has an IsAdmin property, an authorization expression can be:
SysSingleton.oclSingleton.CurrentUser.IsAdmin = true
Use names that match your domain. For example, a role-based test can be written as:
SysSingleton.oclSingleton.CurrentUser.SysRoles->exists(name = 'fisherman')
Choose the right authorization level
Apply a rule at the level that best represents its purpose. Keeping broad, repeated rules in one place reduces duplication, while expressions on individual elements provide the precision needed for a particular use case.
| Requirement | Where to define it | Example |
|---|---|---|
| The same user requirement applies to several actions or ViewModels. | An AccessGroup. | Put administrative actions and administration ViewModels in a MustBeAdmin group.
|
| An action is available only when the current user and the current object meet a condition. | The action's Enable expression. | Enable an action only when the current user is an administrator and the root object is in an allowed state. |
| A field or placed widget must not be shown or changed in a view. | The widget's Visible and/or ReadOnly expression. | Show a sensitive value only to an administrator, or make it read-only for other users. |
| No part of a view may be edited, or the entire ViewModel must not be opened for its root object. | The view's ReadOnly expression or the ViewModel's Access expression. | Do not open a case ViewModel when the current user is not allowed to access that case. |
Centralize repeated rules with AccessGroups
Use an AccessGroup for a static authorization rule that applies to multiple actions or ViewModels. An AccessGroup keeps the rule and the things governed by that rule together.
- Open the AccessGroups dialog.
- Create an AccessGroup, for example
MustBeAdmin. - Define the group's Enable, Visible, and View expressions. Each expression must evaluate to
trueorfalse. - Add the actions and ViewModels that belong to the group.
- Test with users that meet and do not meet the group condition.
For example, the expressions for MustBeAdmin can use:
SysSingleton.oclSingleton.CurrentUser.IsAdmin = true
An AccessGroup is best for rules based on the logged-in user, such as membership in a role. Use an element-level expression when the decision also depends on the object currently shown. For a fuller explanation of these levels, see Training:Access control system in MDriven.
Control actions and widgets
Use an action's Enable expression when an action needs a condition more specific than a shared AccessGroup. For example, an action can remain visible but be unavailable when its rule evaluates to false. This lets the user see that the action exists while preventing its use.
In a view, set a placed widget's ReadOnly expression to prevent edits without hiding the value. Set its Visible expression when the value must not be displayed. You can also set ReadOnly on the view level; this affects all widgets in that view.
Protect access to an entire ViewModel
Each ViewModel has an Access expression. Unlike a user-only AccessGroup rule, this expression can evaluate both the current user and the ViewModel's root object.
For example, a case ViewModel can use an Access expression that verifies that the current user is permitted to access the current case. When the expression evaluates to false, MDriven looks for a ViewModel named AccessDenied and shows it instead. If no AccessDenied ViewModel exists, the user sees a blank screen.
Create an AccessDenied ViewModel so users receive an explicit denial view rather than a blank screen.
Do not leave an action enabled when it will open a ViewModel whose Access expression is false for the selected root object. In the action's expression, test the target ViewModel with the OCL canAccess(vmname):bool operator.
This check lets you:
- Disable an action before it opens a denied ViewModel.
- Avoid creating a report from a ViewModel and root object that fail that ViewModel's Access expression.
Design and test authorization rules
- Identify the user properties, claims, or roles that represent the access decisions in your domain.
- Make the current authenticated user reachable from
SysSingleton.oclSingleton.CurrentUser. - Put repeated, user-based rules in AccessGroups.
- Add Enable, Visible, and ReadOnly expressions where an individual action or widget needs a more precise rule.
- Add a ViewModel Access expression where access depends on both the user and the ViewModel root object.
- Provide an
AccessDeniedViewModel. - Test every rule with at least one allowed user and one denied user, including navigation and report scenarios.
Authorization expressions execute declaratively in the model. Keep their terms close to the domain language used by the people responsible for security decisions; for example, use role names and permissions that they can recognize and review.
