From d960a5c7fb0af95c5783dbda630d6b9cfedfe168 Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Sat, 25 May 2013 14:37:37 -0400 Subject: [PATCH] Add a design doc for the new permission model --- docs/bugdar2_permissions.md | 76 +++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 docs/bugdar2_permissions.md diff --git a/docs/bugdar2_permissions.md b/docs/bugdar2_permissions.md new file mode 100644 index 0000000..e1ab817 --- /dev/null +++ b/docs/bugdar2_permissions.md @@ -0,0 +1,76 @@ +# Bugdar 2.0, Take 3 — Permissions Model + +## Current Situation + +Bugdar v1 has a multi-tierd permission model. Users have a primary group and multiple secondary groups. Since group permissions are OR'd together, they are cumulative rather than subtractive: once a permission bit is ON, it can't be OFF (see `FetchUserPermissions`). A secondary unit by which permissions are partitioned is products. Products also have usergroup-level permissions that can override other group-level permissions if set explicitly to NO, unlike multiple usergroup permissions, which are OR'd together (see `fetch_on_bits()`). + +A separate permissions matrix exists for custom fields. Custom fields have usergroup-level permissions for no access, view rights, and modification rights. + +The basic algorithm for applying these permissions is: + + bool HasPermission($user, $permission, $bug) { + $group_mask = $user->primary_group & $permission; + + $has_product_mask = FALSE; + $product_mask = 0; + + for each $group in $user->groups { + $group_mask |= $group->permissions & $permission; + + if $bug->product in $group->product_permissions { + $has_product_mask = TRUE; + $product_mask |= $group->product_permissions[$bug->product] & $permission; + } + } + + return $has_product_mask ? $product_mask : $group_mask; + } + +Thus it's clear that any product permission will override the set group mask. Yet in each of the two tiers of permissions that `HasPermission` evaluates, the individual permission masks are OR'd together. + +### Database Tables +* `bugfield` + * Configuration data for custom fields. +* `bugfieldpermission` + * Controls custom permissions (none, can view, can edit) for custom fields. + * Links to `bugfield`. +* `permission` + * Controls product-specific permissions that cascade on top of the base `usergroup.permissions` field. +* `usergroup` + * Controls the base permsission of a user, OR'd together in `FetchUserPermissions`. + +## Version 2 + +In version 2, all attributes (product, severity, priority) are all going to be implemented using a "custom field" system. This means that product-level permissions and custom field permissions are no longer applicable. Since products will now be expressed as just ordinary fields, the second tier of permissions needs to be rethought. + +Expressing the v1 relationship is done like such: + + Tuple = Mask + +Expressing this in v2 with fields yields: + + Tuple = Mask + +### Recreating v1 + +This sets a Mask when a Field is set to Value and the user is in Usergroup. Product-level permissions can thus be reproduced: + + Tuple<"Product", "Example Product", "Registered Users"> = NewMask + +But it also allows new permission expressions: + + Tuple<"Lock", "Comments", "Registered Users"> = Inherited_Permissions & ~CAN_COMMENT + +Where Inherited_Permissions is the set permissions at the time of Tuple creation, this would allow one to apply security access labels to bugs that alter the effective permissions. This preserves the two-tierd system in place in v1, with the second tier permissions, if set, overriding the first tier. + +### Extending + +Rather than having the `Tuple` map to a `Mask`, it instead could map to another tuple: + + Tuple = Tuple + +Where the first item in the RHS is a bitwise OR'd mask of permissions being allowed, and the second item is a bitwise OR'd mask of permissions being explicitly denied. All other permissions would be inherited. This would create an effective permission mask of: + + EffectiveMask = ((Primary_Group | Secondary_Group...) | Rule_Permissions[Allow]) & ~Rule_Permissions[Deny] + +This would give Deny permissions highest precedence. \ No newline at end of file -- 2.22.5