In many projects, it is important to distinguish the active user, mainly for the mobile client. Mostly, it is required to just restrict access to certain users. Often, there are also different groups of users that should have different rights to view, edit, create or delete objects. In some cases, the content provided to the mobile client should depend on the active user. This How-To explains how to configure users and how to customize a UBIK® application depending on the active user.
Managing user accounts
The first step in any case is to create and organize accounts for users. In some case, users have to be imported from an external system, which is best done using Proxies (see also how to Configure Proxies). However, accounts can also be created manually or programmatically. In any case, the following information is relevant.
Login
In UBIK®, an account object is called Login, with the system MetaClass LOGIN. Theoretically, a user can have multiple such login credentials, but normally, you'd have one per user. If there are multiple logins for one user, you can create a custom meta class for the users and link the login objects to them via the CONSUMER Reference property (see also how to Relate Objects). You can also create a derivation of the LOGIN system meta class to add further details for the instances. A login object has the following important properties:
- LOGINNAME: The account name
- DOMAINNAME: The domain name
- SYSADMINRIGHTS: Whether the user has administrator privileges in UBIK® Studio
- USE_DOMAIN_CREDENTIALS: Whether to use Active Directory for authentication
- PASSWORD: The password
- CONSUMER: A link to the person this login is associated with (useful if there are multiple accounts per person)
So, the steps to create a login are:
- Find the system meta class LOGIN and drag it into a new bulk editor.
- Create a new instance, filling in at least the LOGINNAME, the DOMAINNAME and the PASSWORD.
- Save the new instance.
User groups
Login accounts are best managed in groups corresponding to roles, e.g., "Administrator" or "Engineer". This is important if you don't want to distinguish by account individually, but more generally by their role. This allows you to add new logins (to existing groups) without having to adapt your customizing. There is a system meta class USERGROUP that can be used for this. Similar to the way you would link multiple logins to a user, you can also relate multiple users to one or many groups (there is a system relation for that, SYSREL_GROUP_LOGIN).
If you have just one group of users (i.e., all the users have the same rights or highly individual rights), it is not necessary to configure groups.
The steps to create and apply a group are:
- Find the system meta class USERGROUP and drag it into a new bulk editor.
- Create a new instance, filling in the name
- Save the new instance.
- Drag the new group into a relation browser.
- Find the login(s) you want to associate with the group and drag it onto the relation node for SYSREL_GROUP_LOGIN (relation between groups and logins).
- Save the changes.
User rights
There is a programmatic framework for group-specific rights in UBIK® that is highly customizable. Currently, UBIK® requires you to add some logic for the evaluation of user rights, so get ready to do some coding!
Defining rights
First, it will be necessary to define what rights there should be. In general, it should be possible to control whether a user is allowed to view ("read"), edit ("write"), create and delete data. Creation and deletion rights usually can be subsumed into the right to manipulate ("write") data. Fortunately, there is already an enum UBIK.Kernel.UserRights describing the three possible rights and mapping them to integer values:
- NoRight = 0
- Read = 10
- Write = 20
So, nothing for you to do yet.
Configuring rights
So we have the basic definitions for reading and writing. Now we have to apply them to use-cases, respectively, objects and users (or better, groups). E.g., if it should be possible to control the rights for editing an object's properties, one could relate the respective user group to the object and set the right on the relation data object. Then, the group is related to the target object, with the respective right as a property of their relation connection.
The next steps will be to create a Relation with a custom relation data meta class defining a property for the rights configuration:
- Create a new Relation plus relation data meta class.
- The left target meta class should be any object (i.e., BASECLASS), whereas the right target meta class should be USERGROUP or LOGIN, depending on whether you're using groups or not.
- Add a new MetaProperty for the user right to the relation data meta class, e.g., MP_USER_RIGHT. It should be an integer property, so we can store values from the UserRights enum in it.
Now you have the possibility to describe rights between users (respectively, groups) and any object, just by creating a relation between them and setting the respective right on the relation data instance.
Evaluating rights
Now that we have defined and configured rights, we have to evaluate them. This can be done by customizing the methods CustomGroupRights and CustomPropertyGroupRights for any meta class.
Controlling the visibility and editability of objects
- Find the meta class of objects you want to control the rights for.
- Customize its method CustomGroupRights.
- Find relation instances between the current object (or its meta class) and user groups.
- Read the custom rights from the relation data objects connecting the target object and a user group.
- For each combination, create a new instance of UBIK.Service.DTO.V240.GroupRight and assign both the group and the right.
- Add all GroupRight instances to a result list and return it.
UBIK® will take care about the rest, i.e., applying the rights.
Controlling the visibility and editability of properties
This works basically the same way as for whole objects, just with a different method to override:
- Find the meta class of objects you want to control the rights for.
- Customize its method CustomPropertyGroupRights. Note that there is a parameter metaPropertyName, so this is about a specific property.
- Now it becomes interesting, because you have many options depending on the degree of detail you want to control the property rights for:
- On meta class level: If the rights for every property are the same for all instances of a meta class, but differ by user, you should evaluate the relation between the meta class and the user group.
- On meta property level: If the rights for a property are the same for all instances of a meta class, but differ by meta property and user, you should evaluate the relation between the meta property and the user group. If a meta property is used on multiple meta classes with different rights, you may have to evaluate the relation between: A) the relation between meta class and meta property and B) the user.
- On content object level: If the rights for every property are the same for the same content object, you should evaluate the relation between the object and the user group.
- On property level: If the rights for a property depend only on the user, you should evaluate the relation between an attribute on the property and the user group. (An attribute is needed because you can't relate a property to anything).
- Read the custom rights from the relation data objects connecting the target object and a user group.
- For each combination, create a new instance of UBIK.Service.DTO.V240.GroupRight and assign both the group and the right.
- Add all GroupRight instances to a result list and return it.
UBIK® will take care about the rest, i.e., applying the rights.
Rights are evaluated by the server; so for the mobile client, there is no offline support for the dynamic evaluation of user rights yet (when this article was created). |