- # This is the key function.
- #
- # perm_origin_uuid: The object that 'gets' or 'has' the permission.
- #
- # starting_uuid: The starting object the permission applies to.
- #
- # starting_perm: The permission that perm_origin_uuid 'has' on starting_uuid
- # One of 1, 2, 3 for can_read, can_write, can_manage
- # respectively, or 0 to revoke permissions.
- #
- # This function is broken up into a number of phases.
- #
- # 1. perm_from_start: Gets the initial set of objects potentially
- # affected by the permission change, using
- # search_permission_graph.
- #
- # 2. additional_perms: Finds other inbound edges that grant
- # permissions on the objects in perm_from_start, and computes
- # permissions that originate from those. This is required to
- # handle the case where there is more than one path through which
- # a user gets permission to an object. For example, a user owns a
- # project and also shares it can_read with a group the user
- # belongs to, adding the can_read link must not overwrite the
- # existing can_manage permission granted by ownership.
- #
- # 3. partial_perms: Combine the permissions computed in the first two phases.
- #
- # 4. user_identity_perms: If there are any users in the set of
- # potentially affected objects and the user's owner was not
- # traversed, recompute permissions for that user. This is
- # required because users always have permission to themselves
- # (identity property) which would be missing from the permission
- # set if the user was traversed while computing permissions for
- # another object.
- #
- # 5. all_perms: Combines perm_from_start, additional_perms, and user_identity_perms.
- #
- # 6. The actual query that produces rows to be added or removed
- # from the materialized_permissions table. This is the clever
- # bit.
- #
- # Key insight: because permissions are transitive (unless
- # traverse_owned is false), by knowing the permissions granted
- # from all the "origins" (perm_origin_uuid, tail_uuid of links
- # where head_uuid is in our potentially affected set, etc) we can
- # join with the materialized_permissions table to get user
- # permissions on those origins, and apply that to the whole graph
- # of objects reached through that origin.