Example #1
0
def inherit_vgrid_files(vgrid, configuration):
    """Transfer ownership of all files which belong to the given VGrid argument
    to parent VGrid. This is the default when a nested VGrid is removed.
    This corresponds to the functionality in createvgrid.py, but we 
    can make our life easy by moving recursively, using a function
    in fileio.py for this purpose. The VGrid shared and web folders are taken
    over entirely by parent and the for new flat style VGrids it is more work
    because they require migration of linked dir into parent one.
    The function recursively moves the following directories: 
            configuration.vgrid_public_base/<vgrid>
            configuration.vgrid_private_base/<vgrid>
            configuration.vgrid_files_home/<vgrid>
    including any actual data for new flat format vgrids in
            configuration.vgrid_files_writable/<vgrid>

    vgrid: The name of the VGrid to let parent take over
    configuration: to determine the location of the directories 

    Note: the entry for the VGrid itself, configuration.vgrid_home/<vgrid>
            is removed separately, see remove_vgrid_entry
    Returns: Success indicator and potential messages.
    """

    _logger = configuration.logger
    _logger.debug('Migrate all files for vgrid %s to parent' % vgrid)
    success = True
    msg = ""

    parent_vgrid = vgrid_list_parents(vgrid, configuration)[-1]
    for prefix in [configuration.vgrid_public_base,
                   configuration.vgrid_private_base,
                   configuration.vgrid_files_home]:
        data_path = os.path.join(prefix, vgrid)
        parent_dir_path = os.path.join(prefix, parent_vgrid)
        # VGrids on flat format with readonly support has a link and a dir.
        # The actual linked dir must then be renamed/moved to replace the link.
        if os.path.islink(data_path):
            link_path = data_path
            link_name = os.path.basename(link_path)
            parent_data_path = os.path.join(parent_dir_path, link_name)
            data_path = os.path.realpath(link_path)
            _logger.debug('delete symlink: %s' % link_path)
            delete_symlink(link_path, _logger)

            _logger.debug('migrate old vgrid dir %s to %s' %
                          (data_path, parent_data_path))
            success_here = move_rec(data_path, parent_data_path, configuration)
            if not success_here:
                kind = prefix.strip(os.sep).split(os.sep)[-1]
                msg += "Error while migrating %s %s to parent" % (vgrid, kind)
                success = False
    if msg:
        _logger.debug('Messages: %s.' % msg)

    return (success, msg)
Example #2
0
def vgrid_inherit_map(configuration, vgrid_map):
    """Takes a vgrid_map and returns a copy extended with inherited values.
    That is, if the vgrid_map has vgrid A with owner John Doe all sub-vgrids
    A/B, A/B/C, A/M, etc. get their owner list set to include John Doe as well.
    """
    inherit_map = copy.deepcopy(vgrid_map)
    # Sort vgrids and extend participation from the end to keep it simple
    # and efficient
    all_vgrids = inherit_map[VGRIDS].keys()
    all_vgrids.sort()
    for vgrid_name in all_vgrids[::-1]:
        vgrid = inherit_map[VGRIDS][vgrid_name]
        for parent_name in vgrid_list_parents(vgrid_name, configuration):
            parent_vgrid = inherit_map[VGRIDS][parent_name]
            for field in (OWNERS, MEMBERS, RESOURCES):
                vgrid[field] += [i for i in parent_vgrid[field] if not i in \
                                 vgrid[field]]
    return inherit_map
Example #3
0
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    defaults = signature()[1]
    title_entry = find_entry(output_objects, 'title')
    label = "%s" % configuration.site_vgrid_label
    title_entry['text'] = "Remove %s Owner" % label
    output_objects.append({'object_type': 'header', 'text':
                           'Remove %s Owner' % label})
    (validate_status, accepted) = validate_input_and_cert(
        user_arguments_dict,
        defaults,
        output_objects,
        client_id,
        configuration,
        allow_rejects=False,
    )
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    vgrid_name = accepted['vgrid_name'][-1]
    flags = ''.join(accepted['flags'])
    cert_id = accepted['cert_id'][-1]
    cert_dir = client_id_dir(cert_id)
    # inherited vgrid membership
    inherit_vgrid_member = False

    if not safe_handler(configuration, 'post', op_name, client_id,
                        get_csrf_limit(configuration), accepted):
        output_objects.append(
            {'object_type': 'error_text', 'text': '''Only accepting
CSRF-filtered POST requests to prevent unintended updates'''
             })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # always allow owner to remove self
    if client_id != cert_id:

        user_map = get_full_user_map(configuration)
        user_dict = user_map.get(client_id, None)
        # Optional site-wide limitation of manage vgrid permission
        if not user_dict or \
                not vgrid_manage_allowed(configuration, user_dict):
            logger.warning("user %s is not allowed to manage vgrids!" %
                           client_id)
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 'Only privileged users can manage %ss' % label})
            return (output_objects, returnvalues.CLIENT_ERROR)

        # make sure vgrid settings allow this owner to edit other owners
        (allow_status, allow_msg) = allow_owners_adm(configuration, vgrid_name,
                                                     client_id)
        if not allow_status:
            output_objects.append({'object_type': 'error_text', 'text':
                                   allow_msg})
            return (output_objects, returnvalues.CLIENT_ERROR)

    # Validity of user and vgrid names is checked in this init function so
    # no need to worry about illegal directory traversal through variables

    (ret_val, msg, _) = \
        init_vgrid_script_add_rem(vgrid_name, client_id, cert_id,
                                  'owner', configuration)
    if not ret_val:
        output_objects.append({'object_type': 'error_text', 'text': msg})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # don't remove if not already an owner

    if not vgrid_is_owner(vgrid_name, cert_id, configuration):
        logger.warning('%s is not allowed to remove owner %s from %s' %
                       (client_id, cert_id, vgrid_name))
        output_objects.append({'object_type': 'error_text', 'text':
                               '%s is not an owner of %s or a parent %s.' %
                               (cert_id, vgrid_name, label)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # we need the local owners file to detect inherited ownerships

    (owners_status, owners_direct) = vgrid_owners(vgrid_name, configuration,
                                                  False)
    (all_status, owners) = vgrid_owners(vgrid_name, configuration, True)
    if not owners_status or not all_status:
        logger.error('Error loading owners for %s: %s / %s'
                     % (vgrid_name, owners_direct, owners))
        output_objects.append(
            {'object_type': 'error_text', 'text':
             'An internal error occurred, error conditions have been logged.'})
        output_objects.append({'object_type': 'text', 'text': '''
         You can help us fix the problem by notifying the administrators
         via mail about what you wanted to do when the error happened.'''})
        return (output_objects, returnvalues.CLIENT_ERROR)

    logger.info('%s removing owner %s from %s' % (client_id, cert_id,
                                                  vgrid_name))

    # find out whether to just remove an owner or delete the whole thing.
    # ask about delete if last or no direct owners.

    if len(owners_direct) > 1:

        logger.debug('Removing %s, one of several owners, from %s.' %
                     (cert_id, vgrid_name))

        if not (cert_id in owners_direct):

            # the owner owns an upper vgrid, ownership is inherited
            # cannot remove, not last (inherited) owner

            logger.warning('Cannot delete: Inherited ownership.' +
                           '\n Owners: %s,\n Direct owners: %s.'
                           % (owners, owners_direct))
            output_objects.append({'object_type': 'error_text', 'text':
                                   '''%s is owner of a parent %s. 
Owner removal has to be performed at the topmost vgrid''' %
                                   (cert_id, label)})
            return (output_objects, returnvalues.CLIENT_ERROR)

        else:

            # Remove any tracker admin rights

            if configuration.trac_admin_path:
                public_tracker_dir = \
                    os.path.abspath(os.path.join(
                        configuration.vgrid_public_base, vgrid_name,
                        '.vgridtracker'))
                private_tracker_dir = \
                    os.path.abspath(os.path.join(
                        configuration.vgrid_private_base, vgrid_name,
                        '.vgridtracker'))
                vgrid_tracker_dir = \
                    os.path.abspath(os.path.join(
                        configuration.vgrid_files_home, vgrid_name,
                        '.vgridtracker'))
                for tracker_dir in [public_tracker_dir, private_tracker_dir,
                                    vgrid_tracker_dir]:
                    if not rm_tracker_admin(configuration, cert_id,
                                            vgrid_name, tracker_dir,
                                            output_objects):
                        return (output_objects, returnvalues.SYSTEM_ERROR)

            user_dir = os.path.abspath(os.path.join(configuration.user_home,
                                                    cert_dir)) + os.sep

            # Do not touch vgrid share if still a member of a parent vgrid

            if vgrid_is_member(vgrid_name, cert_id, configuration):
                # list is in top-down order
                parent_vgrids = vgrid_list_parents(vgrid_name, configuration)
                inherit_vgrid_member = vgrid_name
                for parent in parent_vgrids:
                    if vgrid_is_member(parent, cert_id, configuration,
                                       recursive=False):
                        inherit_vgrid_member = parent
                        break
                output_objects.append(
                    {'object_type': 'text', 'text':
                     '''NOTE: %s is still a member of parent %s %s.
Preserving access to corresponding %s.''' % (cert_id, label,
                                             inherit_vgrid_member, label)})
            else:
                (success, msg) = unlink_share(user_dir, vgrid_name)
                if not success:
                    logger.error('Could not remove share link: %s.' % msg)
                    output_objects.append({'object_type': 'error_text', 'text':
                                           'Could not remove share links: %s.'
                                           % msg})
                    return (output_objects, returnvalues.SYSTEM_ERROR)

            # unlink shared web folders

            (success, msg) = unlink_web_folders(user_dir, vgrid_name)
            if not success:
                logger.error('Could not remove web links: %s.' % msg)
                output_objects.append({'object_type': 'error_text', 'text':
                                       'Could not remove web links: %s.'
                                       % msg})
                return (output_objects, returnvalues.SYSTEM_ERROR)

            # remove user from saved owners list
            (rm_status, rm_msg) = vgrid_remove_owners(configuration, vgrid_name,
                                                      [cert_id])
            if not rm_status:
                output_objects.append({'object_type': 'error_text', 'text':
                                       '%s of owners of %s'
                                       % (rm_msg, vgrid_name)})
                return (output_objects, returnvalues.SYSTEM_ERROR)

            # Any parent vgrid membership is left untouched here as we only
            # force a normal refresh in unmap_inheritance
            unmap_inheritance(configuration, vgrid_name, cert_id)

            output_objects.append({'object_type': 'text', 'text':
                                   '%s successfully removed as owner of %s!'
                                   % (cert_id, vgrid_name)})
            output_objects.append({'object_type': 'link', 'destination':
                                   'adminvgrid.py?vgrid_name=%s' % vgrid_name, 'text':
                                   'Back to administration for %s' % vgrid_name})
            return (output_objects, returnvalues.OK)

    else:

        # no more direct owners - we try to remove this VGrid

        logger.debug('Leave %s from %s with no more direct owners: delete' %
                     (vgrid_name, cert_id))

        if not force(flags):
            output_objects.append({'object_type': 'text', 'text': '''
No more direct owners of %s - leaving will result in the %s getting
deleted. Please use either of the links below to confirm or cancel.
''' % (vgrid_name, label)})
            # Reuse csrf token from this request
            target_op = 'rmvgridowner'
            js_name = target_op
            csrf_token = accepted[csrf_field][-1]
            helper = html_post_helper(js_name, '%s.py' % target_op,
                                      {'vgrid_name': vgrid_name,
                                       'cert_id': cert_id, 'flags': 'f',
                                       csrf_field: csrf_token})
            output_objects.append({'object_type': 'html_form', 'text': helper})
            output_objects.append({'object_type': 'link', 'destination':
                                   "javascript: %s();" % js_name, 'class':
                                   'removelink iconspace', 'text':
                                   'Really leave and delete %s' % vgrid_name})
            output_objects.append({'object_type': 'text', 'text': ''})
            output_objects.append({'object_type': 'link', 'destination':
                                   'adminvgrid.py?vgrid_name=%s' % vgrid_name,
                                   'text': 'Back to administration for %s'
                                   % vgrid_name})
            return (output_objects, returnvalues.OK)

        # check if any resources participate or sub-vgrids depend on this one

        (list_status, subs) = vgrid_list_subvgrids(vgrid_name, configuration)

        if not list_status:
            logger.error('Error loading sub-vgrid for %s: %s)' % (vgrid_name,
                                                                  subs))
            output_objects.append({'object_type': 'error_text', 'text': '''
An internal error occurred, error conditions have been logged.'''})
            output_objects.append({'object_type': 'text', 'text': '''
You can help us fix the problem by notifying the administrators
via mail about what you wanted to do when the error happened.'''})
            return (output_objects, returnvalues.CLIENT_ERROR)

        if len(subs) > 0:
            logger.debug('Cannot delete: still has sub-vgrids: %s' % subs)
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 '%s has one or more child %ss and cannot be deleted.' %
                 (vgrid_name, label)})
            output_objects.append(
                {'object_type': 'text', 'text': '''To leave (and delete) %s
first remove all its children: %s.''' % (vgrid_name, ', '.join(subs))})
            return (output_objects, returnvalues.CLIENT_ERROR)

        # we consider the local members and resources here, not inherited ones

        (member_status, members_direct) = vgrid_members(vgrid_name,
                                                        configuration,
                                                        False)
        (resource_status, resources_direct) = vgrid_resources(vgrid_name,
                                                              configuration,
                                                              False)
        if not member_status or not resource_status:
            logger.warning('failed to load %s members or resources: %s %s'
                           % (vgrid_name, members_direct, resources_direct))
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 'could not load %s members or resources for %s.' %
                 (label, vgrid_name)})
            return (output_objects, returnvalues.SYSTEM_ERROR)
        if len(resources_direct) > 0:
            logger.debug('Cannot delete: still has direct resources %s.'
                         % resources_direct)
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 '%s still has resources and cannot be deleted.' % vgrid_name})
            output_objects.append({'object_type': 'text', 'text': '''
To leave (and delete) %s, first remove the participating resources.'''
                                   % vgrid_name})

            return (output_objects, returnvalues.CLIENT_ERROR)

        if len(members_direct) > 0:

            logger.debug('Cannot delete: still has direct members %s.'
                         % members_direct)
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 '%s still has members and cannot be deleted.' % vgrid_name})
            output_objects.append({'object_type': 'text', 'text': '''
To leave (and delete) %s, first remove all members.'''
                                   % vgrid_name})

            return (output_objects, returnvalues.CLIENT_ERROR)

        # Deleting write restricted VGrid is not allowed

        (load_status, saved_settings) = vgrid_settings(vgrid_name,
                                                       configuration,
                                                       recursive=True,
                                                       as_dict=True)
        if not load_status:
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 'failed to load saved %s settings' % vgrid_name})
            return (output_objects, returnvalues.SYSTEM_ERROR)

        if saved_settings.get('write_shared_files', keyword_members) != \
                keyword_members:
            logger.warning("%s can't delete vgrid %s - write limited!"
                           % (client_id, vgrid_name))
            output_objects.append(
                {'object_type': 'error_text', 'text': """You can't delete
write-restricted %ss - first remove any write restrictions for shared files
on the admin page and then try again.""" % label})
            return (output_objects, returnvalues.CLIENT_ERROR)

        # When reaching here, OK to remove the VGrid.
        #   if top-level: unlink, remove all files and directories,
        #   in all cases: remove configuration entry for the VGrid
        #   unlink and move new-style vgrid sub dir to parent

        logger.info('Deleting %s and all related data as requested by %s' %
                    (vgrid_name, cert_id))

        if (cert_id in owners_direct):

            # owner owns this vgrid, direct ownership

            logger.debug('%s looks like a top-level vgrid.' % vgrid_name)
            logger.debug('Deleting all related files.')

            user_dir = os.path.abspath(os.path.join(configuration.user_home,
                                                    cert_dir)) + os.sep
            (share_lnk, share_msg) = unlink_share(user_dir, vgrid_name)
            (web_lnk, web_msg) = unlink_web_folders(user_dir, vgrid_name)
            (files_act, files_msg) = abandon_vgrid_files(vgrid_name,
                                                         configuration)
        else:

            # owner owns some parent vgrid - ownership is only inherited

            logger.debug('%s looks like a sub-vgrid, ownership inherited.' %
                         vgrid_name)
            logger.debug('Only removing entry, leaving files in place.')
            share_lnk, share_msg = True, ''
            web_lnk, web_msg = True, ''
            (files_act, files_msg) = inherit_vgrid_files(vgrid_name,
                                                         configuration)

        (removed, entry_msg) = remove_vgrid_entry(vgrid_name, configuration)

        output_objects.append({'object_type': 'text', 'text':
                               '%s has been removed with last owner.'
                               % vgrid_name})

        output_objects.append({'object_type': 'link',
                               'destination': 'vgridman.py',
                               'text': 'Back to the overview.'})

        if not share_lnk or not web_lnk or not files_act or not removed:
            err = '\n'.join([share_msg, web_msg, files_msg, entry_msg])
            logger.error('Errors while removing %s:\n%s.' % (vgrid_name, err))

            output_objects.append({'object_type': 'error_text', 'text': '''
An internal error occurred, error conditions have been logged.'''})
            output_objects.append({'object_type': 'text', 'text': '''
You can help us fix the problem by notifying the administrators
via mail about what you wanted to do when the error happened.'''})
            return (output_objects, returnvalues.CLIENT_ERROR)

        else:

            # Remove vgrid from vgrid cache (after deleting all)
            unmap_vgrid(configuration, vgrid_name)
            return (output_objects, returnvalues.OK)
Example #4
0
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    defaults = signature()[1]
    title_entry = find_entry(output_objects, 'title')
    label = "%s" % configuration.site_vgrid_label
    title_entry['text'] = "Administrate %s" % label
    # NOTE: Delay header entry here to include vgrid name
    (validate_status, accepted) = validate_input_and_cert(
        user_arguments_dict,
        defaults,
        output_objects,
        client_id,
        configuration,
        allow_rejects=False,
    )
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    vgrid_name = accepted['vgrid_name'][-1]

    # prepare for confirm dialog, tablesort and toggling the views (css/js)

    # jquery support for tablesorter and confirmation on request and leave
    # requests table initially sorted by 0, 4, 3 (type first, then date and
    # with alphabetical client ID last)
    # sharelinks table initially sorted by 5, 4 reversed (active first and
    # in growing age)

    table_specs = [{
        'table_id': 'accessrequeststable',
        'pager_id': 'accessrequests_pager',
        'sort_order': '[[0,0],[4,0],[3,0]]'
    }, {
        'table_id': 'sharelinkstable',
        'pager_id': 'sharelinks_pager',
        'sort_order': '[[5,1],[4,1]]'
    }]
    (add_import, add_init, add_ready) = man_base_js(configuration, table_specs,
                                                    {'width': 600})
    add_init += '''
        var toggleHidden = function(classname) {
            // classname supposed to have a leading dot
            $(classname).toggleClass("hidden");
        };
        /* helpers for dynamic form input fields */
        function onOwnerInputChange() {
            makeSpareFields("#dynownerspares", "cert_id");
        }
        function onMemberInputChange() {
            makeSpareFields("#dynmemberspares", "cert_id");
        }
        function onResourceInputChange() {
            makeSpareFields("#dynresourcespares", "unique_resource_name");
        }
    '''
    add_ready += '''
    /* init add owners/member/resource forms with dynamic input fields */
    onOwnerInputChange();
    $("#dynownerspares").on("blur", "input[name=cert_id]",
        function(event) {
            //console.debug("in add owner blur handler");
            onOwnerInputChange();
        }
    );
    onMemberInputChange();
    $("#dynmemberspares").on("blur", "input[name=cert_id]",
        function(event) {
            //console.debug("in add member blur handler");
            onMemberInputChange();
        }
    );'''
    if configuration.site_enable_resources:
        add_ready += '''
    onResourceInputChange();
    $("#dynresourcespares").on("blur", "input[name=unique_resource_name]",
        function(event) {
            console.debug("in resource blur handler");
            onResourceInputChange();
        }
    );
    '''
    title_entry['script']['advanced'] += add_import
    title_entry['script']['init'] += add_init
    title_entry['script']['ready'] += add_ready
    output_objects.append({
        'object_type': 'html_form',
        'text': man_base_html(configuration)
    })

    form_method = 'post'
    csrf_limit = get_csrf_limit(configuration)
    fill_helpers = {
        'short_title': configuration.short_title,
        'vgrid_label': label,
        'form_method': form_method,
        'csrf_field': csrf_field,
        'csrf_limit': csrf_limit
    }

    output_objects.append({
        'object_type': 'header',
        'text': "Administrate '%s'" % vgrid_name
    })

    if not vgrid_is_owner(vgrid_name, client_id, configuration):
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Only owners of %s can administrate it.' % vgrid_name
        })
        target_op = "sendrequestaction"
        csrf_token = make_csrf_token(configuration, form_method, target_op,
                                     client_id, csrf_limit)
        js_name = 'reqvgridowner%s' % hexlify(vgrid_name)
        helper = html_post_helper(
            js_name, '%s.py' % target_op, {
                'vgrid_name': vgrid_name,
                'request_type': 'vgridowner',
                'request_text': '',
                csrf_field: csrf_token
            })
        output_objects.append({'object_type': 'html_form', 'text': helper})
        output_objects.append({
            'object_type':
            'link',
            'destination':
            "javascript: confirmDialog(%s, '%s', '%s');" %
            (js_name, "Request ownership of " + vgrid_name + ":<br/>" +
             "\nPlease write a message to the owners below.", 'request_text'),
            'class':
            'addadminlink iconspace',
            'title':
            'Request ownership of %s' % vgrid_name,
            'text':
            'Apply to become an owner'
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    for (item, scr) in zip(['owner', 'member', 'resource'],
                           ['vgridowner', 'vgridmember', 'vgridres']):
        if item == 'resource' and not configuration.site_enable_resources:
            continue
        output_objects.append({
            'object_type': 'sectionheader',
            'text': "%ss" % item.title()
        })
        (init_status, oobjs) = vgrid_add_remove_table(client_id, vgrid_name,
                                                      item, scr, configuration)
        if not init_status:
            output_objects.extend(oobjs)
            return (output_objects, returnvalues.SYSTEM_ERROR)
        else:
            output_objects.append({
                'object_type': 'html_form',
                'text': '<div class="div-%s">' % item
            })
            output_objects.append({
                'object_type':
                'link',
                'destination':
                "javascript:toggleHidden('.div-%s');" % item,
                'class':
                'removeitemlink iconspace',
                'title':
                'Toggle view',
                'text':
                'Hide %ss' % item.title()
            })
            output_objects.extend(oobjs)
            output_objects.append({
                'object_type':
                'html_form',
                'text':
                '</div><div class="hidden div-%s">' % item
            })
            output_objects.append({
                'object_type':
                'link',
                'destination':
                "javascript:toggleHidden('.div-%s');" % item,
                'class':
                'additemlink iconspace',
                'title':
                'Toggle view',
                'text':
                'Show %ss' % item.title()
            })
            output_objects.append({
                'object_type': 'html_form',
                'text': '</div>'
            })

    # Pending requests

    target_op = "addvgridowner"
    csrf_token = make_csrf_token(configuration, form_method, target_op,
                                 client_id, csrf_limit)
    helper = html_post_helper(
        "acceptvgridownerreq", "%s.py" % target_op, {
            'vgrid_name': vgrid_name,
            'cert_id': '__DYNAMIC__',
            'request_name': '__DYNAMIC__',
            csrf_field: csrf_token
        })
    output_objects.append({'object_type': 'html_form', 'text': helper})
    target_op = "addvgridmember"
    csrf_token = make_csrf_token(configuration, form_method, target_op,
                                 client_id, csrf_limit)
    helper = html_post_helper(
        "acceptvgridmemberreq", "%s.py" % target_op, {
            'vgrid_name': vgrid_name,
            'cert_id': '__DYNAMIC__',
            'request_name': '__DYNAMIC__',
            csrf_field: csrf_token
        })
    output_objects.append({'object_type': 'html_form', 'text': helper})
    target_op = "addvgridres"
    csrf_token = make_csrf_token(configuration, form_method, target_op,
                                 client_id, csrf_limit)
    helper = html_post_helper(
        "acceptvgridresourcereq", "%s.py" % target_op, {
            'vgrid_name': vgrid_name,
            'unique_resource_name': '__DYNAMIC__',
            'request_name': '__DYNAMIC__',
            csrf_field: csrf_token
        })
    output_objects.append({'object_type': 'html_form', 'text': helper})
    target_op = "rejectvgridreq"
    csrf_token = make_csrf_token(configuration, form_method, target_op,
                                 client_id, csrf_limit)
    helper = html_post_helper(
        "rejectvgridreq", "%s.py" % target_op, {
            'vgrid_name': vgrid_name,
            'request_name': '__DYNAMIC__',
            csrf_field: csrf_token
        })
    output_objects.append({'object_type': 'html_form', 'text': helper})

    request_dir = os.path.join(configuration.vgrid_home, vgrid_name)
    request_list = []
    for req_name in list_access_requests(configuration, request_dir):
        req = load_access_request(configuration, request_dir, req_name)
        if not req:
            continue
        if not req.get('request_type',
                       None) in ["vgridowner", "vgridmember", "vgridresource"]:
            logger.error("unexpected request_type %(request_type)s" % req)
            continue
        request_item = build_accessrequestitem_object(configuration, req)
        # Convert filename with exotic chars into url-friendly pure hex version
        shared_args = {"request_name": hexlify(req["request_name"])}
        accept_args, reject_args = {}, {}
        accept_args.update(shared_args)
        reject_args.update(shared_args)
        if req['request_type'] == "vgridresource":
            accept_args["unique_resource_name"] = req["entity"]
        else:
            accept_args["cert_id"] = req["entity"]

        request_item['acceptrequestlink'] = {
            'object_type':
            'link',
            'destination':
            "javascript: confirmDialog(%s, '%s', %s, %s);" %
            ("accept%(request_type)sreq" % req,
             "Accept %(target)s %(request_type)s request from %(entity)s" %
             req, 'undefined', "{%s}" %
             ', '.join(["'%s': '%s'" % pair for pair in accept_args.items()])),
            'class':
            'addlink iconspace',
            'title':
            'Accept %(target)s %(request_type)s request from %(entity)s' % req,
            'text':
            ''
        }
        request_item['rejectrequestlink'] = {
            'object_type':
            'link',
            'destination':
            "javascript: confirmDialog(%s, '%s', %s, %s);" %
            ("rejectvgridreq",
             "Reject %(target)s %(request_type)s request from %(entity)s" %
             req, 'undefined', "%s" % reject_args),
            'class':
            'removelink iconspace',
            'title':
            'Reject %(target)s %(request_type)s request from %(entity)s' % req,
            'text':
            ''
        }

        request_list.append(request_item)

    output_objects.append({
        'object_type': 'sectionheader',
        'text': "Pending Requests"
    })
    output_objects.append({
        'object_type': 'table_pager',
        'id_prefix': 'accessrequests_',
        'entry_name': 'access requests',
        'default_entries': default_pager_entries
    })
    output_objects.append({
        'object_type': 'accessrequests',
        'accessrequests': request_list
    })

    # VGrid Share links

    # Table columns to skip
    skip_list = [
        'editsharelink', 'delsharelink', 'invites', 'expire', 'single_file'
    ]

    # NOTE: Inheritance is a bit tricky for sharelinks because parent shares
    # only have relevance if they actually share a path that is a prefix of
    # vgrid_name.

    (share_status, share_list) = vgrid_sharelinks(vgrid_name, configuration)
    sharelinks = []
    if share_status:
        for share_dict in share_list:
            rel_path = share_dict['path'].strip(os.sep)
            parent_vgrids = vgrid_list_parents(vgrid_name, configuration)
            include_share = False
            # Direct sharelinks (careful not to greedy match A/B with A/BCD)
            if rel_path == vgrid_name or \
                    rel_path.startswith(vgrid_name+os.sep):
                include_share = True
            # Parent vgrid sharelinks that in effect also give access here
            for parent in parent_vgrids:
                if rel_path == parent:
                    include_share = True
            if include_share:
                share_item = build_sharelinkitem_object(
                    configuration, share_dict)
                sharelinks.append(share_item)
    else:
        logger.warning("failed to load vgrid sharelinks for %s: %s" %
                       (vgrid_name, share_list))

    output_objects.append({
        'object_type': 'sectionheader',
        'text': "Share Links"
    })
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '<p>Current share links in %s shared folder</p>' % vgrid_name
    })
    output_objects.append({
        'object_type': 'table_pager',
        'id_prefix': 'sharelinks_',
        'entry_name': 'share links',
        'default_entries': default_pager_entries
    })
    output_objects.append({
        'object_type': 'sharelinks',
        'sharelinks': sharelinks,
        'skip_list': skip_list
    })

    # VGrid settings

    output_objects.append({'object_type': 'sectionheader', 'text': "Settings"})

    (direct_status, direct_dict) = vgrid_settings(vgrid_name,
                                                  configuration,
                                                  recursive=False,
                                                  as_dict=True)
    if not direct_status or not direct_dict:
        direct_dict = {}
    (settings_status, settings_dict) = vgrid_settings(vgrid_name,
                                                      configuration,
                                                      recursive=True,
                                                      as_dict=True)
    if not settings_status or not settings_dict:
        settings_dict = {}
    form_method = 'post'
    csrf_limit = get_csrf_limit(configuration)
    # Always set these values
    settings_dict.update({
        'vgrid_name': vgrid_name,
        'vgrid_label': label,
        'owners': keyword_owners,
        'members': keyword_members,
        'all': keyword_all,
        'form_method': form_method,
        'csrf_field': csrf_field,
        'csrf_limit': csrf_limit
    })
    target_op = 'vgridsettings'
    csrf_token = make_csrf_token(configuration, form_method, target_op,
                                 client_id, csrf_limit)
    settings_dict.update({'target_op': target_op, 'csrf_token': csrf_token})

    settings_form = '''
    <form method="%(form_method)s" action="%(target_op)s.py">
        <fieldset>
            <legend>%(vgrid_label)s configuration</legend>
                <input type="hidden" name="%(csrf_field)s" value="%(csrf_token)s" />
                <input type="hidden" name="vgrid_name" value="%(vgrid_name)s" />
'''
    description = settings_dict.get('description', '')
    settings_form += '''
            <h4>Public description</h4>
                <textarea class="fillwidth padspace" name="description" rows=10
                    >%s</textarea>
''' % description
    settings_form += '<br/>'

    settings_form += '''<p>All visibility options below can be set to owners,
members or everyone and by default only owners can see participation. In effect
setting visibility to <em>members</em> means that owners and members can see
the corresponding participants. Similarly setting a visibility flag to
<em>everyone</em> means that all %s users can see the participants.</p>
''' % configuration.short_title
    visibility_options = [("Owners are visible to", "visible_owners"),
                          ("Members are visible to", "visible_members"),
                          ("Resources are visible to", "visible_resources")]
    for (title, field) in visibility_options:
        settings_form += '<h4>%s</h4>' % title
        if direct_dict.get(field, False):
            choices = _valid_visible + _reset_choice
        else:
            choices = _valid_visible + _keep_choice
        for (key, val) in choices:
            checked = ''
            if settings_dict.get(field, keyword_owners) == val:
                checked = "checked"
            settings_form += '''
            <input type="radio" name="%s" value="%s" %s/> %s
''' % (field, val, checked, key)
        settings_form += '<br/>'
    field = 'restrict_settings_adm'
    restrict_settings_adm = settings_dict.get(field,
                                              default_vgrid_settings_limit)
    if direct_dict.get(field, False):
        direct_note = _reset_note
    else:
        direct_note = _keep_note
    settings_form += '''
            <h4>Restrict Settings</h4>
            Restrict changing of these settings to only the first
            <input type="number" name="restrict_settings_adm" min=0 max=999
            minlength=1 maxlength=3 value=%d required />
            owners %s.
''' % (restrict_settings_adm, direct_note)
    settings_form += '<br/>'
    field = 'restrict_owners_adm'
    restrict_owners_adm = settings_dict.get(field,
                                            default_vgrid_settings_limit)
    if direct_dict.get(field, False):
        direct_note = _reset_note
    else:
        direct_note = _keep_note
    settings_form += '''
            <h4>Restrict Owner Administration</h4>
            Restrict administration of owners to only the first
            <input type="number" name="restrict_owners_adm" min=0 max=999
            minlength=1 maxlength=3 value=%d required />
            owners %s.
''' % (restrict_owners_adm, direct_note)
    settings_form += '<br/>'
    field = 'restrict_members_adm'
    restrict_members_adm = settings_dict.get(field,
                                             default_vgrid_settings_limit)
    if direct_dict.get(field, False):
        direct_note = _reset_note
    else:
        direct_note = _keep_note
    settings_form += '''
            <h4>Restrict Member Administration</h4>
            Restrict administration of members to only the first
            <input type="number" name="restrict_members_adm" min=0 max=999
            minlength=1 maxlength=3 value=%d required />
            owners %s.
''' % (restrict_members_adm, direct_note)
    settings_form += '<br/>'
    field = 'restrict_resources_adm'
    restrict_resources_adm = settings_dict.get(field,
                                               default_vgrid_settings_limit)
    if direct_dict.get(field, False):
        direct_note = _reset_note
    else:
        direct_note = _keep_note
    settings_form += '''
            <h4>Restrict Resource Administration</h4>
            Restrict administration of resources to only the first
            <input type="number" name="restrict_resources_adm" min=0 max=999
            minlength=1 maxlength=3 value=%d required />
            owners %s.
''' % (restrict_resources_adm, direct_note)
    settings_form += '<br/>'
    if vgrid_restrict_write_support(configuration):
        settings_form += '''<p>All write access options below can be set to
owners, members or none. By default only owners can write web pages while
owners and members can edit data in the shared folders. In effect setting write
access to <em>members</em> means that owners and members have full access.
Similarly setting a write access flag to <em>owners</em> means that only owners
can modify the data, while members can only read and use it. Finally setting a
write access flag to <em>none</em> means that neither owners nor members can
modify the data there, effectively making it read-only. Some options are not
yet supported and thus are disabled below.
</p>
'''
        writable_options = [
            ("Shared files write access", "write_shared_files",
             keyword_members),
            ("Private web page write access", "write_priv_web",
             keyword_owners),
            ("Public web page write access", "write_pub_web", keyword_owners),
        ]
    else:
        writable_options = []
    for (title, field, default) in writable_options:
        settings_form += '<h4>%s</h4>' % title
        if direct_dict.get(field, False):
            choices = _valid_write_access + _reset_choice
        else:
            choices = _valid_write_access + _keep_choice
        for (key, val) in choices:
            disabled = ''
            # TODO: remove these artifical limits once we support changing
            # TODO: also add check for vgrid web reshare in sharelink then
            if field == 'write_shared_files' and val == keyword_owners:
                disabled = 'disabled'
            elif field == 'write_priv_web' and val in [
                    keyword_members, keyword_none
            ]:
                disabled = 'disabled'
            elif field == 'write_pub_web' and val in [
                    keyword_members, keyword_none
            ]:
                disabled = 'disabled'
            checked = ''
            if settings_dict.get(field, default) == val:
                checked = "checked"
            settings_form += '''
            <input type="radio" name="%s" value="%s" %s %s /> %s
''' % (field, val, checked, disabled, key)
        settings_form += '<br/>'
    sharelink_options = [("Limit sharelink creation to", "create_sharelink")]
    for (title, field) in sharelink_options:
        settings_form += '<h4>%s</h4>' % title
        if direct_dict.get(field, False):
            choices = _valid_sharelink + _reset_choice
        else:
            choices = _valid_sharelink + _keep_choice
        for (key, val) in choices:
            checked = ''
            if settings_dict.get(field, keyword_owners) == val:
                checked = "checked"
            settings_form += '''
            <input type="radio" name="%s" value="%s" %s/> %s
''' % (field, val, checked, key)
        settings_form += '<br/>'
    field = 'request_recipients'
    request_recipients = settings_dict.get(field, default_vgrid_settings_limit)
    if direct_dict.get(field, False):
        direct_note = _reset_note
    else:
        direct_note = _keep_note
    settings_form += '''
            <h4>Request Recipients</h4>
            Notify only first
            <input type="number" name="request_recipients" min=0 max=999
            minlength=1 maxlength=3 value=%d required />
            owners about access requests %s.
''' % (request_recipients, direct_note)
    settings_form += '<br/>'

    bool_options = [
        ("Hidden", "hidden"),
    ]
    for (title, field) in bool_options:
        settings_form += '<h4>%s</h4>' % title
        if direct_dict.get(field, False):
            choices = _valid_bool + _reset_choice
        else:
            choices = _valid_bool + _keep_choice
        for (key, val) in choices:
            checked, inherit_note = '', ''
            if settings_dict.get(field, False) == val:
                checked = "checked"
            if direct_dict.get(field, False) != \
                    settings_dict.get(field, False):
                inherit_note = '''&nbsp;<span class="warningtext iconspace">
Forced by a parent %(vgrid_label)s. Please disable there first if you want to
change the value here.</span>''' % settings_dict
            settings_form += '''
            <input type="radio" name="%s" value="%s" %s /> %s
''' % (field, val, checked, key)
        settings_form += '%s<br/>' % inherit_note
    settings_form += '<br/>'

    settings_form += '''
            <input type="submit" value="Save settings" />
        </fieldset>
    </form>
'''
    output_objects.append({
        'object_type': 'html_form',
        'text': settings_form % settings_dict
    })

    # Checking/fixing of missing components

    output_objects.append({
        'object_type': 'sectionheader',
        'text': "Repair/Add Components"
    })
    target_op = 'updatevgrid'
    csrf_token = make_csrf_token(configuration, form_method, target_op,
                                 client_id, csrf_limit)
    settings_dict.update({'target_op': target_op, 'csrf_token': csrf_token})
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '''
      <form method="%(form_method)s" action="%(target_op)s.py">
        <input type="hidden" name="%(csrf_field)s" value="%(csrf_token)s" />
          <input type="hidden" name="vgrid_name" value="%(vgrid_name)s" />
          <input type="submit" value="Repair components" />
      </form>
''' % settings_dict
    })

    (owners_status, owners_direct) = vgrid_owners(vgrid_name, configuration,
                                                  False)
    if not owners_status:
        logger.error("failed to load owners for %s: %s" %
                     (vgrid_name, owners_direct))
        return (output_objects, returnvalues.SYSTEM_ERROR)
    (members_status, members_direct) = vgrid_members(vgrid_name, configuration,
                                                     False)
    if not members_status:
        logger.error("failed to load members for %s: %s" %
                     (vgrid_name, members_direct))
        return (output_objects, returnvalues.SYSTEM_ERROR)
    (resources_status,
     resources_direct) = vgrid_resources(vgrid_name, configuration, False)
    if not resources_status:
        logger.error("failed to load resources for %s: %s" %
                     (vgrid_name, resources_direct))
        return (output_objects, returnvalues.SYSTEM_ERROR)

    output_objects.append({
        'object_type': 'sectionheader',
        'text': "Delete %s " % vgrid_name
    })
    if len(owners_direct) > 1 or members_direct or resources_direct:
        output_objects.append({
            'object_type': 'html_form',
            'text': '''
To delete <b>%(vgrid)s</b> first remove all resources, members and owners
ending with yourself.
''' % {
                'vgrid': vgrid_name
            }
        })
    else:
        output_objects.append({
            'object_type': 'html_form',
            'text': '''
<p>As the last owner you can leave and delete <b>%(vgrid)s</b> including all
associated shared files and components.<br/>
</p>
<p class="warningtext">
You cannot undo such delete operations, so please use with great care!
</p>
''' % {
                'vgrid': vgrid_name
            }
        })
        target_op = "rmvgridowner"
        csrf_token = make_csrf_token(configuration, form_method, target_op,
                                     client_id, csrf_limit)
        js_name = 'rmlastvgridowner'
        helper = html_post_helper(
            js_name, '%s.py' % target_op, {
                'vgrid_name': vgrid_name,
                'cert_id': client_id,
                'flags': 'f',
                csrf_field: csrf_token
            })
        output_objects.append({'object_type': 'html_form', 'text': helper})
        output_objects.append({
            'object_type':
            'link',
            'destination':
            "javascript: confirmDialog(%s, '%s');" %
            (js_name, 'Really leave and delete %s?' % vgrid_name),
            'class':
            'removelink iconspace',
            'title':
            'Leave and delete %s' % vgrid_name,
            'text':
            'Leave and delete %s' % vgrid_name
        })

    # Spacing
    output_objects.append({
        'object_type':
        'html_form',
        'text':
        '''
            <div class="vertical-spacer"></div>
    '''
    })

    return (output_objects, returnvalues.OK)
Example #5
0
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    defaults = signature()[1]
    output_objects.append({'object_type': 'header', 'text'
                          : 'Add %s Owner' % configuration.site_vgrid_label})
    (validate_status, accepted) = validate_input_and_cert(
        user_arguments_dict,
        defaults,
        output_objects,
        client_id,
        configuration,
        allow_rejects=False,
        )
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    if not correct_handler('POST'):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : 'Only accepting POST requests to prevent unintended updates'})
        return (output_objects, returnvalues.CLIENT_ERROR)

    vgrid_name = accepted['vgrid_name'][-1].strip()
    cert_id = accepted['cert_id'][-1].strip()
    cert_dir = client_id_dir(cert_id)
    # inherited vgrid membership
    inherit_vgrid_member = False

    # Allow openid alias as subject if openid with alias is enabled
    if configuration.user_openid_providers and configuration.user_openid_alias:
        cert_id = expand_openid_alias(cert_id, configuration)

    # Validity of user and vgrid names is checked in this init function so
    # no need to worry about illegal directory traversal through variables

    (ret_val, msg, _) = \
        init_vgrid_script_add_rem(vgrid_name, client_id, cert_id,
                                  'owner', configuration)
    if not ret_val:
        output_objects.append({'object_type': 'error_text', 'text'
                              : msg})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # don't add if already an owner

    if vgrid_is_owner(vgrid_name, cert_id, configuration):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : '%s is already an owner of %s or a parent %s.'
             % (cert_id, vgrid_name, configuration.site_vgrid_label)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # don't add if already a direct member

    if vgrid_is_member(vgrid_name, cert_id, configuration, recursive=False):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : '%s is already a member of %s - please remove first.'
             % (cert_id, vgrid_name)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # owner of subvgrid?

    (status, subvgrids) = vgrid_list_subvgrids(vgrid_name,
            configuration)
    if not status:
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'Error getting list of sub%ss: %s'
                               % (configuration.site_vgrid_label, subvgrids)})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    for subvgrid in subvgrids:
        if vgrid_is_owner(subvgrid, cert_id, configuration, recursive=False):
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : """%s is already an owner of a sub-%s ('%s'). Please
remove the person first and then try this operation again.""" % \
                 (cert_id, configuration.site_vgrid_label, subvgrid)})
            return (output_objects, returnvalues.CLIENT_ERROR)
        if vgrid_is_member(subvgrid, cert_id, configuration, recursive=False):
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : """%s is already a member of a sub-%s ('%s'). Please
remove the person first and then try this operation again.""" % \
                 (cert_id, configuration.site_vgrid_label, subvgrid)})
            return (output_objects, returnvalues.CLIENT_ERROR)

    # we DO allow ownership if member of parent vgrid - only handle with care

    if vgrid_is_member(vgrid_name, cert_id, configuration):
        # list is in top-down order 
        parent_vgrids = vgrid_list_parents(vgrid_name, configuration)
        inherit_vgrid_member = vgrid_name
        for parent in parent_vgrids:
            if vgrid_is_member(parent, cert_id, configuration,
                               recursive=False):
                inherit_vgrid_member = parent
                break
        output_objects.append(
            {'object_type': 'text', 'text'
             : '''NOTE: %s is already a member of parent %s %s.''' % \
             (cert_id, configuration.site_vgrid_label, inherit_vgrid_member)
             })

    # getting here means cert_id is not owner of any parent or child vgrids.
    # may still be member of a parent grid but not a child vgrid.

    public_base_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_public_base,
                        vgrid_name)) + os.sep
    private_base_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name)) + os.sep

    # Please note that base_dir must end in slash to avoid access to other
    # user dirs when own name is a prefix of another user name

    user_dir = os.path.abspath(os.path.join(configuration.user_home,
                               cert_dir)) + os.sep

    user_public_base = os.path.abspath(os.path.join(user_dir,
            'public_base')) + os.sep
    user_private_base = os.path.abspath(os.path.join(user_dir,
            'private_base')) + os.sep

    # make sure all dirs can be created (that a file or directory with the same
    # name do not exist prior to adding the owner)

    if os.path.exists(user_public_base + vgrid_name):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : '''Could not add owner, a file or directory in public_base
exists with the same name! %s''' % user_dir + vgrid_name})
        return (output_objects, returnvalues.CLIENT_ERROR)

    if os.path.exists(user_private_base + vgrid_name):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : '''Could not add owner, a file or directory in private_base
exists with the same name!'''})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # vgrid share already exists if user is a member of parent vgrid
    
    if not inherit_vgrid_member and os.path.exists(user_dir + vgrid_name):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : '''Could not add owner, a file or directory in the home
directory exists with the same name!'''})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Add

    (add_status, add_msg) = vgrid_add_owners(configuration, vgrid_name,
                                             [cert_id])
    if not add_status:
        output_objects.append({'object_type': 'error_text', 'text'
                              : add_msg})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    vgrid_name_parts = vgrid_name.split('/')
    is_subvgrid = len(vgrid_name_parts) > 1

    # create public_base in cert_ids home dir if it does not exists

    try:
        os.mkdir(user_public_base)
    except Exception, exc:
        pass
Example #6
0
def main(client_id, user_arguments_dict):
    """Main function used by front end"""

    (configuration, logger, output_objects, op_name) = \
        initialize_main_variables(client_id, op_header=False)
    defaults = signature()[1]
    (validate_status, accepted) = validate_input_and_cert(
        user_arguments_dict,
        defaults,
        output_objects,
        client_id,
        configuration,
        allow_rejects=False,
        )
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    if not correct_handler('POST'):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : 'Only accepting POST requests to prevent unintended updates'})
        return (output_objects, returnvalues.CLIENT_ERROR)

    vgrid_name = accepted['vgrid_name'][-1]
    flags = ''.join(accepted['flags'])
    cert_id = accepted['cert_id'][-1]
    cert_dir = client_id_dir(cert_id)
    # inherited vgrid membership
    inherit_vgrid_member = False

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Remove %s' % configuration.site_vgrid_label
    output_objects.append({'object_type': 'header', 'text'
                          : 'Remove %s Owner' % \
                           configuration.site_vgrid_label})

    # Validity of user and vgrid names is checked in this init function so
    # no need to worry about illegal directory traversal through variables

    (ret_val, msg, _) = \
        init_vgrid_script_add_rem(vgrid_name, client_id, cert_id,
                                  'owner', configuration)
    if not ret_val:
        output_objects.append({'object_type': 'error_text', 'text'
                              : msg})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # don't remove if not already an owner

    if not vgrid_is_owner(vgrid_name, cert_id, configuration):
        output_objects.append({'object_type': 'error_text', 'text'
                              : '%s is not an owner of %s or a parent %s.'
                               % (cert_id, vgrid_name,
                                  configuration.site_vgrid_label)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # we need the local owners file to detect inherited ownerships

    (status, owners_direct) = vgrid_owners(vgrid_name, configuration, False)
    (all_status, owners) = vgrid_owners(vgrid_name, configuration, True)
    if not status or not all_status:
        logger.error('Error loading owners for %s: %s / %s'
                     % (vgrid_name, owners_direct, owners))
        output_objects.append({'object_type': 'error_text', 'text'
         : 'An internal error occurred, error conditions have been logged.'})
        output_objects.append({'object_type': 'text', 'text'
         : '''
         You can help us fix the problem by notifying the administrators
         via mail about what you wanted to do when the error happened.'''})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # find out whether to just remove an owner or delete the whole thing.
    # ask about delete if last or no direct owners.

    if len(owners_direct) > 1:
        
        logger.debug('Removing %s, one of several owners, from %s.' % 
                     (cert_id, vgrid_name))

        if not (cert_id in owners_direct):

            # the owner owns an upper vgrid, ownership is inherited
            # cannot remove, not last (inherited) owner

            logger.debug('Cannot delete: Inherited ownership.' + 
                         '\n Owners: %s,\n Direct owners: %s.' 
                         % (owners, owners_direct))
            output_objects.append({'object_type': 'error_text', 'text'
                                   : '''%s is owner of a parent %s. 
Owner removal has to be performed at the topmost vgrid''' % \
                                   (cert_id, configuration.site_vgrid_label)})
            return (output_objects, returnvalues.CLIENT_ERROR)

        else:

            # Remove any tracker admin rights
            
            if configuration.trac_admin_path:
                public_tracker_dir = \
                                   os.path.abspath(os.path.join(
                    configuration.vgrid_public_base, vgrid_name,
                    '.vgridtracker'))
                private_tracker_dir = \
                                    os.path.abspath(os.path.join(
                    configuration.vgrid_private_base, vgrid_name,
                    '.vgridtracker'))
                vgrid_tracker_dir = \
                                  os.path.abspath(os.path.join(
                    configuration.vgrid_files_home, vgrid_name,
                    '.vgridtracker'))
                for tracker_dir in [public_tracker_dir, private_tracker_dir,
                                    vgrid_tracker_dir]:
                    if not rm_tracker_admin(configuration, cert_id,
                                             vgrid_name, tracker_dir,
                                             output_objects):
                        return (output_objects, returnvalues.SYSTEM_ERROR)

            user_dir = os.path.abspath(os.path.join(configuration.user_home,
                                                    cert_dir)) + os.sep
        
            # Do not touch vgrid share if still a member of a parent vgrid
            
            if vgrid_is_member(vgrid_name, cert_id, configuration):
                # list is in top-down order 
                parent_vgrids = vgrid_list_parents(vgrid_name, configuration)
                inherit_vgrid_member = vgrid_name
                for parent in parent_vgrids:
                    if vgrid_is_member(parent, cert_id, configuration,
                                       recursive=False):
                        inherit_vgrid_member = parent
                        break
                output_objects.append(
                    {'object_type': 'text', 'text'
                     : '''NOTE: %s is still a member of parent %s %s.
                     Preserving access to corresponding %s.''' % \
                     (cert_id, configuration.site_vgrid_label,
                      inherit_vgrid_member, configuration.site_vgrid_label)
                     })
            else:
                (success, msg) = unlink_share(user_dir, vgrid_name)
                if not success: 
                    logger.error('Could not remove share link: %s.' % msg)
                    output_objects.append({'object_type': 'error_text', 'text'
                                           : 'Could not remove share links: %s.'
                                           % msg})
                    return (output_objects, returnvalues.SYSTEM_ERROR)

            # unlink shared web folders

            (success, msg) = unlink_web_folders(user_dir, vgrid_name)
            if not success: 
                logger.error('Could not remove web links: %s.' % msg)
                output_objects.append({'object_type': 'error_text', 'text'
                                       : 'Could not remove web links: %s.' 
                                       % msg})
                return (output_objects, returnvalues.SYSTEM_ERROR)

            # remove user from saved owners list
            (rm_status, rm_msg) = vgrid_remove_owners(configuration, vgrid_name,
                                                     [cert_id])
            if not rm_status:
                output_objects.append({'object_type': 'error_text', 'text'
                                       : '%s of owners of %s' 
                                       % (rm_msg, vgrid_name)})
                return (output_objects, returnvalues.SYSTEM_ERROR)

            # Any parent vgrid membership is left untouched here as we only
            # force a normal refresh in unmap_inheritance
            unmap_inheritance(configuration, vgrid_name, cert_id)

            output_objects.append({'object_type': 'text', 'text'
                          : '%s successfully removed as owner of %s!'
                           % (cert_id, vgrid_name)})
            output_objects.append({'object_type': 'link', 'destination':
                           'adminvgrid.py?vgrid_name=%s' % vgrid_name, 'text':
                           'Back to administration for %s' % vgrid_name})
            return (output_objects, returnvalues.OK)

    else:
        
        # no more direct owners - we try to remove this VGrid

        logger.debug('Leave %s from %s with no more direct owners: delete' %
                     (vgrid_name, cert_id))

        if not force(flags):
            output_objects.append({'object_type': 'text', 'text' : '''
No more direct owners of %s - leaving will result in the %s getting
deleted. Please use either of the links below to confirm or cancel.
''' % (vgrid_name, configuration.site_vgrid_label)})
            js_name = 'rmvgridowner%s' % hexlify(vgrid_name)
            helper = html_post_helper(js_name, 'rmvgridowner.py',
                                      {'vgrid_name': vgrid_name,
                                       'cert_id': cert_id, 'flags': 'f'})
            output_objects.append({'object_type': 'html_form', 'text': helper})
            output_objects.append({'object_type': 'link', 'destination':
                                   "javascript: %s();" % js_name, 'class':
                                   'removelink', 'text':
                                   'Really leave and delete %s' % vgrid_name})
            output_objects.append({'object_type': 'text', 'text' : ''})
            output_objects.append({'object_type': 'link', 'destination':
                                   'adminvgrid.py?vgrid_name=%s' % vgrid_name,
                                   'text': 'Back to administration for %s'
                                   % vgrid_name})
            return (output_objects, returnvalues.OK)

        # check if any resources participate or sub-vgrids depend on this one

        (status, subs) = vgrid_list_subvgrids(vgrid_name, configuration)

        if not status:
            logger.error('Error loading sub-%ss for %s: %s)'
                         % (configuration.site_vgrid_label, vgrid_name, subs))
            output_objects.append({'object_type': 'error_text', 'text' : '''
An internal error occurred, error conditions have been logged.'''})
            output_objects.append({'object_type': 'text', 'text' : '''
You can help us fix the problem by notifying the administrators
via mail about what you wanted to do when the error happened.'''})
            return (output_objects, returnvalues.CLIENT_ERROR)

        if len(subs) > 0:

            logger.debug('Cannot delete: still has sub-%ss %s.'
                         % (configuration.site_vgrid_label, subs))
            output_objects.append({'object_type': 'error_text', 'text' : \
    '%s has sub-structures and cannot be deleted.' % vgrid_name})
            output_objects.append({'object_type': 'text', 'text' : '''
To leave (and delete) %s, first remove its sub-structures: %s.'''
                                      % (vgrid_name, ', '.join(subs))})

            return (output_objects, returnvalues.CLIENT_ERROR)

        # we consider the local members and resources here, not inherited ones
        
        (member_status, members_direct) = vgrid_members(vgrid_name,
                                                        configuration,
                                                        False)
        (resource_status, resources_direct) = vgrid_resources(vgrid_name,
                                                              configuration,
                                                              False)
        if not member_status or not resource_status:
            logger.warning('failed to load %s members or resources: %s %s'
                           % (vgrid_name, members_direct, resources_direct))
            output_objects.append({'object_type': 'error_text', 'text' : \
    'could not load %s members or resources for %s.' % \
                                   (configuration.site_vgrid_label,
                                    vgrid_name)})
            return (output_objects, returnvalues.SYSTEM_ERROR)
        if len(resources_direct) > 0:
            logger.debug('Cannot delete: still has direct resources %s.'
                         % resources_direct)
            output_objects.append({'object_type': 'error_text', 'text' : \
    '%s still has resources and cannot be deleted.' % vgrid_name})
            output_objects.append({'object_type': 'text', 'text' : '''
To leave (and delete) %s, first remove the participating resources.'''
                                      % vgrid_name})

            return (output_objects, returnvalues.CLIENT_ERROR)

        if len(members_direct) > 0:

            logger.debug('Cannot delete: still has direct members %s.'
                         % members_direct)
            output_objects.append({'object_type': 'error_text', 'text' : \
    '%s still has members and cannot be deleted.' % vgrid_name})
            output_objects.append({'object_type': 'text', 'text' : '''
To leave (and delete) %s, first remove all members.'''
                                      % vgrid_name})

            return (output_objects, returnvalues.CLIENT_ERROR)

        # When reaching here, OK to remove the VGrid.
        #   if top-level: unlink, remove all files and directories, 
        #   in all cases: remove configuration entry for the VGrid

        if (cert_id in owners_direct):

            # owner owns this vgrid, direct ownership

            logger.debug('%s looks like a top-level %s.' % \
                         (configuration.site_vgrid_label, vgrid_name))
            logger.debug('Deleting all related files.')

            user_dir = os.path.abspath(os.path.join(configuration.user_home,
                                                    cert_dir)) + os.sep
            (share_lnk, msg1)  = unlink_share(user_dir, vgrid_name)
            (web_lnk, msg1)  = unlink_web_folders(user_dir, vgrid_name)
            (abandoned, msg2) = abandon_vgrid_files(vgrid_name, configuration)
        else:

            # owner owns an upper vgrid, ownership is inherited

            logger.debug('%s looks like a sub-%s, ownership inherited.'
                         % (vgrid_name, configuration.site_vgrid_label))
            logger.debug('Only removing entry, leaving files in place.')
            share_lnk = True
            web_lnk = True
            abandoned = True
            msg1 = ''
            msg2 = ''

        (removed, msg3) = remove_vgrid_entry(vgrid_name, configuration)

        output_objects.append({'object_type': 'text', 'text'
                                   : '%s has been removed with last owner.'
                                      % vgrid_name})

        output_objects.append({'object_type': 'link', 
                               'destination': 'vgridadmin.py', 
                               'text': 'Back to the overview.'})

        if not share_lnk or not web_lnk or not abandoned or not removed:

            logger.error('Errors while removing %s:\n%s.'
                         % (vgrid_name, '\n'.join([msg1,msg2,msg3])))

            output_objects.append({'object_type': 'error_text', 'text' : '''
An internal error occurred, error conditions have been logged.'''})
            output_objects.append({'object_type': 'text', 'text' : '''
You can help us fix the problem by notifying the administrators
via mail about what you wanted to do when the error happened.'''})
            return (output_objects, returnvalues.CLIENT_ERROR)

        else:

            # Remove vgrid from vgrid cache (after deleting all)
            unmap_vgrid(configuration, vgrid_name)
            return (output_objects, returnvalues.OK)