Forum OpenACS Development: copying permissions

Collapse
Posted by Malte Sussdorff on
I have the request to provide a default folder structure to a project in ]project-open[ using file-storage capabilites (and folders). You could compare this to providing a default folder structure to each file-storage instance for a new community in .LRN.

This is easy to achieve, as I have a folder with templates under which the folder structure I need to copy begins (e.g. /templates/project and /templates/project/folder1 /templates/project/folder2 aso.). Once I create a new project, I just call content_folder__copy and be done with it.

Yet.... it does copy the folder structure, but sadly assumes, that I want to inherit the permissions from the new destination folder. Furthermore it assumes, I don't want to keep the permissions set in the template folders.

Sadly, that's not true, so I wrote a procedure to copy a folder (fs::copy_folder) which allows me to copy the permissions as well as the notifications from the template folder (as I also have a group which should get notifications for uploads to a certain folder).

Writing this I realized, there is no procedure to copy permissions from one object to another. So I wrote this as well (permission::copy)

Before I post my code (later on), did I overlook something? Could I have done this easier?

Collapse
2: Re: copying permissions (response to 1)
Posted by Malte Sussdorff on
ad_proc permission::copy {
    -from_object_id
    -to_object_id
    -clean_inheritance:boolean
    -overwrite:boolean
} {
    @author Malte Sussdorff (mailto:malte.sussdorff@cognovis.de)

    Copy the permissions from one object to another.

    @param from_object_id Source object_id for the permissions
    @param to_object_id Destination object_id which will get the new permissions
    @param clean_inheritance Clean the inheritance of the destination object_id. Useful for items / folders which would usually inherit from the pare\
nt_object_id regardless of what the permissions are on the object itself
    @param overwrite Overwrite existing permissions. In this case we would first clean up the permissions for this item
} {
    if {$overwrite_p} {
        # Clean the permissions                                                                                                                       
        set object_id $to_object_id
        db_foreach select_permissions {} {
            permission::revoke -object_id $object_id -party_id $grantee_id -privilege $privilege
        }
    }

    if {$clean_inheritance_p} {
        # Unset inheritance                                                                                                                           
        permission::set_not_inherit -object_id $to_object_id
    }

    set object_id $from_object_id
    db_foreach select_permissions {} {
        permission::grant -object_id $to_object_id -party_id $grantee_id -privilege $privilege
    }
}

    <fullquery name="permission::copy.select_permissions">
        <querytext>
            select grantee_id,privilege
            from acs_permissions
            where object_id = :object_id
        </querytext>
    </fullquery>
Collapse
3: fs::copy_folder (response to 1)
Posted by Malte Sussdorff on
ad_proc fs::copy_folder {
    -source_folder_id
    -destination_folder_id
} {
    @author Malte Sussdorff (mailto:malte.sussdorff@cognovis.de)
    @creation-date 2010-09-24

    Copies the folder to another parent folder
    Makes sure to copy the permissions as well

    @param destination_folder_id Folder ID of the destination folder below which the folder will be copied
    @param source_folder_id Folder ID of the folder to be copied
} {
    set user_id [ad_conn user_id]
    set peer_addr [ad_conn peeraddr]

    # Make sure we have write permission on the destination folder                                                                                                     
    permission::require_permission \
        -party_id $user_id \
        -object_id $destination_folder_id \
        -privilege "write"

    permission::require_permission \
        -party_id $user_id \
        -object_id $source_folder_id \
        -privilege "read"

    # Make sure both are actually folders                                                                                                                              
    if {![content::folder::is_folder -item_id $source_folder_id] || ![content::folder::is_folder -item_id $destination_folder_id]} {
        return 0
    }

    set new_parent_folder_id [db_string copy_folder {}]

    db_foreach folder_compare {
        select source.item_id as old_folder_id, target.item_id as new_folder_id, security_inherit_p
        from (select children.item_id, children.name, security_inherit_p
              from cr_items children, cr_items parent, acs_objects o
              where children.tree_sortkey between parent.tree_sortkey and tree_right(parent.tree_sortkey)
              and parent.tree_sortkey <> children.tree_sortkey
              and parent.item_id = :source_folder_id
              and children.item_id = o.object_id
              order by children.tree_sortkey) source,
        (select children.item_id, children.name
         from cr_items children, cr_items parent
         where children.tree_sortkey between parent.tree_sortkey and tree_right(parent.tree_sortkey)
         and parent.tree_sortkey <> children.tree_sortkey
         and parent.item_id = :new_parent_folder_id
         order by children.tree_sortkey) target
        where source.name = target.name
    } {
        if {$security_inherit_p eq "t"} {
            permission::copy -from_object_id $old_folder_id -to_object_id $new_folder_id -overwrite
        } else {
            permission::copy -from_object_id $old_folder_id -to_object_id $new_folder_id -overwrite -clean_inheritance
        }
    }

    if {[permission::inherit_p -object_id $source_folder_id]} {
        permission::copy -from_object_id [content::item::get_parent_folder -item_id $source_folder_id] -to_object_id $new_parent_folder_id -clean_inheritance -overwrite
    } else {
        permission::copy -from_object_id $source_folder_id -to_object_id $new_parent_folder_id -clean_inheritance -overwrite
    }
}