Permission system

As the Modelverse runs as a service, and allows users to share models, permissions become required. We briefly introduce the permission system used in the Modelverse.

As in the Modelverse everything is modelled explicitly, all permisions and meta-information about models is also modelled explicitly in the core model. This model is not readable to any user, but can be queried and altered through the provided set of operations.

Model permissions

First and foremost are the permissions on the models. When creating a new model with model_add, the model is by default only readable and writable for the creating user. All other users have neither read, nor write access unless explicitly granted by the creating user. Similar to UNIX permissions, we use numeric values to indicate permissions, in the form XYZ. X indicates the permissions of the owner itself. Y indicates the permissions of the owning group. Z indicates the permissions of all other users.

The values can range from 0 to 2. 0 indicates that the model is not readable, nor writable. 1 indicates that the model is readable, but not writable. 2 indicates that the model is both readable and writable.

As such, a model can have permission 210. This indicates that the owner can read and write the model, the owning group can open the model read-only, and all other users have no access at all to the model.

Models can be queried for their permission information with the model_list_full operation:

>>> model_list_full("models/petrinets/")
[("my_pn", "user1", "group1", "200"),
 ("my_pn2", "user2", "group1", "210"),
 ("my_pn3", "user2", "group2", "210"),
 ("my_pn4", "user2", "group2", "211"),
 ...
]

In this case, user1 can modify my_pn, as he is the owner (permission 2: read/write), read my_pn2, as he is a member of group1 (permission 1: read), and has no access to my_pn3, as he is neither owner, nor in the group (permission 0: none). All users can read my_pn4, independent of their group (permission 1: read).

In future versions of the Modelverse, an additional executable permission can be added. This permission will be checked before executing the activity or process model. For now, read permissions are equal to execution permissions, although this will in the future not always be the case. Indeed, read permissions allows users to open the model and read its contents (i.e., see how it does it), whereas execution permission allows users to execute it (i.e., see what it does). Both are distinct: one might want users to execute an activity, but not see how it is implemented (e.g., for protection of intellectual property). Vice versa, one might want users to open activities as a model, but not execute them (e.g., if the user does not have permissions to execute code on the server).

For user-specific information on which operations are permitted, the operation read_permissions can be used. This operation returns either the empty string (no permissions), “R” (read permission), or “W” (read/write permission) for a single model, based on the user and the groups he is a member of:

>>> read_permissions("models/petrinets/my_pn")
"W"
>>> read_permissions("models/petrinets/my_pn2")
"R"
>>> read_permissions("models/petrinets/my_pn3")
""
>>> read_permissions("models/petrinets/my_pn4")
"R"

Folder permissions

Similar to models, folders can also have permissions, owners, and an owning group. In this case, a readable folder is required to perform a model_list operation on that folder. A writable folder is required to create new entries (either models or new folders) in that folder. Note that this permission system leads to interesting situations, as in the UNIX permission model, where a folder cannot be read, but its contained files can (if their exact name is used). When a file was already created, overwriting that file does not require any permissions of the folder at all.

Permission management

To share your models, you basically need to relax their permissions. The default permissions are such that only the owning user can read/write the model, and no other users have access to it. To alter the permissions, we have access to several operations.

  1. permission_modify changes the permissions of a model to the specified string. For example, to make my_pn readable for everyone:

    >>> permission_modify("models/my_pn", "211")
    
  2. permission_owner changes the owner of a model, thereby possibly revoking our own permission, but passing it on to someone else. For example, to make user2 the owner of our PetriNet model:

    >>> permission_owner("models/my_pn", "user2")
    
  3. permission_group changes the owning group of a model, thereby possibly revoking permissions for several users. For example, to make group2 the owning group of our PetriNet model:

    >>> permission_group("models/my_pn", "group2")
    

Meta-level propagation

Due to its meta-modelling nature, Modelverse permissions are more involved than just file-like permissions. Indeed, a model depends on the language used to create it, such as PetriNets. While in this case we have assumed PetriNets to be always readable, this does not necessarily need to be the case.

Creating a new instance of an unreadable metamodel, or language, is of course impossible, and the call to model_add will be prevented. Worse, however, is when the permissions of the metamodel are altered when there already is a model in that language. In this case, the model will suddenly become unreadable, as it depends on an unreadable metamodel. Later on, we will see that this does not necessarily make it impossible for the model to be opened, as it only prevents it to be opened with that specific metamodel. This does, however, require multi-conformance, which is an advanced concepts that is currently out of scope of this tutorial.

Group permissions

Groups are merely sets of users. Users can be added to the group with the group_join operation. To make user1 join group1:

>>> group_join("group1", "user1")

Similarly, they can be removed from a group, thereby revoking all their permissions that were granted by the group. To make user1 leave group1 again:

>>> group_kick("group1", "user1")

As groups are key to model permissions, care should be taken who is made a member of a specific group. Groups are themselves managed by group administrators, who govern the members of a specific group. Group administrators can create new group administrators as well, who also automatically become a member of the group. Similarly, group administrators can revoke the permissions of other group administrators:

>>> group_owner_add("group1", "user1")
>>> group_owner_delete("group1", "user1")

Note that, when removing group administrator status of a user, the user will still be a member of the group, though no longer an administrator. As such, the result of the previous two commands will leave user1 as a group member, even though that might not have been the case before. A group_kick automatically removes group administrator permissions as well.

All users can create new groups, of which they automatically become the group administrator:

>>> group_add("group2)

Similarly, groups can be removed by the group owner. This not only removes the group, but also kicks all users and thereby revokes all permissions originally given by that group:

>>> group_delete("group2")

User management

Users can manage the basics of their accounts. This includes changing their username. In this case, only the name is altered, and all permissions remain unaltered. This is because only the name changes, and not the internal representation of that user. For example, to change the username of user1 to user_1:

>>> user_name("user1", "user_1")

Similarly, users can alter their password:

>>> user_password("user_1", "new_password")

In both cases, all currently active sessions remain active, but future logins need to use the new credentials.

Administrators

Finally, there is still the notion of an administrator in the Modelverse. Administrators are basically like the root users on UNIX systems: independent of permissions, they are allowed to perform any operation they want. As such, they are implicitly owner of each model, administrator of all groups, and have full permissions for user management. The Modelverse is initialized with one administrator user, but administrators can create (promote) new administrators, or revoke their administrator permissions (demote):

>>> admin_promote("user1")
>>> admin_demote("user1")