Role-Based Access Control (RBAC) #

Role-based-access-control (RBAC) is a policy neutral access control mechanism defined around roles and privileges. The components of RBAC such as role-permissions, user-role, and role-role relationships make it simple to perform user assignments.

Create a role in the system and the user in it, who can log on to the portal as the department employee and view the requests addressed directly to this department. Also, he will be able to change the status, give an answer, but he will not be able to create a new request.

It’s good practice to get a user with the supervisor role and work under this user, who can give rights to others, and controls what other users do, but he can’t change the data himself.

Creating users and roles #

Create a new role in a system

role_menu

role_creating

Create a new user for the role in the Administrator -> Groups and Users -> User list menu and add him the role. Set password for the user.

new_user

Access to the desktop and menu items #

It is advisable to use it on an already completed project.
Go to the Desktop or Shortcuts menu and add a role

desktop_right

Add the rights for Education Department to the City Requests Desktop and Request List.

Entity level security #

Create rules for a specific role so that department users can only read and update existing applications.

Create permissions to read and modify records for the req model in the Administrator -> Security -> Entity level security menu. The user of departments cannot add or delete records.

els

"Entity mask" are the names of entities that begin with req.
"Method mask" are the methods, names of which start with s and u (select and update).

Reboot the UB server and check if rules are applied correctly.

Creation of the role, user, and rights to shortcuts and entities with js-code #

Repeat all the actions that were performed above, for the HealthDepartment role with js-code.
This is a better way to quickly install a preconfigured project.
Create the new file 030_setRole_navshortcuts.js in the folder models/requests/_initialData/
This code does the following

  • create new user hd_user
  • create HealthDepartment role
  • add hd_user to HealthDepartment role
  • provide rights for CityRequests Desktop to HealthDepartment role
  • provide rights for Request LIst shortcut to HealthDepartment role
  • provide rights for req* entities to HealthDepartment role
  • create new user super and set him system supervisor role
module.exports = function(session) {
    var
        desktopID, usersRoleID, folderID, lastID, userID, conn = session.connection;

//hd_user and Health Department role
    userID = conn.lookup('uba_user', 'ID', {expression: 'name', condition: 'equal', values: {name: 'hd_user'}});
    if (!userID) {
        console.info('\t\tcreate new `hd_user` user');
        userID = conn.insert({
            entity: 'uba_user',
            fieldList: ['ID'],
            execParams: {
                name: 'hd_user',
                firstName: 'hd',
                lastName: 'user'
                //,uPasswordHashHexa: nsha256('salt' + 'hduser')
            }
        });
    }
    usersRoleID = conn.lookup('uba_role', 'ID', {
        expression: 'name',
        condition: 'equal',
        values: {name: 'HealthDepartment'}
    });
    if (!usersRoleID) {
        console.info('\t\tcreate new `HealthDepartment` role');
        usersRoleID = conn.insert({
            entity: 'uba_role',
            fieldList: ['ID'],
            execParams: {
                name: 'HealthDepartment',
                description: 'Health department role'
            }
        });
    }

    var checkUserInRole = conn.lookup('uba_userrole', 'ID',
        conn.Repository('uba_userrole').where('userID', '=', userID).where('roleID', '=', usersRoleID).ubRequest().whereList
    );
    if (!checkUserInRole) {
        console.info('\t\tadd hd_user to Health department role');
        conn.insert({
            entity: 'uba_userrole',
            execParams: {
                userID: userID,
                roleID: usersRoleID
            }
        });
    }


    desktopID = conn.lookup('ubm_desktop', 'ID', {
        expression: 'code',
        condition: 'equal',
        values: {code: 'CityReq_desktop'}
    });
    if (desktopID) {
        var checkRoleInDesktop = conn.lookup('ubm_desktop_adm', 'ID',
            conn.Repository('ubm_desktop_adm').where('instanceID', '=', desktopID).where('admSubjID', '=', usersRoleID).ubRequest().whereList
        );
        if (!checkRoleInDesktop) {
            console.info('\t\tprovide rights for `CityReq_desktop` to HealthDepartment role');
            conn.insert({
                entity: 'ubm_desktop_adm',
                execParams: {
                    instanceID: desktopID,
                    admSubjID: usersRoleID
                }
            });
        }

        lastID = conn.lookup('ubm_navshortcut', 'ID', {
            expression: 'code',
            condition: 'equal',
            values: {code: 'req_reqList'}
        });
        if (lastID) {
            var checkRoleInShortcut = conn.lookup('ubm_navshortcut_adm', 'ID',
                conn.Repository('ubm_navshortcut_adm').where('instanceID', '=', lastID).where('admSubjID', '=', usersRoleID).ubRequest().whereList
            );
            if (!checkRoleInShortcut) {
                console.info('\t\tprovide rights for `req_reqList` shortcut to HealthDepartment role');
                conn.insert({
                    entity: 'ubm_navshortcut_adm',
                    execParams: {
                        instanceID: lastID,
                        admSubjID: usersRoleID
                    }
                });
            }
        }


    }

//entity level security
    var checkCodeEls = conn.lookup('uba_els', 'ID',
        conn.Repository('uba_els').where('code', '=', 'READ_UPD_REQ_HD').ubRequest().whereList
    );
    if (!checkCodeEls) {
        console.info('\t\tprovide rights for `req*` entities to HealthDepartment role');
        conn.insert({
            entity: 'uba_els',
            execParams: {
                code: 'READ_UPD_REQ_HD',
                entityMask: 'req*',
                methodMask: '[su]*',
                ruleType: 'A',
                ruleRole: usersRoleID,
                description: 'Read and update requests model'

            }
        });
    }

// create user super

    console.info('\tAdding user "super" with supervisor role')
    var superUserID = conn.insert({
        entity: 'uba_user',
        fieldList: ['ID'],
        execParams: {
            name: 'super',
            description: 'Defaults user with supervisor priviledges'
        }
    })
    conn.query({
        entity: 'uba_user',
        method: 'changeOtherUserPassword',
        execParams: {
            newPwd: 'admin',
            forUser: 'super',
            needChangePassword: false
        }
    })
}

Run the script with the initialize command
ubcli initialize -u admin -p admin -host http://localhost:8881 -m requests

If you want to initialize the script without executing some js-files, put the symbol _ at the beginning of the file name. If you want to create a new project with already created users, roles and rights for them, the link to the complete code is here

Row level security #

In oreder to restrict user of the department to see only the records addressed to him, you need to configure the rights to read certain records.

To be able to associate the system role user and department from the list of applications, you need to add a new attribute to the entity req_department in req_depart.meta file, associated with the entity uba_role (system roles)

 {
     "name":"roleInSystem",
     "dataType": "Entity",  
     "associatedEntity": "uba_role", // association with other entity 
     "caption": "Role in System", // caption of the object on AdminUI  
     "allowNull": true //it can be empty.
 }

Update the model with the command
ubcli generateDDL -u admin -p admin -host http://localhost:8881 -m requests -autorun

You also need to add a field Role in a system on the form for editing departments. Add this field to the INTERFACE`S DEFINITION form of req_depart

{attributeName: "roleInSystem" /*Role in System*/}

After, edit the data Departments form, putting the values in the field: "Role in System".

The rule for reading certain rows is described in the "rls" attribute.

Document reference https://unitybase.info/api/server/#!/guide/rls

Change the mixins section of the req_reqList.meta file to the following code

 "mixins": { // the mandatory section (can be empty)
  "mStorage": {    "simpleAudit": true
  },
"rls": {
		"expression": "'(' + $.currentOwner() + ' OR ' + '[department.roleInSystem] in (' + Session.userRoles + '))'"

       }   
 }

After the changes to the model, you need to recreate the SQL script again with generateDDL
ubcli generateDDL -u admin -p admin -host http://localhost:8881 -m requests -autorun

In Administrator mode, create a few orders for different departments, log on to the system with created users, and make sure that the rules that are set are working correctly.
Next step