Permissions System

=Permissions=

Tables
Each table that needs securing has one or more RelationshipPermission Zymonic XML objects referenced in it. This will define who can access the data and under what circumstances; before looking at the XML we need to understand the concepts that are used within Zymonic's security system.

Users
Zymonic's users are unremarkable - generally there is one zz_user_record entry associated with each person (or remote system). Very often the zz_user_record entries are created / maintained using a PerformTransition/PerformUpdates action on a separate 'user' process where significant customisations or legacy systems are integrated.

Zymonic users can also be automatically populated/synchronised with an external directory system e.g. LDAP or eDirectory - these modes can be enabled in SystemOptions XML using the guides in the POD of the appropriate modules e.g. "man Zymonic::Auth::LDAP".

Groups
Groups are held in zz_groups.

Whilst groups can be used in a similar fashion to other permission systems it is important to consider whether a group or a role is most appropriate. If you are trying to group users by what they can access, i.e., which records they should have access to. If there is no link between the zz_groups table and the record being secured (a foreign key of some sort) then the functionality should probably be being implemented with a role.

Roles
Roles are where groups of users can do the same things within Zymonic even if they can't do the same things to different records within the same table (in this case a 'Group' with some kind of link to the table becomes appropriate - probably in addition to a role rather than instead of).

Roles are maintained via the 'Roles List'.

Each Role has a name and a seniority. The smaller the seniority is the more senior the user is. If a user has a role which allows them to create or maintain roles then they may only create/maintain roles with a lower seniority to their own role; additionally if a user has sudo permission then the user can only become a user who has a role that is equal or lower in senority, i.e., numerically higher.

Each role also has a list of 'Role Permissions' these can be enabled or disabled on the role. The user will only be able to enable and see role permissions that their own role has.

When the config build is run a 'superuser' role will be created/updated which has all role permissions enabled - this is the role which will be needed to start creating other roles.

The user's role is set on their zz_user_record record.

zz_record_security
For every record in a DB table in Zymonic there are permissions that determine who can access that record (read write etc.) to determine that each record has a ‘sec_id’ field, this field can contain;

A) nothing - means no-perms anyone can do anything with the record - unusual

B) a word/number that refers to the table and is the same for most/all records in that table

C) a word/number that is unique to that record or a small number of records

in the case of B or C Zymonic will use the sec_id to:

OLD MODE: Look up records in zz_record_security (sec_id being a ‘foreign key’ in there)

NEW MODE: Look up records in zz_[table being secured’s name]_rs - (sec_id being a foreign key in there)

In either case those records will contain:

| Field                  | Type          | Null | Key | Default             | Extra        | | permission_holder       | varchar(255)  | YES  | MUL | NULL                |                             | | id                     | int(11)       | NO   | PRI | NULL                | auto_increment              | | ip_list                | varchar(255)  | YES  | MUL | NULL                |                             | | fap_list               | varchar(255)  | YES  | MUL | NULL                |                             | | tab                    | char(1)       | YES  | MUL | NULL                |                             | | roleperm               | char(50)      | YES  | MUL | any                 |                             | | field_zname            | varchar(255)  | YES  |     | NULL                |                             | | sec_id                 | varchar(500)  | YES  | MUL | NULL                |                             | | has_field_permissions   | char(1)       | YES  |     | NULL                |                             | | parent_process_id      | int(18)       | YES  | MUL | NULL                |                             | | deleted                | char(1)       | YES  | MUL | NULL                |                             | | autocreated            | int(18)       | YES  | MUL | NULL                |                             | | posix_process_id       | int(18)       | YES  |     | NULL                |                             | | zzlu                   | timestamp     | NO   | MUL | CURRENT_TIMESTAMP   | on update CURRENT_TIMESTAMP | | zzluts                 | double        | YES  |     | NULL                |                             | | zza                    | timestamp     | NO   |     | 0000-00-00 00:00:00 |                             | | zz_source              | varchar(512)  | YES  |     | NULL                |                             | | zz_remote_keyfields    | varchar(1000) | YES  |     | NULL                |                             | | permission_readable    | char(1)       | YES  |     | NULL                |                             | | permission_deleteable  | char(1)       | YES  |     | NULL                |                             | | permission_secureable  | char(1)       | YES  |     | NULL                |                             | | permission_undeleteable | char(1)      | YES  |     | NULL                |                             | | permission_appendable  | char(1)       | YES  |     | NULL                |                             | | permission_changeable  | char(1)       | YES  |     | NULL                |

id, parent_process_id, deleted, autocreated, posix_process_id, zzlu, zzluts, zza, zz_source and zz_remote_keyfields - are all 'internal' fields and will not be considered further in this discussion.

permission_holder - Who is being allowed access : anyone authenticated (AUTHENTICATED), specific group (GROUP: [group id or name]), specific person or unauthenticated users (USER: [user id]) or someone not logged in (UNAUTHENTICATED)

ip_list - this is name of a list of IP addresses and ranges that is maintained in the zz_ip_lists table. That table will use ip_list as a 'foreign key' to check ip addresses against.

fap_list - like ip_list this is the foreign key in another table, zz_fap_lists, which contains a list of filters and processes to which this permission record applies.

tab - used to determine whether the sec_id record applies at table level (this flag is only used during refreshing the permissiosn during a config build).

roleperm* - This is the zname of the 'role permission' that the user must have (via their role) for this permission record to apply to them.

has_field_permissions - for records where individual fields have different permissions thie will be 'Y' and additional records will be retrieved which have the correct field_zname

field_zname - this indicates that the permissions apply to a particular field.

permission_* - these fields determine what the user can do, as well as the standard permissions (read, delete, secure, undelete, append, modify), additional permission types can be added in the XML or system configuration.

The security system will use the current session's details to determine which of the records retrieved from zz_record_security / zz_[table name]_rs apply to you and then give you all the permissions that you have at least one ‘yes’ for.

This last bit can be done either via a set of SQL joins / sub-query that are provided by Zymonic::Auth and then added as part of building the query or it can be done by passing a sec_id for one record to a Zymonic::Auth method that calculates the permissions for one record - this latter is done when loading one record e.g. on a single page form / when updating.

How Permissions influence Pages and their content / menus
Each process or filter has an entry in the zz_fap table; this links up to record security via a sec_id as usual, however, instead of being populated as normal based on RelationshipPermissions XML defined against the table, a special class of RelationshipPermission is associated with zz_fap which looks at the base table of the Filter or the base tables of the Forms within a Process and uses those to determine whether a user will be able to access any data via the process or filter. If a user will be able to access data via a filter or process then there will be an appropriate entry in the record security table.

Menus (Filters of Filters and Processes) use the zz_fap table to determine which processes / filters to show - they are generally limited by something in addition to security e.g. a specific list or a category (another field available within zz_fap).

Additionally a block will only show on a user's view of a page if they have a read permission on the filter or processes' entry in zz_fap.

Pages are also stored in a table (zz_pages) which has permissions.

Finally each page is automatically assigned a role permission and relationship permission.

A user will be able to see a page IF their role has the role permission for the page OR some other RelationshipPermission added to zz_pages allows them access AND there will be at least one visible block on the page.

This means that even if the user has the page permission, if they do not have permissions to access any of the data via any of the processes/filters in the menu on the page then they will not be able to see the page.

sudo
Like unix sudo allows a user to interact with the system as if they were another user (with an equal or less senior role) all actions they take when sudo-ed will be logged with both usernames.

RelationshipPermission / Role Permission / Page / FoFaP XML and some examples
TODO