Dev_Groups and permissions discussion
Clone this wiki locally
Groups and Permissions Discussion
Groups are identified by a "group spec" in a manner similar to bundles and worksheets. Groups are either user-defined or system-defined. System-defined groups cannot be modified. An example of a system-defined group is the Public group which denotes all users. Non system-defined group are associated with a user (the creator of the group) via
group = Table( 'group', db_metadata, Column('id', Integer, primary_key=True, nullable=False), Column('uuid', String(63), nullable=False), Column('name', String(255), nullable=False), Column('user_defined', Boolean), Column('owner_id', Integer, nullable=True), UniqueConstraint('uuid', name='uix_1'), Index('group_name_index', 'name'), Index('group_owner_id_index', 'owner_id'), sqlite_autoincrement=True, ) group.insert().values(name="Public", uuid=..., user_defined=False)
The Public group is intended to represent all users, including users who are not authenticated. If the need arise, a system-defined Authenticated group can be added to represent all authenticated users.
user_group table associates a user with a set of groups. A user is identified by the unique user ID provided by the OAuth authentication server.
user_group = Table( 'user_group', db_metadata, Column('id', Integer, primary_key=True, nullable=False), Column('group_uuid', String(63), ForeignKey(group.c.uuid), nullable=False), Column('user_id', String(63), nullable=False), Column('is_admin', Boolean), Index('group_uuid_index', 'group_uuid'), Index('user_id_index', 'user_id'), sqlite_autoincrement=True, )
is_admin exists because a user may be added to a group and given admin privileges for the group. By default, the creator of the group is always an admin.
The implementation will have to be aware of special groups like Public since users will not be explicitly added to such groups.
The set of possible permissions will be small and defined using symbolic constants. Basic permissions are: None, Read and All.
Permissions are granted to a group on an object (a bundle or a worksheet).
group_object_permission = Table( 'group_object_permission', db_metadata, Column('id', Integer, primary_key=True, nullable=False), Column('group_uuid', String(63), ForeignKey(group.c.uuid), nullable=False), # Reference to a worksheet or bundle object Column('object_uuid', String(63), nullable=True), # Permissions encoded as integer. 'Read' (0x01) or 'All' (0x11) Column('permission', Integer, nullable=False), sqlite_autoincrement=True, )
group_object_permission only knows about groups; it does not know about users directly. All objects (bundles and worksheets) will have an additional column to keep track of the user who created the object. The so-called object owner always has full rights on the object.
To manage groups:
add-group <group_spec> del-group <group_spec> add-user <user_spec> <group_spec> del-user <user_spec> <group_spec> #List my groups cl list -g #Show info (list members) of a group cl info -g <group_spec>
To set permissions, in a initial discussion, we had noted:
set-perm <group_spec> <none|r(ead)|a(ll)> <bundle_spec> set-perm -w <group_spec> <none|r(ead)|a(ll)> <worksheet_spec> set-perm -g <group_spec> <none|r(ead)|a(ll)> <group_spec>
The above design uses an additional command switch to specify the type of object (similar to
cl clist vs.
cl list -w). An alternative would be to have command named after the object type:
set-bundle-perm <group_spec> <none|r(ead)|a(ll)> <bundle_spec> set-worksheet-perm <group_spec> <none|r(ead)|a(ll)> <worksheet_spec> set-group-perm <group_spec> <none|r(ead)|a(ll)> <group_spec>
Another option would be to have a single command for all objects but that may increase the number of times that a user is forced to use the full UUID as opposed to using the friendly name of the object:
set-perm <group_spec> <none|r(ead)|a(ll)> <object_spec>
Bundle service API
TODO: How do existing service API change to satisfy the need of clients. A primary client is the web site.
list_worksheets(auth_token, owner/group, search text, bundle referenced, ..., offset/limit) list_bundles(auth_token, owner/group, search text, bundle dependencies, ..., offset/limit)
User uploads a bundle
When a user uploads a bundle, the bundle server authenticates the user and obtains the unique user ID,
user_id, from the OAuth authentication server.
The bundle server queries the
user_grouptable to find a system-defined group associated with
user_id. If such a group does not exist, then it is created. The end result is a group representing the individual user. Let
user_g_iddenote the UUID of the group.
The bundle is created so we know its UUID,
The association between the user (indirectly represented by group
user_g_id) and the bundle (
bundle_uuid) are recorded in the
group_object_permissiontable. The user is granted full control.
User shares a bundle with a team.
From the CLI, user creates a group for the team:
cl add-group myteam
As a result of the command, the bundle server creates a user-defined group named "myteam". The user (who issued the command) is automatically added to the group and is granted all permissions on the group.
From the CLI, user adds a team member to the group:
cl add-user member1 myteam
As a result of the command, the bundle server calls the OAuth authentication server to resolve the name "member1" into a unique user ID,
member1_user_id. The bundle server also resolves "myteam" into a group UUID. If successful, the bundle server verifies that the issuer of the CLI command has permissions to edit the group, then adds "member1" to the group.
Other team members are added one-by-one.
From the CLI, user sets permission on the bundle:
cl set-perm myteam read mybundle
Sharing a worsheet with private bundles
Let's say that a user creates a worsheet which references bundles which are private to that user. Now the user attempts to make the worksheet public to all. It's probably reasonable to assume that the CLI and/or the bundle service would warn the user and would refuse to make the worksheet public until the bundles are also public.