Index: openacs-4/packages/acs-core-docs/www/permissions-tediously-explained.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/permissions-tediously-explained.adp,v diff -u -r1.3 -r1.4 --- openacs-4/packages/acs-core-docs/www/permissions-tediously-explained.adp 8 Nov 2017 09:42:11 -0000 1.3 +++ openacs-4/packages/acs-core-docs/www/permissions-tediously-explained.adp 25 Apr 2018 08:38:28 -0000 1.4 @@ -3,11 +3,11 @@ OpenACS Permissions Tediously Explained -
+ leftLink="parties" leftLabel="Prev" + title="Chapter 11. Development +Reference" + rightLink="object-identity" rightLabel="Next"> +

OpenACS Permissions Tediously Explained

by Vadim Nasardinov. Modified and converted to Docbook XML by @@ -50,8 +50,7 @@ constraint acs_objects_context_object_un unique (context_id, object_id) disable ); - -

This means that items that want to use the features of the +

This means that items that want to use the features of the OpenACS object system needs to have an entry in the acs_objects. This allows developers to define relationships between any two entities A and B by defining a relationship between their corresponding entries in the acs_objects table. One of the applications @@ -63,8 +62,7 @@ pretty_name varchar2(100), pretty_plural varchar2(100) ); - -

+    
   create table acs_permissions (
       object_id
           not null
@@ -78,8 +76,7 @@
       constraint acs_permissions_pk
           primary key (object_id, grantee_id, privilege)
   );
-    
-

The acs_privileges table +

The acs_privileges table stores named privileges like read, write, delete, create, and admin. The acs_permissions table stores assertions of the form:

Who (grantee_id) can do what (privilege) on which object @@ -130,7 +127,7 @@ Context Hierarchy

Suppose objects A, B, ..., and F form the following hierarchy.

-

Table 11.2. Context Hierarchy +

Table 11.2. Context Hierarchy Example

@@ -156,7 +153,7 @@

This can be represented in the acs_objects table by the following entries:

-

Table 11.3. acs_objects example +

Table 11.3. acs_objects example data

@@ -257,8 +254,7 @@ constraint acs_object_context_index_pk primary key (object_id, ancestor_id) ) organization index; - -

A few things to note about this table are these. Number one, it +

A few things to note about this table are these. Number one, it is an index-organized table, which means it is substantially optimized for access by primary key. Number two, as the above computations suggest, the size of the table grows @@ -304,15 +300,12 @@

@@ -361,8 +353,7 @@ constraint acs_privilege_hierarchy_pk primary key (privilege, child_privilege) ); - -

As in the case of the context hierarchy, it is convenient to +

As in the case of the context hierarchy, it is convenient to have a flattened representation of this hierarchal structure. This is accomplished by defining the following view.

   create or replace view acs_privilege_descendant_map
@@ -385,8 +376,7 @@
          prior child_privilege = privilege
       )
     or p2.privilege = p1.privilege;
-    
-

As the number of different privileges in the system is expected +

As the number of different privileges in the system is expected to be reasonably small, there is no pressing need to cache the flattened ansector-descendant view of the privilege hierarchy in a specially maintained table like it is done in the case of the @@ -412,8 +402,7 @@ constraint parties_email_un unique, url varchar2(200) ); - -

+    
   create table persons (
       person_id
           not null
@@ -424,8 +413,7 @@
       last_name            varchar2(100)
           not null
   );
-    
-
+    
   create table users (
       user_id
           not null
@@ -434,18 +422,15 @@
       password        char(40),
       -- other attributes
   );
-    
-
- 
+    
 
   create table groups (
       group_id
           not null
           constraint groups_group_id_fk references parties (party_id)
           constraint groups_pk primary key,
       group_name           varchar2(100) not null
   );
-    
-

Recall that the grantee_id +

Recall that the grantee_id column of the acs_permissions table references parties.party_id. This means that you can grant a privilege on an object to a party, person, user, or group. @@ -476,8 +461,7 @@ constraint acs_object_rels_un unique (rel_type, object_id_one, object_id_two) ); - -

+    
   create table membership_rels (
       rel_id
           constraint membership_rel_rel_id_fk references acs_rels (rel_id)
@@ -487,8 +471,7 @@
           constraint membership_rel_mem_ck
            check (member_state in ('approved', 'banned', 'rejected', 'deleted'))
   );
-    
-

The acs_rels table +

The acs_rels table entries would look like so:


A
object_id=10
readable by Joe
-       


B
object_id=20
readable by Joe
-               


C
object_id=30
security_inherit_p = 'f'
not readable by Joe
-       

@@ -322,7 +315,6 @@       


F
object_id=60
security_inherit_p = 'f'
not readable by Joe
-       

@@ -515,8 +498,7 @@ constraint composition_rels_rel_id_fk references acs_rels (rel_id) constraint composition_rels_rel_id_pk primary key ); - -

The relevant entries in the acs_rels look +

The relevant entries in the acs_rels look like so.

@@ -537,7 +519,7 @@ or not a user is member of a group is similar to the one discussed above in the case of the context hierarchy. Groups can form hierarchies with respect to the composition relationship. The -compositon relationship is transitive. If G1 is a subgroup of G2, and G2 is a subgroup of G3, then G1 is a subgroup of G3; that is, any member of G1 is also a member of G3.

Traversing the group composition hierarchy requires running +composition relationship is transitive. If G1 is a subgroup of G2, and G2 is a subgroup of G3, then G1 is a subgroup of G3; that is, any member of G1 is also a member of G3.

Traversing the group composition hierarchy requires running hierarchical queries, which are expensive in Oracle. As we saw in the Context Hierarchy section, one way of reducing the performance @@ -562,8 +544,7 @@ constraint group_component_index_pk primary key (group_id, component_id, rel_id) ) organization index; - -

+    
   create table group_member_index (
       group_id
           not null
@@ -580,8 +561,7 @@
       constraint group_member_index_pk
           primary key (member_id, group_id, rel_id)
   ) organization index;
-    
-

The group_component_index +

The group_component_index table stores a flattened representation of the group composition hierarchy that is maintained in sync with the acs_rels and composition_rels tables through @@ -616,8 +596,7 @@ where mr.rel_id = r.rel_id and r.object_id_one = gci.component_id; - -

A heuristic way to verify that group_member_view is essentially identical +

A heuristic way to verify that group_member_view is essentially identical to group_member_index is to compute the symmetric difference between the two:

 select
@@ -637,8 +616,7 @@
    minus
    select group_id, member_id from group_member_view
   )
-    
-

The query returns no rows. The important point is, if we have a +

The query returns no rows. The important point is, if we have a flattened view of the composition hierarchy -- like one provided by the group_component_index table -- membership relationship resolution can be computed @@ -649,8 +627,7 @@

Putting It All Together

Security information is queried by calling the acs_permission.permission_p function in -OpenACS. This is accessible from Tcl via the permission::permission_p procedure.

-  
+OpenACS. This is accessible from Tcl via the permission::permission_p procedure.

  
   create or replace package body acs_permission
   as
     -- some stuff removed for the sake of brevity
@@ -673,8 +650,7 @@
     end;
 
   end acs_permission;
-    
-

problem +

problem avoidance

The function queries acs_object_party_privilege_map, which is a humongous view that joins three flattened hierarchies: the context tree, the privilege @@ -686,8 +662,7 @@ would ultimately result in a query error.

For example, do not try to do things like

 select count(*)
   from acs_object_party_privilege_map;
-    
-

To give another example of things to avoid, I have seen code +

To give another example of things to avoid, I have seen code like this:

   declare
       cursor cur is
@@ -713,18 +688,15 @@
 
   end;
   /
-    
-

The acs_permission.revoke_permission function -merely runs a delete statement like so:

-  
+    

The acs_permission.revoke_permission function +merely runs a delete statement like so:

  
   delete from
      acs_permissions
   where
      object_id = revoke_permission.object_id
      and grantee_id = revoke_permission.grantee_id
      and privilege = revoke_permission.privilege;
-    
-

Note that in the above example, acs_permissions had only one entry that +

Note that in the above example, acs_permissions had only one entry that needed to be deleted:

@@ -759,8 +731,7 @@ privilege from acs_object_grantee_priv_map; - -
+    
 create or replace view acs_object_grantee_priv_map
 as
 select
@@ -772,9 +743,7 @@
   acs_privilege_descendant_map m
 where
   a.privilege = m.privilege;
-    
-
- 
+    
 
 create or replace view acs_permissions_all
 as
 select
@@ -786,8 +755,7 @@
   acs_permissions p
 where
   op.ancestor_id = p.object_id;
-    
-
+    
 create or replace view acs_object_paths
 as
 select
@@ -796,9 +764,7 @@
   n_generations
 from
   acs_object_context_index;
-    
-
- 
+    
 
 
 create or replace view group_member_map
 as
@@ -809,13 +775,12 @@
   container_id
 from
   group_member_index;
-    
-
+ - \ No newline at end of file + leftLink="parties" leftLabel="Prev" leftTitle="Parties in OpenACS" + rightLink="object-identity" rightLabel="Next" rightTitle="Object Identity" + homeLink="index" homeLabel="Home" + upLink="dev-guide" upLabel="Up"> + \ No newline at end of file