-- This file will eventually replace content-perms.sql -- Implements the CMS permission declare v_perms varchar2(1) := 'f'; begin begin select 't' into v_perms from dual where exists (select 1 from acs_privileges where privilege = 'cm_root'); exception when no_data_found then v_perms := 'f'; end; if v_perms <> 't' then -- Dummy root privilege acs_privilege.create_privilege('cm_root', 'Root', 'Root'); -- He can do everything acs_privilege.create_privilege('cm_admin', 'Administrator', 'Administrators'); acs_privilege.create_privilege('cm_relate', 'Relate Items', 'Relate Items'); acs_privilege.create_privilege('cm_write', 'Write', 'Write'); acs_privilege.create_privilege('cm_new', 'Create New Item', 'Create New Item'); acs_privilege.create_privilege('cm_examine', 'Admin-level Read', 'Admin-level Read'); acs_privilege.create_privilege('cm_read', 'User-level Read', 'User-level Read'); acs_privilege.create_privilege('cm_item_workflow', 'Modify Workflow', 'Modify Workflow'); acs_privilege.create_privilege('cm_perm_admin', 'Modify Any Permissions', 'Modify Any Permissions'); acs_privilege.create_privilege('cm_perm', 'Donate Permissions', 'Donate Permissions'); acs_privilege.add_child('cm_root', 'cm_admin'); -- Do anything acs_privilege.add_child('cm_admin', 'cm_relate'); -- Related/Child items acs_privilege.add_child('cm_relate', 'cm_write'); -- Modify the item acs_privilege.add_child('cm_write', 'cm_new'); -- Create subitems acs_privilege.add_child('cm_new', 'cm_examine'); -- View in admin mode acs_privilege.add_child('cm_examine', 'cm_read'); -- View in user mode acs_privilege.add_child('cm_admin', 'cm_item_workflow'); -- Change item workflow acs_privilege.add_child('cm_admin', 'cm_perm_admin'); -- Modify any permissions acs_privilege.add_child('cm_perm_admin', 'cm_perm'); -- Modify any permissions on an item -- Proper inheritance acs_privilege.add_child('admin', 'cm_root'); end if; end; / show errors create or replace package cms_permission is procedure update_permissions ( --/** Make the child item inherit all of the permissions of the parent -- item. Typically, this function is called whenever permissions on -- an item are changed for the first time. -- @author Stanislav Freidin -- @param item_id The item_id -- @param is_recursive If 'f', update child items as well, otherwise -- update only the item itself (note: this is the opposite of -- is_recursive in grant_permission and revoke_permission) -- @see {cms_permission.grant_permission}, {cms_permission.copy_permissions} --*/ item_id in cr_items.item_id%TYPE, is_recursive in varchar2 default 't' ); function has_grant_authority ( --/** Determine if the user may grant a certain permission to another -- user. The permission may only be granted if the user has -- the permission himself and possesses the cm_perm access, or if the -- user possesses the cm_perm_admin access. -- @author Stanislav Freidin -- @param item_id The item whose permissions are to be changed -- @param holder_id The person who is attempting to grant the permissions -- @param privilege The privilege to be granted -- @return 't' if the donation is possible, 'f' otherwise -- @see {cms_permission.grant_permission}, -- {cms_permission.is_has_revoke_authority}, -- {acs_permission.grant_permission} --*/ item_id in cr_items.item_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE ) return varchar2; procedure grant_permission ( --/** Grant the specified privilege to another user. If the donation is -- not possible, the procedure does nothing. -- @author Stanislav Freidin -- @param item_id The item whose permissions are to be changed -- @param holder_id The person who is attempting to grant the permissions -- @param privilege The privilege to be granted -- @param recepient_id The person who will gain the privilege -- @param is_recursive If 't', applies the donation recursively to -- all child items of the item (equivalent to UNIX's chmod -r). -- If 'f', only affects the item itself. -- @see {cms_permission.has_grant_authority}, -- {cms_permission.revoke_permission}, -- {acs_permission.grant_permission} --*/ item_id in cr_items.item_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE, recepient_id in parties.party_id%TYPE, is_recursive in varchar2 default 'f' ); function has_revoke_authority ( --/** Determine if the user may take a certain permission away from another -- user. The permission may only be revoked if the user has -- the permission himself and possesses the cm_perm access, while the -- other user does not, or if the user possesses the cm_perm_admin access. -- @author Stanislav Freidin -- @param item_id The item whose permissions are to be changed -- @param holder_id The person who is attempting to revoke the permissions -- @param privilege The privilege to be revoked -- @param revokee_id The user from whom the privilege is to be taken away -- @return 't' if it is possible to revoke the privilege, 'f' otherwise -- @see {cms_permission.has_grant_authority}, -- {cms_permission.revoke_permission}, -- {acs_permission.revoke_permission} --*/ item_id in cr_items.item_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE, revokee_id in parties.party_id%TYPE ) return varchar2; procedure revoke_permission ( --/** Take the specified privilege away from another user. If the operation is -- not possible, the procedure does nothing. -- @author Stanislav Freidin -- @param item_id The item whose permissions are to be changed -- @param holder_id The person who is attempting to revoke the permissions -- @param privilege The privilege to be revoked -- @param recepient_id The person who will lose the privilege -- @param is_recursive If 't', applies the operation recursively to -- all child items of the item (equivalent to UNIX's chmod -r). -- If 'f', only affects the iten itself. -- @see {cms_permission.grant_permission}, -- {cms_permission.has_revoke_authority}, -- {acs_permission.revoke_permission} --*/ item_id in cr_items.item_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE, revokee_id in parties.party_id%TYPE, is_recursive in varchar2 default 'f' ); function permission_p ( --/** Determine if the user has the specified permission on the specified -- object. Does NOT check objects recursively: that is, if the user has -- the permission on the parent object, he does not automatically gain -- the permission on all the child objects.

-- In addition, checks if the Publishing workflow has been assigned to -- the item. If it has, then the user must be assigned to the current -- workflow task in order to utilize his cm_relate, cm_write or cm_new -- permission. -- @author Stanislav Freidin -- @param item_id The object whose permissions are to be checked -- @param holder_id The person whose permissions are to be examined -- @param privilege The privilege to be checked -- @return 't' if the user has the specified permission on the item, -- 'f' otherwise -- @see {cms_permission.grant_permission}, {cms_permission.revoke_permission}, -- {acs_permission.permission_p} --*/ item_id in cr_items.item_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE ) return varchar2; function cm_admin_exists --/** Determine if there exists a user who has administrative -- privileges on the entire content repository. -- @author Stanislav Freidin -- @return 't' if an administrator exists, 'f' otherwise -- @see {cms_permission.grant_permission} --*/ return varchar2; end cms_permission; / show errors create or replace package body cms_permission is procedure update_permissions ( item_id in cr_items.item_id%TYPE, is_recursive in varchar2 default 'f' ) is v_grantee_id parties.party_id%TYPE; v_privilege acs_privileges.privilege%TYPE; v_inherit_p varchar2(1); v_context_id acs_objects.context_id%TYPE; cursor c_child_cur is select item_id from cr_items where parent_id = update_permissions.item_id; begin -- If there is no inheritance, nothing to do select security_inherit_p, context_id into v_inherit_p, v_context_id from acs_objects where object_id = update_permissions.item_id; if v_inherit_p = 'f' or v_context_id is null then return; end if; -- Remove inheritance on the item update acs_objects set security_inherit_p = 'f' where object_id = update_permissions.item_id; -- If not recursive, turn off inheritance for children of -- this item if is_recursive = 'f' then update acs_objects set security_inherit_p = 'f' where object_id in ( select item_id from cr_items where parent_id = update_permissions.item_id ) and security_inherit_p = 't'; end if; -- Get permissions assigned to the parent(s), copy them into child declare cursor c_perm_cur is select p.grantee_id, p.privilege from acs_permissions p, (select object_id from acs_objects connect by prior context_id = object_id and security_inherit_p = 't' start with object_id = v_context_id) o where p.object_id = o.object_id; begin open c_perm_cur; loop fetch c_perm_cur into v_grantee_id, v_privilege; exit when c_perm_cur%NOTFOUND; if acs_permission.permission_p ( item_id, v_grantee_id, v_privilege ) = 'f' then acs_permission.grant_permission ( item_id, v_grantee_id, v_privilege ); end if; end loop; close c_perm_cur; end; end update_permissions; function has_grant_authority ( item_id in cr_items.item_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE ) return varchar2 is begin -- Can donate permission only if you already have it and you have cm_perm, -- OR you have cm_perm_admin if acs_permission.permission_p (item_id, holder_id, 'cm_perm_admin')= 't' or ( acs_permission.permission_p (item_id, holder_id, 'cm_perm') = 't' and acs_permission.permission_p (item_id, holder_id, privilege) = 't' ) then return 't'; else return 'f'; end if; end has_grant_authority; function has_revoke_authority ( item_id in cr_items.item_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE, revokee_id in parties.party_id%TYPE ) return varchar2 is cursor c_perm_cur is select 't' from acs_privilege_hierarchy where acs_permission.permission_p( has_revoke_authority.item_id, has_revoke_authority.holder_id, child_privilege ) = 't' and acs_permission.permission_p( has_revoke_authority.item_id, has_revoke_authority.revokee_id, privilege ) = 'f' connect by prior privilege = child_privilege start with child_privilege = 'cm_perm'; v_ret varchar2(1); begin open c_perm_cur; fetch c_perm_cur into v_ret; if c_perm_cur%NOTFOUND then v_ret := 'f'; end if; close c_perm_cur; return v_ret; end has_revoke_authority; procedure grant_permission ( item_id in cr_items.item_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE, recepient_id in parties.party_id%TYPE, is_recursive in varchar2 default 'f' ) is cursor c_item_cur is select item_id from (select item_id from cr_items connect by parent_id = prior item_id start with item_id = grant_permission.item_id) i where has_grant_authority ( i.item_id, grant_permission.holder_id, grant_permission.privilege ) = 't' and acs_permission.permission_p ( i.item_id, grant_permission.recepient_id, grant_permission.privilege ) = 'f'; v_item_id cr_items.item_id%TYPE; type item_array_type is table of cr_items.item_id%TYPE index by binary_integer; v_items item_array_type; v_idx integer; v_count integer; cursor c_perm_cur is select descendant from acs_privilege_descendant_map where privilege = grant_permission.privilege and descendant <> grant_permission.privilege; type perm_array_type is table of acs_privileges.privilege%TYPE index by binary_integer; v_perms perm_array_type; v_perm acs_privileges.privilege%TYPE; v_perm_idx integer; v_perm_count integer; begin update_permissions(item_id, is_recursive); -- Select all child items open c_item_cur; v_count := 0; loop fetch c_item_cur into v_item_id; exit when c_item_cur%NOTFOUND; v_count := v_count + 1; v_items(v_count) := v_item_id; exit when is_recursive = 'f'; end loop; close c_item_cur; if v_count < 1 then return; end if; -- Grant parent permission for v_idx in 1..v_count loop acs_permission.grant_permission ( v_items(v_idx), recepient_id, privilege ); end loop; -- Select the child permissions v_perm_count := 0; open c_perm_cur; loop fetch c_perm_cur into v_perm; exit when c_perm_cur%NOTFOUND; v_perm_count := v_perm_count + 1; v_perms(v_perm_count) := v_perm; end loop; close c_perm_cur; -- Revoke child permissions for v_idx in 1..v_count loop for v_perm_idx in 1..v_perm_count loop acs_permission.revoke_permission ( v_items(v_idx), recepient_id, v_perms(v_perm_idx) ); end loop; end loop; end grant_permission; procedure revoke_permission ( item_id in cr_items.item_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE, revokee_id in parties.party_id%TYPE, is_recursive in varchar2 default 'f' ) is cursor c_item_cur is select item_id from cr_items connect by parent_id = prior item_id start with item_id = revoke_permission.item_id where has_revoke_authority ( item_id, cms_permission.revoke_permission.holder_id, cms_permission.revoke_permission.privilege, cms_permission.revoke_permission.revokee_id ) = 't' and acs_permission.permission_p ( item_id, cms_permission.revoke_permission.revokee_id, cms_permission.revoke_permission.privilege ) = 't'; cursor c_perm_cur is select child_privilege from acs_privilege_hierarchy where privilege = revoke_permission.privilege and child_privilege <> revoke_permission.privilege; type item_array_type is table of cr_items.item_id%TYPE index by binary_integer; v_items item_array_type; v_item_id cr_items.item_id%TYPE; v_idx integer; v_count integer; type perm_array_type is table of acs_privileges.privilege%TYPE index by binary_integer; v_perms perm_array_type; v_perm acs_privileges.privilege%TYPE; v_perm_idx integer; v_perm_count integer; begin update_permissions(item_id, is_recursive); -- Select the child permissions v_perm_count := 0; open c_perm_cur; loop fetch c_perm_cur into v_perm; exit when c_perm_cur%NOTFOUND; v_perm_count := v_perm_count + 1; v_perms(v_perm_count) := v_perm; end loop; close c_perm_cur; -- Select child items v_count := 0; open c_item_cur; loop fetch c_item_cur into v_item_id; exit when c_item_cur%NOTFOUND; v_count := v_count + 1; v_items(v_count) := v_item_id; exit when is_recursive = 'f'; end loop; close c_item_cur; if v_count < 1 then return; end if; -- Grant child permissions for v_idx in 1..v_count loop for v_perm_idx in 1..v_perm_count loop acs_permission.grant_permission ( v_items(v_idx), revokee_id, v_perms(v_perm_idx) ); end loop; end loop; -- Revoke the parent permission for v_idx in 1..v_count loop acs_permission.revoke_permission ( v_items(v_idx), revoke_permission.revokee_id, revoke_permission.privilege ); end loop; end revoke_permission; function permission_p ( item_id in cr_items.item_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE ) return varchar2 is v_workflow_count integer; v_task_count integer; begin -- Check permission the old-fashioned way first if acs_permission.permission_p ( item_id, holder_id, privilege ) = 'f' then return 'f'; end if; -- Special case for workflow if privilege = 'cm_relate' or privilege = 'cm_write' or privilege = 'cm_new' then -- Check if the publishing workflow exists, and if it -- is the only workflow that exists select count(case_id) into v_workflow_count from wf_cases where object_id = permission_p.item_id; -- If there are multiple workflows / no workflows, do nothing -- special if v_workflow_count <> 1 then return 't'; end if; -- Even if there is a workflow, the user can touch the item if he -- has cm_item_workflow if acs_permission.permission_p ( item_id, holder_id, 'cm_item_workflow' ) = 't' then return 't'; end if; -- Check if the user holds the current task if v_workflow_count = 0 then return 'f'; end if; select count(task_id) into v_task_count from wf_user_tasks t, wf_cases c where t.case_id = c.case_id and c.workflow_key = 'publishing_wf' and c.state = 'active' and c.object_id = permission_p.item_id and ( t.state = 'enabled' or ( t.state = 'started' and t.holding_user = permission_p.holder_id )) and t.user_id = permission_p.holder_id; -- is the user assigned a current task on this item if v_task_count = 0 then return 'f'; end if; end if; return 't'; end permission_p; -- Determine if the CMS admin exists function cm_admin_exists return varchar2 is v_exists varchar2(1); begin select 't' into v_exists from dual where exists ( select 1 from acs_permissions where privilege in ('cm_admin', 'cm_root') ); return v_exists; exception when no_data_found then return 'f'; end cm_admin_exists; end cms_permission; / show errors -- A trigger to automatically grant item creators the cm_write and cm_perm -- permissions create or replace trigger cr_items_permission_tr after insert on cr_items for each row declare v_user_id parties.party_id%TYPE; begin select creation_user into v_user_id from acs_objects where object_id = :new.item_id; if v_user_id is not null then if acs_permission.permission_p ( :new.item_id, v_user_id, 'cm_write' ) = 'f' then acs_permission.grant_permission ( :new.item_id, v_user_id, 'cm_write' ); end if; if acs_permission.permission_p ( :new.item_id, v_user_id, 'cm_perm' ) = 'f' then acs_permission.grant_permission ( :new.item_id, v_user_id, 'cm_perm' ); end if; end if; exception when no_data_found then null; end cr_items_permission_tr; / show errors -- A simple wrapper for acs-content-repository procs create or replace package content_permission is procedure inherit_permissions ( parent_object_id in acs_objects.object_id%TYPE, child_object_id in acs_objects.object_id%TYPE, child_creator_id in parties.party_id%TYPE default null ); function has_grant_authority ( object_id in acs_objects.object_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE ) return varchar2; procedure grant_permission_h ( object_id in acs_objects.object_id%TYPE, grantee_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE ); procedure grant_permission ( object_id in acs_objects.object_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE, recepient_id in parties.party_id%TYPE, is_recursive in varchar2 default 'f', object_type in acs_objects.object_type%TYPE default 'content_item' ); function has_revoke_authority ( object_id in acs_objects.object_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE, revokee_id in parties.party_id%TYPE ) return varchar2; procedure revoke_permission_h ( object_id in acs_objects.object_id%TYPE, revokee_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE ); procedure revoke_permission ( object_id in acs_objects.object_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE, revokee_id in parties.party_id%TYPE, is_recursive in varchar2 default 'f', object_type in acs_objects.object_type%TYPE default 'content_item' ); function permission_p ( object_id in acs_objects.object_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE ) return varchar2; function cm_admin_exists return varchar2; end content_permission; / show errors create or replace package body content_permission is procedure inherit_permissions ( parent_object_id in acs_objects.object_id%TYPE, child_object_id in acs_objects.object_id%TYPE, child_creator_id in parties.party_id%TYPE default null ) is begin cms_permission.update_permissions(child_object_id); end inherit_permissions; function has_grant_authority ( object_id in acs_objects.object_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE ) return varchar2 is begin return cms_permission.has_grant_authority ( object_id, holder_id, privilege ); end has_grant_authority; procedure grant_permission_h ( object_id in acs_objects.object_id%TYPE, grantee_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE ) is begin return; end; procedure grant_permission ( object_id in acs_objects.object_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE, recepient_id in parties.party_id%TYPE, is_recursive in varchar2 default 'f', object_type in acs_objects.object_type%TYPE default 'content_item' ) is begin cms_permission.grant_permission ( object_id, holder_id, privilege, recepient_id, is_recursive ); end grant_permission; function has_revoke_authority ( object_id in acs_objects.object_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE, revokee_id in parties.party_id%TYPE ) return varchar2 is begin return cms_permission.has_revoke_authority ( object_id, holder_id, privilege, revokee_id ); end has_revoke_authority; procedure revoke_permission_h ( object_id in acs_objects.object_id%TYPE, revokee_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE ) is begin return; end revoke_permission_h; procedure revoke_permission ( object_id in acs_objects.object_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE, revokee_id in parties.party_id%TYPE, is_recursive in varchar2 default 'f', object_type in acs_objects.object_type%TYPE default 'content_item' ) is begin cms_permission.revoke_permission ( object_id, holder_id, privilege, revokee_id, is_recursive ); end revoke_permission; function permission_p ( object_id in acs_objects.object_id%TYPE, holder_id in parties.party_id%TYPE, privilege in acs_privileges.privilege%TYPE ) return varchar2 is begin return cms_permission.permission_p ( object_id, holder_id, privilege ); end permission_p; function cm_admin_exists return varchar2 is begin return cms_permission.cm_admin_exists; end cm_admin_exists; end content_permission; / show errors