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)
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
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)
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 = ''' <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)
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
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)