Ejemplo n.º 1
0
def user_view_access(configuration, vgrid_name, client_id, settings_dict,
                     field):
    """Check if client_id has access to view field participation for
    vgrid_name based on saved settings_dict.
    """
    required = settings_dict.get(field, keyword_owners)

    if required == keyword_owners:
        access = vgrid_is_owner(vgrid_name, client_id, configuration)
    elif required == keyword_members:
        access = vgrid_is_owner_or_member(vgrid_name, client_id, configuration)
    elif required == keyword_all:
        access = True
    else:
        access = False
    return access
Ejemplo n.º 2
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 Resource" % label
    output_objects.append({
        'object_type': 'header',
        'text': 'Remove %s Resource' % 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]
    unique_resource_name = accepted['unique_resource_name'][-1].lower()

    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)

    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 resources

    (allow_status, allow_msg) = allow_resources_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, ret_variables) = \
        init_vgrid_script_add_rem(vgrid_name, client_id,
                                  unique_resource_name, 'resource',
                                  configuration)
    if not ret_val:
        output_objects.append({'object_type': 'error_text', 'text': msg})
        return (output_objects, returnvalues.CLIENT_ERROR)
    elif msg:

        # In case of warnings, msg is non-empty while ret_val remains True

        output_objects.append({'object_type': 'warning', 'text': msg})

    if not vgrid_is_owner(vgrid_name, client_id, configuration):
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''You must be an owner of the %s to
remove a resource!''' % label
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # don't remove if not a participant

    if not vgrid_is_resource(vgrid_name, unique_resource_name, configuration):
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '%s is not a resource in %s or a parent %s.' %
            (unique_resource_name, vgrid_name, label)
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # remove

    (rm_status, rm_msg) = vgrid_remove_resources(configuration, vgrid_name,
                                                 [unique_resource_name])
    if not rm_status:
        output_objects.append({'object_type': 'error_text', 'text': rm_msg})
        output_objects.append({
            'object_type': 'error_text',
            'text': '''%(res_name)s might be listed as a resource
of this %(vgrid_label)s because it is a resource of a parent %(vgrid_label)s.
Removal must be performed from the most significant %(vgrid_label)s possible.
''' % {
                'res_name': unique_resource_name,
                'vgrid_label': label
            }
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    output_objects.append({
        'object_type':
        'text',
        'text':
        'Resource %s successfully removed from %s %s!' %
        (unique_resource_name, vgrid_name, label)
    })
    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)
Ejemplo n.º 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'] = "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)
Ejemplo n.º 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]
    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
Ejemplo n.º 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]
    title_entry = find_entry(output_objects, 'title')
    label = "%s" % configuration.site_vgrid_label
    title_entry['text'] = "Add %s Member" % label
    output_objects.append({'object_type': 'header', 'text':
                           'Add %s Member(s)' % label})
    status = returnvalues.OK
    (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].strip()
    cert_id_list = accepted['cert_id']
    request_name = unhexlify(accepted['request_name'][-1])
    rank_list = accepted['rank'] + ['' for _ in cert_id_list]

    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)

    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 members

    (allow_status, allow_msg) = allow_members_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)

    cert_id_added = []
    for (cert_id, rank_str) in zip(cert_id_list, rank_list):
        cert_id = cert_id.strip()
        cert_dir = client_id_dir(cert_id)
        try:
            rank = int(rank_str)
        except ValueError:
            rank = None

        # 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,
                                      'member', configuration)
        if not ret_val:
            output_objects.append({'object_type': 'error_text', 'text':
                                   msg})
            status = returnvalues.CLIENT_ERROR
            continue

        # 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, label)})
            status = returnvalues.CLIENT_ERROR
            continue

        # don't add if already a member unless rank is given

        if rank is None and vgrid_is_member(vgrid_name, cert_id, configuration):
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 '''%s is already a member of %s or a parent %s. Please remove
    the person first and then try this operation again.''' %
                 (cert_id, vgrid_name, label)
                 })
            status = returnvalues.CLIENT_ERROR
            continue

        # owner or member of subvgrid?

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

        # TODO: we DO allow ownership of sub vgrids with parent membership so we
        # should support the (cumbersome) relinking of vgrid shares here. Leave it
        # to user to do it manually for now with temporary removal of ownership

        skip_entity = False
        for subvgrid in subvgrids:
            if vgrid_is_owner(subvgrid, cert_id, configuration, recursive=False):
                output_objects.append(
                    {'object_type': 'error_text', 'text':
                     """%(cert_id)s is already an owner of a
sub-%(vgrid_label)s ('%(subvgrid)s'). While we DO support members being owners
of sub-%(vgrid_label)ss, we do not support adding parent %(vgrid_label)s
members at the moment. Please (temporarily) remove the person as owner of all
sub-%(vgrid_label)ss first and then try this operation again.""" %
                     {'cert_id': cert_id, 'subvgrid': subvgrid,
                      'vgrid_label': label}})
                status = returnvalues.CLIENT_ERROR
                skip_entity = True
                break
            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, label, subvgrid)})
                status = returnvalues.CLIENT_ERROR
                skip_entity = True
                break
        if skip_entity:
            continue

        # Check if only rank change was requested and apply if so

        if rank is not None:
            (add_status, add_msg) = vgrid_add_members(configuration,
                                                      vgrid_name,
                                                      [cert_id], rank=rank)
            if not add_status:
                output_objects.append(
                    {'object_type': 'error_text', 'text': add_msg})
                status = returnvalues.SYSTEM_ERROR
            else:
                output_objects.append({'object_type': 'text', 'text':
                                       'changed %s to member %d' % (cert_id,
                                                                    rank)})
            # No further action after rank change as everything else exists
            continue

        # Getting here means cert_id is neither owner or member of any parent or
        # sub-vgrids.

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

        base_dir = os.path.abspath(os.path.join(configuration.vgrid_home,
                                                vgrid_name)) + os.sep
        user_dir = os.path.abspath(os.path.join(configuration.user_home,
                                                cert_dir)) + 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 member)

        if os.path.exists(user_dir + vgrid_name):
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 '''Could not add member, a file or directory in the home
directory called %s exists! (%s)''' % (vgrid_name, user_dir + vgrid_name)})
            status = returnvalues.CLIENT_ERROR
            continue

        # Add

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

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

        if is_subvgrid:
            try:

                # vgrid_name = IMADA/STUD/BACH
                # vgrid_name_last_fragment = BACH

                vgrid_name_last_fragment = \
                    vgrid_name_parts[len(vgrid_name_parts)
                                     - 1].strip()

                # vgrid_name_without_last_fragment = IMADA/STUD/

                vgrid_name_without_last_fragment = \
                    ('/'.join(vgrid_name_parts[0:len(vgrid_name_parts)
                                               - 1]) + os.sep).strip()

                # create dirs if they do not exist

                dir1 = user_dir + vgrid_name_without_last_fragment
                if not os.path.isdir(dir1):
                    os.makedirs(dir1)
            except Exception, exc:

                # out of range? should not be possible due to is_subvgrid check

                output_objects.append(
                    {'object_type': 'error_text', 'text':
                     ('Could not create needed dirs on %s server! %s'
                      % (configuration.short_title, exc))})
                logger.error('%s when looking for dir %s.' % (exc, dir1))
                status = returnvalues.SYSTEM_ERROR
                continue

        # create symlink from users home directory to vgrid file directory

        link_src = os.path.abspath(configuration.vgrid_files_home + os.sep
                                   + vgrid_name) + os.sep
        link_dst = user_dir + vgrid_name

        # create symlink to vgrid files

        if not make_symlink(link_src, link_dst, logger):
            output_objects.append({'object_type': 'error_text', 'text':
                                   'Could not create link to %s files!' %
                                   label
                                   })
            logger.error('Could not create link to %s files! (%s -> %s)' %
                         (label, link_src, link_dst))
            status = returnvalues.SYSTEM_ERROR
            continue
        cert_id_added.append(cert_id)
Ejemplo n.º 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)
    client_dir = client_id_dir(client_id)
    defaults = signature()[1]
    title_entry = find_entry(output_objects, 'title')
    label = "%s" % configuration.site_vgrid_label
    title_entry['text'] = "Update %s Components" % label
    output_objects.append({
        'object_type': 'header',
        'text': 'Update %s Components' % 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]

    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)

    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
        })

        form_method = 'post'
        csrf_limit = get_csrf_limit(configuration)
        fill_helpers = {
            'vgrid_label': label,
            'vgrid_name': vgrid_name,
            'form_method': form_method,
            'csrf_field': csrf_field,
            'csrf_limit': csrf_limit
        }
        target_op = 'sendrequestaction'
        csrf_token = make_csrf_token(configuration, form_method, target_op,
                                     client_id, csrf_limit)
        fill_helpers.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="hidden" name="request_type" value="vgridowner"/>
        <input type="text" size=50 name="request_text" />
        <input type="hidden" name="output_format" value="html" />
        <input type="submit" value="Request %(vgrid_label)s access" />
        </form>
    ''' % fill_helpers
        })

        return (output_objects, returnvalues.SYSTEM_ERROR)

    # 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

    base_dir = os.path.abspath(
        os.path.join(configuration.vgrid_home, vgrid_name)) + os.sep
    public_base_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_public_base,
                        vgrid_name)) + os.sep
    public_scm_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_public_base,
                        vgrid_name, '.vgridscm')) + os.sep
    public_tracker_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_public_base,
                        vgrid_name, '.vgridtracker')) + os.sep
    private_base_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name)) + os.sep
    private_scm_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name, '.vgridscm')) + os.sep
    private_tracker_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name, '.vgridtracker')) + os.sep
    private_forum_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name, '.vgridforum')) + os.sep
    vgrid_files_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_files_home,
                        vgrid_name)) + os.sep
    vgrid_scm_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_files_home,
                        vgrid_name, '.vgridscm')) + os.sep
    vgrid_tracker_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_files_home,
                        vgrid_name, '.vgridtracker')) + os.sep

    output_objects.append({'object_type': 'text', 'text':
                           'Updating %s %s components ...' % \
                           (label, vgrid_name)})

    # Try to create all base directories used for vgrid files

    for path in (base_dir, public_base_dir, private_base_dir, vgrid_files_dir):
        try:
            os.mkdir(path)
        except Exception, exc:
            pass
Ejemplo n.º 7
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)
    client_dir = client_id_dir(client_id)
    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]

    output_objects.append({'object_type': 'header', 'text'
                          : "Update '%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 })

        js_name = 'reqvgridowner%s' % hexlify(vgrid_name)
        helper = html_post_helper(js_name, 'sendrequestaction.py',
                                  {'vgrid_name': vgrid_name,
                                   'request_type': 'vgridowner',
                                   'request_text': ''})
        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 (field below).",
                                  'request_text'),
                               'class': 'addadminlink',
                               'title': 'Request ownership of %s' % vgrid_name,
                               'text': 'Apply to become an owner'})

        return (output_objects, returnvalues.SYSTEM_ERROR)

    # 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

    base_dir = os.path.abspath(os.path.join(configuration.vgrid_home,
                               vgrid_name)) + os.sep
    public_base_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_public_base,
                        vgrid_name)) + os.sep
    public_scm_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_public_base,
                        vgrid_name, '.vgridscm')) + os.sep
    public_tracker_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_public_base,
                        vgrid_name, '.vgridtracker')) + os.sep
    private_base_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name)) + os.sep
    private_scm_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name, '.vgridscm')) + os.sep
    private_tracker_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name, '.vgridtracker')) + os.sep
    private_forum_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name, '.vgridforum')) + os.sep
    vgrid_files_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_files_home,
                        vgrid_name)) + os.sep
    vgrid_scm_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_files_home,
                        vgrid_name, '.vgridscm')) + os.sep
    vgrid_tracker_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_files_home,
                        vgrid_name, '.vgridtracker')) + os.sep

    output_objects.append({'object_type': 'text', 'text'
                           : 'Updating %s %s components ...' % \
                           (configuration.site_vgrid_label, vgrid_name)})
    
    # Try to create all base directories used for vgrid files

    for path in (base_dir, public_base_dir, private_base_dir, vgrid_files_dir):
        try:
            os.mkdir(path)
        except Exception, exc:
            pass
Ejemplo n.º 8
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)
Ejemplo n.º 9
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)
    client_dir = client_id_dir(client_id)
    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:
        WARNING_MSG = str(accepted)
        output_objects.append({'object_type': 'warning', 'text': WARNING_MSG})
        return (accepted, returnvalues.CLIENT_ERROR)

    # Convert accpeted values to string and filter out NON-set values

    accepted_joined_values = {
        key: ''.join(value)
        for (key, value) in accepted.iteritems() if len(value) > 0
    }

    action = accepted_joined_values['action']
    flags = accepted_joined_values['flags']
    path = accepted_joined_values['path']
    extension = accepted['extension'][-1].strip()

    logger.debug('%s from %s: %s' % (op_name, client_id, accepted))

    if not action in valid_actions:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Invalid action "%s" (supported: %s)' %
            (action, ', '.join(valid_actions))
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

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

    # 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

    base_dir = os.path.abspath(
        os.path.join(configuration.user_home, client_dir)) + os.sep
    abs_path = os.path.join(base_dir, path)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'IMAGEPREVIEW Management'
    output_objects.append({
        'object_type': 'header',
        'text': 'IMAGEPREVIEW Management'
    })
    status = returnvalues.ERROR

    vgrid_name = in_vgrid_share(configuration, abs_path)
    vgrid_owner = vgrid_is_owner(vgrid_name, client_id, configuration)

    status = returnvalues.OK
    if vgrid_name is None:
        status = returnvalues.ERROR
        ERROR_MSG = "No vgrid found for path: '%s'" % path
        output_objects.append({'object_type': 'error_text', 'text': ERROR_MSG})

    if status == returnvalues.OK:
        if action == 'list_settings':
            status = list_settings(configuration, abs_path, path,
                                   output_objects)
            logger.debug('list exit status: %s' % str(status))
        elif action == 'remove_setting':
            if vgrid_owner == False:
                status = returnvalues.ERROR
                ERROR_MSG = \
                    "Ownership of vgrid: '%s' required to change imagepreview settings" \
                    % vgrid_name
                output_objects.append({
                    'object_type': 'error_text',
                    'text': ERROR_MSG
                })
            else:
                status = remove_setting(configuration, abs_path, path,
                                        extension, output_objects)
            logger.debug('remove_setting exit status: %s' % str(status))
        elif action == 'get_setting':
            status = get_setting(configuration, abs_path, path, extension,
                                 output_objects)
            logger.debug('get_setting exit status: %s' % str(status))
        elif action == 'update_setting':
            if vgrid_owner == False:
                status = returnvalues.ERROR
                ERROR_MSG = \
                    "Ownership of vgrid: '%s' required to change imagepreview settings" \
                    % vgrid_name
                output_objects.append({
                    'object_type': 'error_text',
                    'text': ERROR_MSG
                })
            else:
                status = update_setting(
                    configuration,
                    base_dir,
                    abs_path,
                    path,
                    extension,
                    accepted_joined_values,
                    output_objects,
                )
                logger.debug('update_setting exit status: %s' % str(status))
        elif action == 'create_setting':

            if vgrid_owner == False:
                status = returnvalues.ERROR
                ERROR_MSG = \
                    "Ownership of vgrid: '%s' required to change imagepreview settings" \
                    % vgrid_name
                output_objects.append({
                    'object_type': 'error_text',
                    'text': ERROR_MSG
                })
            else:
                status = create_setting(
                    configuration,
                    client_id,
                    base_dir,
                    abs_path,
                    path,
                    extension,
                    accepted_joined_values,
                    output_objects,
                )
                status = returnvalues.OK
            logger.debug('create_setting exit status: %s' % str(status))
        elif action == 'reset_setting':
            if vgrid_owner == False:
                status = returnvalues.ERROR
                ERROR_MSG = \
                    "Ownership of vgrid: '%s' required to change imagepreview settings" \
                    % vgrid_name
                output_objects.append({
                    'object_type': 'error_text',
                    'text': ERROR_MSG
                })
            else:
                status = reset_settings(configuration, abs_path, path,
                                        output_objects, extension)
            logger.debug('reset exit status: %s' % str(status))
        elif action == 'get':

            status = get(configuration, base_dir, path, output_objects)
            logger.debug('get exit status: %s' % str(status))
        elif action == 'remove':
            if vgrid_owner == False:
                status = returnvalues.ERROR
                ERROR_MSG = \
                    "Ownership of vgrid: '%s' required to change imagepreview settings" \
                    % vgrid_name
                output_objects.append({
                    'object_type': 'error_text',
                    'text': ERROR_MSG
                })
            else:
                status = remove(configuration, base_dir, abs_path, path,
                                output_objects)
                logger.debug('remove exit status: %s' % str(status))
        elif action == 'clean':
            if vgrid_owner == False:
                status = returnvalues.ERROR
                ERROR_MSG = \
                    "Ownership of vgrid: '%s' required to change imagepreview settings" \
                    % vgrid_name
                output_objects.append({
                    'object_type': 'error_text',
                    'text': ERROR_MSG
                })
            else:
                status = clean(configuration, base_dir, abs_path, path,
                               output_objects)
                logger.debug('clean exit status: %s' % str(status))
        elif action == 'cleanrecursive':

            if vgrid_owner == False:
                status = returnvalues.ERROR
                ERROR_MSG = \
                    "Ownership of vgrid: '%s' required to change imagepreview settings" \
                    % vgrid_name
                output_objects.append({
                    'object_type': 'error_text',
                    'text': ERROR_MSG
                })
            else:
                status = clean(
                    configuration,
                    base_dir,
                    abs_path,
                    path,
                    output_objects,
                    recursive=True,
                )
                logger.debug('cleanrecursive exit status: %s' % str(status))
        elif action == 'refresh':

            if vgrid_owner == False:
                status = returnvalues.ERROR
                ERROR_MSG = \
                    "Ownership of vgrid: '%s' required to change imagepreview settings" \
                    % vgrid_name
                output_objects.append({
                    'object_type': 'error_text',
                    'text': ERROR_MSG
                })
            else:
                status = refresh(
                    configuration,
                    client_id,
                    base_dir,
                    abs_path,
                    path,
                    output_objects,
                )
                logger.debug('refresh exit status: %s' % str(status))
        else:
            ERROR_MSG = "action: '%s' _NOT_ implemented yet" \
                % str(action)
            output_objects.append({
                'object_type': 'error_text',
                'text': ERROR_MSG
            })

    logger.debug('output_objects: %s' % str(output_objects))
    logger.debug('status: %s' % str(status))
    return (output_objects, status)
Ejemplo n.º 10
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 Member" % label
    output_objects.append({
        'object_type': 'header',
        'text': 'Remove %s Member' % 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]
    cert_id = accepted['cert_id'][-1]
    cert_dir = client_id_dir(cert_id)

    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 member 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 members
        (allow_status, allow_msg) = allow_members_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,
                                  'member', 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 a member

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

    # owner of subvgrid?

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

    # TODO: we DO allow ownership of sub vgrids with parent membership so we
    # should support the (cumbersome) relinking of vgrid shares here. Leave it
    # to user to do it manually for now with temporary removal of ownership

    for subvgrid in subvgrids:
        if vgrid_is_owner(subvgrid, cert_id, configuration, recursive=False):
            output_objects.append({
                'object_type': 'error_text',
                'text':
                """%(cert_id)s is already an owner of a sub-%(vgrid_label)s
('%(subvgrid)s'). While we DO support members being owners of
sub-%(vgrid_label)ss, we do not support removing parent %(vgrid_label)s members
at the moment. Please (temporarily) remove the person as owner of all
sub-%(vgrid_label)ss first and then try this operation again.""" % {
                    'cert_id': cert_id,
                    'subvgrid': subvgrid,
                    'vgrid_label': label
                }
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

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

    base_dir = os.path.abspath(
        os.path.join(configuration.vgrid_home, vgrid_name)) + os.sep

    # remove symlink from users home directory to vgrid directory

    # 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

    dst = user_dir + vgrid_name
    try:
        os.remove(dst)
    except Exception, exc:

        # ouch, not good. Email admin?

        pass
Ejemplo n.º 11
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'] = '%s send request' % configuration.short_title
    output_objects.append({
        'object_type': 'header',
        'text': '%s send request' % configuration.short_title
    })
    (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)

    target_id = client_id
    vgrid_name = accepted['vgrid_name'][-1].strip()
    visible_user_names = accepted['cert_id']
    visible_res_names = accepted['unique_resource_name']
    request_type = accepted['request_type'][-1].strip().lower()
    request_text = accepted['request_text'][-1].strip()
    protocols = [proto.strip() for proto in accepted['protocol']]
    use_any = False
    if any_protocol in protocols:
        use_any = True
        protocols = configuration.notify_protocols
    protocols = [proto.lower() for proto in protocols]

    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)

    valid_request_types = [
        'resourceowner', 'resourceaccept', 'resourcereject', 'vgridowner',
        'vgridmember', 'vgridresource', 'vgridaccept', 'vgridreject', 'plain'
    ]
    if not request_type in valid_request_types:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '%s is not a valid request_type (valid types: %s)!' %
            (request_type.lower(), valid_request_types)
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    if not protocols:
        output_objects.append({
            'object_type': 'error_text',
            'text': 'No protocol specified!'
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    user_map = get_user_map(configuration)
    reply_to = user_map[client_id][USERID]
    # Try to point replies to client_id email
    client_email = extract_field(reply_to, 'email')

    if request_type == "plain":
        if not visible_user_names:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No user ID specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

        user_id = visible_user_names[-1].strip()
        anon_map = anon_to_real_user_map(configuration)
        if anon_map.has_key(user_id):
            user_id = anon_map[user_id]
        if not user_map.has_key(user_id):
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No such user: %s' % user_id
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_name = user_id
        user_dict = user_map[user_id]
        vgrid_access = user_vgrid_access(configuration, client_id)
        vgrids_allow_email = user_dict[CONF].get('VGRIDS_ALLOW_EMAIL', [])
        vgrids_allow_im = user_dict[CONF].get('VGRIDS_ALLOW_IM', [])
        if any_vgrid in vgrids_allow_email:
            email_vgrids = vgrid_access
        else:
            email_vgrids = set(vgrids_allow_email).intersection(vgrid_access)
        if any_vgrid in vgrids_allow_im:
            im_vgrids = vgrid_access
        else:
            im_vgrids = set(vgrids_allow_im).intersection(vgrid_access)
        if use_any:
            # Do not try disabled protocols if ANY was requested
            if not email_vgrids:
                protocols = [
                    proto for proto in protocols
                    if proto not in email_keyword_list
                ]
            if not im_vgrids:
                protocols = [
                    proto for proto in protocols if proto in email_keyword_list
                ]
        if not email_vgrids and [
                proto for proto in protocols if proto in email_keyword_list
        ]:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'You are not allowed to send emails to %s!' % user_id
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not im_vgrids and [
                proto for proto in protocols if proto not in email_keyword_list
        ]:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'You are not allowed to send instant messages to %s!' % user_id
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        for proto in protocols:
            if not user_dict[CONF].get(proto.upper(), False):
                if use_any:
                    # Remove missing protocols if ANY protocol was requested
                    protocols = [i for i in protocols if i != proto]
                else:
                    output_objects.append({
                        'object_type':
                        'error_text',
                        'text':
                        'User %s does not accept %s messages!' %
                        (user_id, proto)
                    })
                    return (output_objects, returnvalues.CLIENT_ERROR)
        if not protocols:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'User %s does not accept requested protocol(s) messages!' %
                user_id
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_list = [user_id]
    elif request_type in ["vgridaccept", "vgridreject"]:
        # Always allow accept messages but only between owners/members
        if not visible_user_names and not visible_res_names:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No user or resource ID specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not vgrid_name:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No vgrid_name specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if vgrid_name.upper() == default_vgrid.upper():
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'No requests for %s are allowed!' % default_vgrid
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not vgrid_is_owner(vgrid_name, client_id, configuration):
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'You are not an owner of %s or a parent %s!' %
                (vgrid_name, label)
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        # NOTE: we support exactly one vgrid but multiple users/resources here
        if visible_user_names:
            logger.info("setting user recipients: %s" % visible_user_names)
            target_list = [user_id.strip() for user_id in visible_user_names]
        elif visible_res_names:
            # vgrid resource accept - lookup and notify resource owners
            logger.info("setting res owner recipients: %s" % visible_res_names)
            target_list = []
            for unique_resource_name in visible_res_names:
                logger.info("loading res owners for %s" % unique_resource_name)
                (load_status,
                 res_owners) = resource_owners(configuration,
                                               unique_resource_name)
                if not load_status:
                    output_objects.append({
                        'object_type':
                        'error_text',
                        'text':
                        'Could not lookup owners of %s!' % unique_resource_name
                    })
                    continue
                logger.info("adding res owners to recipients: %s" % res_owners)
                target_list += [user_id for user_id in res_owners]

        target_id = '%s %s owners' % (vgrid_name, label)
        target_name = vgrid_name
    elif request_type in ["resourceaccept", "resourcereject"]:
        # Always allow accept messages between actual resource owners
        if not visible_user_names:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No user ID specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not visible_res_names:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No resource ID specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        # NOTE: we support exactly one resource but multiple users here
        unique_resource_name = visible_res_names[-1].strip()
        target_name = unique_resource_name
        res_map = get_resource_map(configuration)
        if not res_map.has_key(unique_resource_name):
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'No such resource: %s' % unique_resource_name
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        owners_list = res_map[unique_resource_name][OWNERS]
        if not client_id in owners_list:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'You are not an owner of %s!' % unique_resource_name
            })
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Invalid resource %s message!' % request_type
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_id = '%s resource owners' % unique_resource_name
        target_name = unique_resource_name
        target_list = [user_id.strip() for user_id in visible_user_names]
    elif request_type == "resourceowner":
        if not visible_res_names:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No resource ID specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        # NOTE: we support exactly one resource but multiple users here
        unique_resource_name = visible_res_names[-1].strip()
        anon_map = anon_to_real_res_map(configuration.resource_home)
        if anon_map.has_key(unique_resource_name):
            unique_resource_name = anon_map[unique_resource_name]
        target_name = unique_resource_name
        res_map = get_resource_map(configuration)
        if not res_map.has_key(unique_resource_name):
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'No such resource: %s' % unique_resource_name
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_list = res_map[unique_resource_name][OWNERS]
        if client_id in target_list:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'You are already an owner of %s!' % unique_resource_name
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

        request_dir = os.path.join(configuration.resource_home,
                                   unique_resource_name)
        access_request = {
            'request_type': request_type,
            'entity': client_id,
            'target': unique_resource_name,
            'request_text': request_text
        }
        if not save_access_request(configuration, request_dir, access_request):
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Could not save request - owners may still manually add you'
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)
    elif request_type in ["vgridmember", "vgridowner", "vgridresource"]:
        if not vgrid_name:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No vgrid_name specified!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

        # default vgrid is read-only

        if vgrid_name.upper() == default_vgrid.upper():
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'No requests for %s are not allowed!' % default_vgrid
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

        # stop owner or member request if already an owner
        # and prevent repeated resource access requests

        if request_type == 'vgridresource':
            # NOTE: we support exactly one resource here
            unique_resource_name = visible_res_names[-1].strip()
            target_id = entity = unique_resource_name
            if vgrid_is_resource(vgrid_name, unique_resource_name,
                                 configuration):
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'You already have access to %s or a parent %s.' %
                    (vgrid_name, label)
                })
                return (output_objects, returnvalues.CLIENT_ERROR)
        else:
            target_id = entity = client_id
            if vgrid_is_owner(vgrid_name, client_id, configuration):
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'You are already an owner of %s or a parent %s!' %
                    (vgrid_name, label)
                })
                return (output_objects, returnvalues.CLIENT_ERROR)

        # only ownership requests are allowed for existing members

        if request_type == 'vgridmember':
            if vgrid_is_member(vgrid_name, client_id, configuration):
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'You are already a member of %s or a parent %s.' %
                    (vgrid_name, label)
                })
                return (output_objects, returnvalues.CLIENT_ERROR)

        # Find all VGrid owners configured to receive notifications

        target_name = vgrid_name
        (settings_status, settings_dict) = vgrid_settings(vgrid_name,
                                                          configuration,
                                                          recursive=True,
                                                          as_dict=True)
        if not settings_status:
            settings_dict = {}
        request_recipients = settings_dict.get('request_recipients',
                                               default_vgrid_settings_limit)
        # We load and use direct owners first if any - otherwise inherited
        owners_list = []
        for inherited in (False, True):
            (owners_status, owners_list) = vgrid_owners(vgrid_name,
                                                        configuration,
                                                        recursive=inherited)
            if not owners_status:
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'Failed to lookup owners for %s %s - sure it exists?' %
                    (vgrid_name, label)
                })
                return (output_objects, returnvalues.CLIENT_ERROR)
            elif owners_list:
                break
        if not owners_list:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Failed to lookup owners for %s %s - sure it exists?' %
                (vgrid_name, label)
            })
            return (output_objects, returnvalues.CLIENT_ERROR)
        # Now we have direct or inherited owners to notify
        target_list = owners_list[:request_recipients]

        request_dir = os.path.join(configuration.vgrid_home, vgrid_name)
        access_request = {
            'request_type': request_type,
            'entity': entity,
            'target': vgrid_name,
            'request_text': request_text
        }
        if not save_access_request(configuration, request_dir, access_request):
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Could not save request - owners may still manually add you'
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)

    else:
        output_objects.append({
            'object_type': 'error_text',
            'text': 'Invalid request type: %s' % request_type
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Now send request to all targets in turn
    # TODO: inform requestor if no owners have mail/IM set in their settings

    logger.debug("sending notification to recipients: %s" % target_list)

    for target in target_list:

        if not target:
            logger.warning("skipping empty notify target: %s" % target_list)
            continue

        # USER_CERT entry is destination

        notify = []
        for proto in protocols:
            notify.append('%s: SETTINGS' % proto)
        job_dict = {
            'NOTIFY': notify,
            'JOB_ID': 'NOJOBID',
            'USER_CERT': target,
            'EMAIL_SENDER': client_email
        }

        notifier = notify_user_thread(
            job_dict,
            [target_id, target_name, request_type, request_text, reply_to],
            'SENDREQUEST',
            logger,
            '',
            configuration,
        )

        # Try finishing delivery but do not block forever on one message
        notifier.join(30)
    output_objects.append({
        'object_type':
        'text',
        'text':
        'Sent %s message to %d people' % (request_type, len(target_list))
    })
    output_objects.append({
        'object_type':
        'text',
        'text':
        """Please make sure you have notifications
configured on your Setings page if you expect a reply to this message"""
    })

    return (output_objects, returnvalues.OK)
Ejemplo n.º 12
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)
    client_dir = client_id_dir(client_id)
    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)

    action = accepted['action'][-1]
    share_id = accepted['share_id'][-1]
    path = accepted['path'][-1]
    read_access = accepted['read_access'][-1].lower() in enabled_strings
    write_access = accepted['write_access'][-1].lower() in enabled_strings
    expire = accepted['expire'][-1]
    # Merge and split invite to make sure 'a@b, c@d' entries are handled
    invite_list = ','.join(accepted['invite']).split(',')
    invite_list = [i for i in invite_list if i]
    invite_msg = accepted['msg']

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Share Link'

    # jquery support for tablesorter and confirmation on delete/redo:
    # table initially sorted by 5, 4 reversed (active first and in growing age)

    table_spec = {'table_id': 'sharelinkstable', 'sort_order': '[[5,1],[4,1]]'}
    (add_import, add_init, add_ready) = man_base_js(configuration,
                                                    [table_spec],
                                                    {'width': 600})
    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)
    })

    header_entry = {'object_type': 'header', 'text': 'Manage share links'}
    output_objects.append(header_entry)

    if not configuration.site_enable_sharelinks:
        output_objects.append({
            'object_type':
            'text',
            'text':
            '''
Share links are disabled on this site.
Please contact the site admins %s if you think they should be enabled.
''' % configuration.admin_email
        })
        return (output_objects, returnvalues.OK)

    logger.info('sharelink %s from %s' % (action, client_id))
    logger.debug('sharelink from %s: %s' % (client_id, accepted))

    if not action in valid_actions:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Invalid action "%s" (supported: %s)' %
            (action, ', '.join(valid_actions))
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    if action in post_actions:
        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)

    (load_status, share_map) = load_share_links(configuration, client_id)
    if not load_status:
        share_map = {}

    form_method = 'post'
    csrf_limit = get_csrf_limit(configuration)
    target_op = 'sharelink'
    csrf_token = make_csrf_token(configuration, form_method, target_op,
                                 client_id, csrf_limit)
    if action in get_actions:
        if action == "show":
            # Table columns to skip
            skip_list = ['owner', 'single_file', 'expire']
            sharelinks = []
            for (saved_id, share_dict) in share_map.items():
                share_item = build_sharelinkitem_object(
                    configuration, share_dict)
                js_name = 'delete%s' % hexlify(saved_id)
                helper = html_post_helper(
                    js_name, '%s.py' % target_op, {
                        'share_id': saved_id,
                        'action': 'delete',
                        csrf_field: csrf_token
                    })
                output_objects.append({
                    'object_type': 'html_form',
                    'text': helper
                })
                share_item['delsharelink'] = {
                    'object_type':
                    'link',
                    'destination':
                    "javascript: confirmDialog(%s, '%s');" %
                    (js_name, 'Really remove %s?' % saved_id),
                    'class':
                    'removelink iconspace',
                    'title':
                    'Remove share link %s' % saved_id,
                    'text':
                    ''
                }
                sharelinks.append(share_item)

            # Display share links and form to add new ones

            output_objects.append({
                'object_type': 'sectionheader',
                'text': 'Share Links'
            })
            output_objects.append({
                'object_type': 'table_pager',
                'entry_name': 'share links',
                'default_entries': default_pager_entries
            })
            output_objects.append({
                'object_type': 'sharelinks',
                'sharelinks': sharelinks,
                'skip_list': skip_list
            })

            output_objects.append({
                'object_type': 'html_form',
                'text': '<br/>'
            })
            output_objects.append({
                'object_type': 'sectionheader',
                'text': 'Create Share Link'
            })
            submit_button = '''<span>
    <input type=submit value="Create share link" />
    </span>'''
            sharelink_html = create_share_link_form(configuration, client_id,
                                                    'html', submit_button,
                                                    csrf_token)
            output_objects.append({
                'object_type': 'html_form',
                'text': sharelink_html
            })
        elif action == "edit":
            header_entry['text'] = 'Edit Share Link'
            share_dict = share_map.get(share_id, {})
            if not share_dict:
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'existing share link is required for edit'
                })
                return (output_objects, returnvalues.CLIENT_ERROR)

            output_objects.append({
                'object_type':
                'html_form',
                'text':
                '''
<p>
Here you can send invitations for your share link %(share_id)s to one or more
comma-separated recipients.
</p>
                                   ''' % share_dict
            })
            sharelinks = []
            share_item = build_sharelinkitem_object(configuration, share_dict)
            saved_id = share_item['share_id']
            js_name = 'delete%s' % hexlify(saved_id)
            helper = html_post_helper(js_name, '%s.py' % target_op, {
                'share_id': saved_id,
                'action': 'delete',
                csrf_field: csrf_token
            })
            output_objects.append({'object_type': 'html_form', 'text': helper})
            # Hide link to self
            del share_item['editsharelink']
            share_item['delsharelink'] = {
                'object_type':
                'link',
                'destination':
                "javascript: confirmDialog(%s, '%s');" %
                (js_name, 'Really remove %s?' % saved_id),
                'class':
                'removelink iconspace',
                'title':
                'Remove share link %s' % saved_id,
                'text':
                ''
            }
            sharelinks.append(share_item)
            output_objects.append({
                'object_type': 'sharelinks',
                'sharelinks': sharelinks
            })
            submit_button = '''<span>
    <input type=submit value="Send invitation(s)" />
    </span>'''
            sharelink_html = invite_share_link_form(configuration, client_id,
                                                    share_dict, 'html',
                                                    submit_button, csrf_token)
            output_objects.append({
                'object_type': 'html_form',
                'text': sharelink_html
            })
            output_objects.append({
                'object_type': 'link',
                'destination': 'sharelink.py',
                'text': 'Return to share link overview'
            })

        return (output_objects, returnvalues.OK)
    elif action in post_actions:
        share_dict = share_map.get(share_id, {})
        if not share_dict and action != 'create':
            logger.warning('%s tried to %s missing or not owned link %s!' %
                           (client_id, action, share_id))
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                '%s requires existing share link' % action
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

        share_path = share_dict.get('path', path)

        # 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

        base_dir = os.path.abspath(
            os.path.join(configuration.user_home, client_dir)) + os.sep

        rel_share_path = share_path.lstrip(os.sep)
        # IMPORTANT: path must be expanded to abs for proper chrooting
        abs_path = os.path.abspath(os.path.join(base_dir, rel_share_path))
        relative_path = abs_path.replace(base_dir, '')
        real_path = os.path.realpath(abs_path)
        single_file = os.path.isfile(real_path)
        vgrid_name = in_vgrid_share(configuration, abs_path)

        if action == 'delete':
            header_entry['text'] = 'Delete Share Link'
            (save_status, _) = delete_share_link(share_id, client_id,
                                                 configuration, share_map)
            if save_status and vgrid_name:
                logger.debug("del vgrid sharelink pointer %s" % share_id)
                (del_status,
                 del_msg) = vgrid_remove_sharelinks(configuration, vgrid_name,
                                                    [share_id], 'share_id')
                if not del_status:
                    logger.error("del vgrid sharelink pointer %s failed: %s" %
                                 (share_id, del_msg))
                    return (False, share_map)
            desc = "delete"
        elif action == "update":
            header_entry['text'] = 'Update Share Link'
            # Try to point replies to client_id email
            client_email = extract_field(client_id, 'email')
            if invite_list:
                invites = share_dict.get('invites', []) + invite_list
                invites_uniq = list(set([i for i in invites if i]))
                invites_uniq.sort()
                share_dict['invites'] = invites_uniq
                auto_msg = invite_share_link_message(configuration, client_id,
                                                     share_dict, 'html')
                msg = '\n'.join(invite_msg)
                # Now send request to all targets in turn
                threads = []
                for target in invite_list:
                    job_dict = {
                        'NOTIFY': [target.strip()],
                        'JOB_ID': 'NOJOBID',
                        'USER_CERT': client_id,
                        'EMAIL_SENDER': client_email
                    }

                    logger.debug('invite %s to %s' % (target, share_id))
                    threads.append(
                        notify_user_thread(
                            job_dict,
                            [auto_msg, msg],
                            'INVITESHARE',
                            logger,
                            '',
                            configuration,
                        ))

                # Try finishing delivery but do not block forever on one message
                notify_done = [False for _ in threads]
                for _ in range(3):
                    for i in range(len(invite_list)):
                        if not notify_done[i]:
                            logger.debug('check done %s' % invite_list[i])
                            notify = threads[i]
                            notify.join(3)
                            notify_done[i] = not notify.isAlive()
                notify_sent, notify_failed = [], []
                for i in range(len(invite_list)):
                    if notify_done[i]:
                        notify_sent.append(invite_list[i])
                    else:
                        notify_failed.append(invite_list[i])
                logger.debug('notify sent %s, failed %s' %
                             (notify_sent, notify_failed))
                if notify_failed:
                    output_objects.append({
                        'object_type':
                        'html_form',
                        'text':
                        '''
<p>Failed to send invitation to %s</p>''' % ', '.join(notify_failed)
                    })
                if notify_sent:
                    output_objects.append({
                        'object_type':
                        'html_form',
                        'text':
                        '''<p>Invitation sent to %s</p>
<textarea class="fillwidth padspace" rows="%d" readonly="readonly">
%s
%s
</textarea>
                                            ''' %
                        (', '.join(notify_sent),
                         (auto_msg + msg).count('\n') + 3, auto_msg, msg)
                    })
            if expire:
                share_dict['expire'] = expire
            (save_status, _) = update_share_link(share_dict, client_id,
                                                 configuration, share_map)
            desc = "update"
        elif action == "create":
            header_entry['text'] = 'Create Share Link'
            if not read_access and not write_access:
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'No access set - please select read, write or both'
                })
                return (output_objects, returnvalues.CLIENT_ERROR)
            # NOTE: check path here as relative_path is empty for path='/'
            if not path:
                output_objects.append({
                    'object_type': 'error_text',
                    'text': 'No path provided!'
                })
                return (output_objects, returnvalues.CLIENT_ERROR)
            # We refuse sharing of entire home for security reasons
            elif not valid_user_path(
                    configuration, abs_path, base_dir, allow_equal=False):
                logger.warning('%s tried to %s restricted path %s ! (%s)' %
                               (client_id, action, abs_path, path))
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    '''Illegal path "%s":
you can only share your own data, and not your entire home direcory.''' % path
                })
                return (output_objects, returnvalues.CLIENT_ERROR)
            elif not os.path.exists(abs_path):
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'Provided path "%s" does not exist!' % path
                })
                return (output_objects, returnvalues.CLIENT_ERROR)
            # Refuse sharing of (mainly auth) dot dirs in root of user home
            elif real_path.startswith(os.path.join(base_dir, '.')):
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'Provided path "%s" cannot be shared for security reasons'
                    % path
                })
                return (output_objects, returnvalues.CLIENT_ERROR)
            elif single_file and write_access:
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    '''Individual files
cannot be shared with write access - please share a directory with the file in
it or only share with read access.
                     '''
                })
                return (output_objects, returnvalues.CLIENT_ERROR)

            # We check if abs_path is in vgrid share, but do not worry about
            # private_base or public_base since they are only available to
            # owners, who can always share anyway.

            if vgrid_name is not None and \
                    not vgrid_is_owner(vgrid_name, client_id, configuration):
                # share is inside vgrid share so we must check that user is
                # permitted to create sharelinks there.
                (load_status, settings_dict) = vgrid_settings(vgrid_name,
                                                              configuration,
                                                              recursive=True,
                                                              as_dict=True)
                if not load_status:
                    # Probably owners just never saved settings, use defaults
                    settings_dict = {'vgrid_name': vgrid_name}
                allowed = settings_dict.get('create_sharelink', keyword_owners)
                if allowed != keyword_members:
                    output_objects.append({
                        'object_type': 'error_text',
                        'text': '''The settings
for the %(vgrid_name)s %(vgrid_label)s do not permit you to re-share
%(vgrid_label)s shared folders. Please contact the %(vgrid_name)s owners if you
think you should be allowed to do that.
''' % {
                            'vgrid_name': vgrid_name,
                            'vgrid_label': configuration.site_vgrid_label
                        }
                    })
                    return (output_objects, returnvalues.CLIENT_ERROR)

            access_list = []
            if read_access:
                access_list.append('read')
            if write_access:
                access_list.append('write')

            share_mode = '-'.join((access_list + ['only'])[:2])

            # TODO: more validity checks here

            if share_dict:
                desc = "update"
            else:
                desc = "create"

            # IMPORTANT: always use expanded path
            share_dict.update({
                'path': relative_path,
                'access': access_list,
                'expire': expire,
                'invites': invite_list,
                'single_file': single_file
            })
            attempts = 1
            generate_share_id = False
            if not share_id:
                attempts = 3
                generate_share_id = True
            for i in range(attempts):
                if generate_share_id:
                    share_id = generate_sharelink_id(configuration, share_mode)
                share_dict['share_id'] = share_id
                (save_status,
                 save_msg) = create_share_link(share_dict, client_id,
                                               configuration, share_map)
                if save_status:
                    logger.info('created sharelink: %s' % share_dict)
                    break
                else:
                    # ID Collision?
                    logger.warning('could not create sharelink: %s' % save_msg)
            if save_status and vgrid_name:
                logger.debug("add vgrid sharelink pointer %s" % share_id)
                (add_status,
                 add_msg) = vgrid_add_sharelinks(configuration, vgrid_name,
                                                 [share_dict])
                if not add_status:
                    logger.error(
                        "save vgrid sharelink pointer %s failed: %s " %
                        (share_id, add_msg))
                    return (False, share_map)
        else:
            output_objects.append({
                'object_type': 'error_text',
                'text': 'No such action %s' % action
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

        if not save_status:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Error in %s share link %s: ' % (desc, share_id) +
                'save updated share links failed!'
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

        output_objects.append({
            'object_type':
            'text',
            'text':
            '%sd share link %s on %s .' %
            (desc.title(), share_id, relative_path)
        })
        if action in ['create', 'update']:
            sharelinks = []
            share_item = build_sharelinkitem_object(configuration, share_dict)
            saved_id = share_item['share_id']
            js_name = 'delete%s' % hexlify(saved_id)
            helper = html_post_helper(js_name, '%s.py' % target_op, {
                'share_id': saved_id,
                'action': 'delete',
                csrf_field: csrf_token
            })
            output_objects.append({'object_type': 'html_form', 'text': helper})
            share_item['delsharelink'] = {
                'object_type':
                'link',
                'destination':
                "javascript: confirmDialog(%s, '%s');" %
                (js_name, 'Really remove %s?' % saved_id),
                'class':
                'removelink iconspace',
                'title':
                'Remove share link %s' % saved_id,
                'text':
                ''
            }
            sharelinks.append(share_item)
            output_objects.append({
                'object_type': 'sharelinks',
                'sharelinks': sharelinks
            })
            if action == 'create':
                # NOTE: Leave editsharelink here for use in fileman overlay
                #del share_item['editsharelink']
                output_objects.append({
                    'object_type': 'html_form',
                    'text': '<br />'
                })
                submit_button = '''<span>
            <input type=submit value="Send invitation(s)" />
            </span>'''
                invite_html = invite_share_link_form(configuration, client_id,
                                                     share_dict, 'html',
                                                     submit_button, csrf_token)
                output_objects.append({
                    'object_type': 'html_form',
                    'text': invite_html
                })
    else:
        output_objects.append({
            'object_type': 'error_text',
            'text': 'Invalid share link action: %s' % action
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    output_objects.append({'object_type': 'html_form', 'text': '<br />'})
    output_objects.append({
        'object_type': 'link',
        'destination': 'sharelink.py',
        'text': 'Return to share link overview'
    })

    return (output_objects, returnvalues.OK)
Ejemplo n.º 13
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)
    client_dir = client_id_dir(client_id)
    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].strip()

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

    # No owner check here so we need to specifically check for illegal
    # directory access

    reserved_names = (default_vgrid, any_vgrid, all_vgrids)
    if vgrid_name in reserved_names or \
           not valid_dir_input(configuration.vgrid_home, vgrid_name):
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'Illegal vgrid_name: %s' % vgrid_name})
        logger.warning("""createvgrid possible illegal directory access
attempt by '%s': vgrid_name '%s'""" % (client_id, vgrid_name))
        return (output_objects, returnvalues.CLIENT_ERROR)

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

    # 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

    base_dir = os.path.abspath(os.path.join(configuration.vgrid_home,
                               vgrid_name)) + os.sep
    public_base_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_public_base,
                        vgrid_name)) + os.sep
    public_scm_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_public_base,
                        vgrid_name, '.vgridscm')) + os.sep
    public_tracker_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_public_base,
                        vgrid_name, '.vgridtracker')) + os.sep
    private_base_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name)) + os.sep
    private_scm_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name, '.vgridscm')) + os.sep
    private_tracker_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name, '.vgridtracker')) + os.sep
    private_forum_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_private_base,
                        vgrid_name, '.vgridforum')) + os.sep
    vgrid_files_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_files_home,
                        vgrid_name)) + os.sep
    vgrid_scm_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_files_home,
                        vgrid_name, '.vgridscm')) + os.sep
    vgrid_tracker_dir = \
        os.path.abspath(os.path.join(configuration.vgrid_files_home,
                        vgrid_name, '.vgridtracker')) + os.sep

    # does vgrid exist?

    if os.path.isdir(base_dir):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : '%s %s cannot be created because it already exists!'
             % (configuration.site_vgrid_label, vgrid_name)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # verify that client is owner of imada or imada/topology if trying to
    # create imada/topology/test

    vgrid_name_list = vgrid_name.split('/')
    vgrid_name_list_length = len(vgrid_name_list)
    if vgrid_name_list_length <= 0:
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'vgrid_name not specified?'})
        return (output_objects, returnvalues.SYSTEM_ERROR)
    elif vgrid_name_list_length == 1:

        # anyone can create base vgrid

        new_base_vgrid = True
    else:
        new_base_vgrid = False
        vgrid_name_without_last_fragment = \
            '/'.join(vgrid_name_list[0:vgrid_name_list_length - 1])
        parent_base = os.path.dirname(base_dir.rstrip(os.sep))
        if not os.path.isdir(parent_base):
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : 'Parent %s %s does not exist!' % \
                 (configuration.site_vgrid_label,
                  vgrid_name_without_last_fragment)
                 })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not vgrid_is_owner(vgrid_name_without_last_fragment,
                              client_id, configuration):
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : 'You must own a parent %s to create a sub vgrid' % \
                 configuration.site_vgrid_label
                 })
            return (output_objects, returnvalues.CLIENT_ERROR)

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

    try_again_string = \
        """%s cannot be created, a file or directory exists with the same
name, please try again with a new name!""" % configuration.site_vgrid_label
    if os.path.exists(public_base_dir):
        output_objects.append({'object_type': 'error_text', 'text'
                              : try_again_string})
        return (output_objects, returnvalues.CLIENT_ERROR)

    if os.path.exists(private_base_dir):
        output_objects.append({'object_type': 'error_text', 'text'
                              : try_again_string})
        return (output_objects, returnvalues.CLIENT_ERROR)

    if os.path.exists(vgrid_files_dir):
        output_objects.append({'object_type': 'error_text', 'text'
                              : try_again_string})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # create directory to store vgrid files

    try:
        os.mkdir(base_dir)
    except Exception, exc:
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : """Could not create %(_label)s directory, remember to create
parent %(_label)s before creating a sub-%(_label)s.""" % \
             {'_label': configuration.site_vgrid_label}
             })
        return (output_objects, returnvalues.CLIENT_ERROR)
Ejemplo n.º 14
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)
Ejemplo n.º 15
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)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = '%s send request' % \
                            configuration.short_title
    output_objects.append({'object_type': 'header', 'text'
                          : '%s send request' % \
                            configuration.short_title})

    target_id = client_id
    vgrid_name = accepted['vgrid_name'][-1].strip()
    visible_user_name = accepted['cert_id'][-1].strip()
    visible_res_name = accepted['unique_resource_name'][-1].strip()
    request_type = accepted['request_type'][-1].strip().lower()
    request_text = accepted['request_text'][-1].strip()
    protocols = [proto.strip() for proto in accepted['protocol']]
    use_any = False
    if any_protocol in protocols:
        use_any = True
        protocols = configuration.notify_protocols
    protocols = [proto.lower() for proto in protocols]

    valid_request_types = ['resourceowner', 'resourceaccept', 'vgridowner',
                           'vgridmember','vgridresource', 'vgridaccept',
                           'plain']
    if not request_type in valid_request_types:
        output_objects.append({
            'object_type': 'error_text', 'text'
            : '%s is not a valid request_type (valid types: %s)!'
            % (request_type.lower(),
               valid_request_types)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    if not protocols:
        output_objects.append({
            'object_type': 'error_text', 'text':
            'No protocol specified!'})
        return (output_objects, returnvalues.CLIENT_ERROR)

    user_map = get_user_map(configuration)
    reply_to = user_map[client_id][USERID]

    if request_type == "plain":
        if not visible_user_name:
            output_objects.append({
                'object_type': 'error_text', 'text':
                'No user ID specified!'})
            return (output_objects, returnvalues.CLIENT_ERROR)

        user_id = visible_user_name
        anon_map = anon_to_real_user_map(configuration.user_home)
        if anon_map.has_key(visible_user_name):
            user_id = anon_map[visible_user_name]
        if not user_map.has_key(user_id):
            output_objects.append({'object_type': 'error_text',
                                   'text': 'No such user: %s' % \
                                   visible_user_name
                                   })
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_name = user_id
        user_dict = user_map[user_id]
        allow_vgrids = user_allowed_vgrids(configuration, client_id)
        vgrids_allow_email = user_dict[CONF].get('VGRIDS_ALLOW_EMAIL', [])
        vgrids_allow_im = user_dict[CONF].get('VGRIDS_ALLOW_IM', [])
        if any_vgrid in vgrids_allow_email:
            email_vgrids = allow_vgrids
        else:
            email_vgrids = set(vgrids_allow_email).intersection(allow_vgrids)
        if any_vgrid in vgrids_allow_im:
            im_vgrids = allow_vgrids
        else:
            im_vgrids = set(vgrids_allow_im).intersection(allow_vgrids)
        if use_any:
            # Do not try disabled protocols if ANY was requested
            if not email_vgrids:
                protocols = [proto for proto in protocols \
                             if proto not in email_keyword_list]
            if not im_vgrids:
                protocols = [proto for proto in protocols \
                             if proto in email_keyword_list]
        if not email_vgrids and [proto for proto in protocols \
                                 if proto in email_keyword_list]:
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'You are not allowed to send emails to %s!' % \
                visible_user_name
                })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not im_vgrids and [proto for proto in protocols \
                              if proto not in email_keyword_list]:
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'You are not allowed to send instant messages to %s!' % \
                visible_user_name
                })
            return (output_objects, returnvalues.CLIENT_ERROR)
        for proto in protocols:
            if not user_dict[CONF].get(proto.upper(), False):
                if use_any:
                    # Remove missing protocols if ANY protocol was requested
                    protocols = [i for i in protocols if i != proto]
                else:
                    output_objects.append({
                        'object_type': 'error_text', 'text'
                        : 'User %s does not accept %s messages!' % \
                        (visible_user_name, proto)
                        })
                    return (output_objects, returnvalues.CLIENT_ERROR)
        if not protocols:
            output_objects.append({
                'object_type': 'error_text', 'text':
                'User %s does not accept requested protocol(s) messages!' % \
                visible_user_name})
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_list = [user_id]
    elif request_type == "vgridaccept":
        # Always allow accept messages but only between vgrid members/owners
        user_id = visible_user_name
        if not vgrid_name:
            output_objects.append({
                'object_type': 'error_text', 'text': 'No vgrid_name specified!'})
            return (output_objects, returnvalues.CLIENT_ERROR)
        if vgrid_name.upper() == default_vgrid.upper():
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'No requests for %s are not allowed!' % \
                default_vgrid
                })
            return (output_objects, returnvalues.CLIENT_ERROR)
        if not vgrid_is_owner(vgrid_name, client_id, configuration):
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'You are not an owner of %s or a parent %s!' % \
                (vgrid_name, configuration.site_vgrid_label)})
            return (output_objects, returnvalues.CLIENT_ERROR)
        allow_vgrids = user_allowed_vgrids(configuration, client_id)
        if not vgrid_name in allow_vgrids:
            output_objects.append({
                'object_type': 'error_text', 'text':
                'Invalid %s message! (%s sv %s)' % (request_type, user_id,
                                                    allow_vgrids)})
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_id = '%s %s owners' % (vgrid_name, configuration.site_vgrid_label)
        target_name = vgrid_name
        target_list = [user_id]
    elif request_type == "resourceaccept":
        # Always allow accept messages between actual resource owners
        user_id = visible_user_name
        if not visible_res_name:
            output_objects.append({
                'object_type': 'error_text', 'text':
                'No resource ID specified!'})
            return (output_objects, returnvalues.CLIENT_ERROR)
        unique_resource_name = visible_res_name
        target_name = unique_resource_name
        res_map = get_resource_map(configuration)
        if not res_map.has_key(unique_resource_name):
            output_objects.append({'object_type': 'error_text',
                                   'text': 'No such resource: %s' % \
                                   unique_resource_name
                                   })
            return (output_objects, returnvalues.CLIENT_ERROR)
        owners_list = res_map[unique_resource_name][OWNERS]
        if not client_id in owners_list or not user_id in owners_list:
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'Invalid resource owner accept message!'})
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_id = '%s resource owners' % unique_resource_name
        target_name = unique_resource_name
        target_list = [user_id]
    elif request_type == "resourceowner":
        if not visible_res_name:
            output_objects.append({
                'object_type': 'error_text', 'text':
                'No resource ID specified!'})
            return (output_objects, returnvalues.CLIENT_ERROR)
        
        unique_resource_name = visible_res_name
        anon_map = anon_to_real_res_map(configuration.resource_home)
        if anon_map.has_key(visible_res_name):
            unique_resource_name = anon_map[visible_res_name]
        target_name = unique_resource_name
        res_map = get_resource_map(configuration)
        if not res_map.has_key(unique_resource_name):
            output_objects.append({'object_type': 'error_text',
                                   'text': 'No such resource: %s' % \
                                   visible_res_name
                                   })
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_list = res_map[unique_resource_name][OWNERS]
        if client_id in target_list:
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'You are already an owner of %s!' % unique_resource_name
                })
            return (output_objects, returnvalues.CLIENT_ERROR)
    elif request_type in ["vgridmember", "vgridowner", "vgridresource"]:
        unique_resource_name = visible_res_name
        if not vgrid_name:
            output_objects.append({
                'object_type': 'error_text', 'text': 'No vgrid_name specified!'})
            return (output_objects, returnvalues.CLIENT_ERROR)

        # default vgrid is read-only
        
        if vgrid_name.upper() == default_vgrid.upper():
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'No requests for %s are not allowed!' % \
                default_vgrid
                })
            return (output_objects, returnvalues.CLIENT_ERROR)

        # stop owner or member request if already an owner

        if request_type != 'vgridresource':
            if vgrid_is_owner(vgrid_name, client_id, configuration):
                output_objects.append({
                    'object_type': 'error_text', 'text'
                    : 'You are already an owner of %s or a parent %s!' % \
                    (vgrid_name, configuration.site_vgrid_label)})
                return (output_objects, returnvalues.CLIENT_ERROR)

        # only ownership requests are allowed for existing members

        if request_type == 'vgridmember':
            if vgrid_is_member(vgrid_name, client_id, configuration):
                output_objects.append({
                    'object_type': 'error_text', 'text'
                    : 'You are already a member of %s or a parent %s.' % \
                    (vgrid_name, configuration.site_vgrid_label)})
                return (output_objects, returnvalues.CLIENT_ERROR)

        # set target to resource and prevent repeated resource access requests

        if request_type == 'vgridresource':
            target_id = unique_resource_name
            if vgrid_is_resource(vgrid_name, unique_resource_name,
                                 configuration):
                output_objects.append({
                    'object_type': 'error_text', 'text'
                    : 'You already have access to %s or a parent %s.' % \
                    (vgrid_name, configuration.site_vgrid_label)})
                return (output_objects, returnvalues.CLIENT_ERROR)

        # Find all VGrid owners

        target_name = vgrid_name
        (status, target_list) = vgrid_list(vgrid_name, 'owners', configuration)
        if not status:
            output_objects.append({
                'object_type': 'error_text', 'text'
                : 'Could not load list of current owners for %s %s!'
                % (vgrid_name, configuration.site_vgrid_label)})
            return (output_objects, returnvalues.CLIENT_ERROR)

    else:
        output_objects.append({
            'object_type': 'error_text', 'text': 'Invalid request type: %s' % \
            request_type})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Now send request to all targets in turn
    # TODO: inform requestor if no owners have mail/IM set in their settings
    
    for target in target_list:
        # USER_CERT entry is destination

        notify = []
        for proto in protocols:
            notify.append('%s: SETTINGS' % proto)
        job_dict = {'NOTIFY': notify, 'JOB_ID': 'NOJOBID', 'USER_CERT': target}

        notifier = notify_user_thread(
            job_dict,
            [target_id, target_name, request_type, request_text, reply_to],
            'SENDREQUEST',
            logger,
            '',
            configuration,
            )

        # Try finishing delivery but do not block forever on one message
        notifier.join(30)
    output_objects.append({'object_type': 'text', 'text':
                           'Sent %s message to %d people' % \
                           (request_type, len(target_list))})
    output_objects.append({'object_type': 'text', 'text':
                           """Please make sure you have notifications
configured on your Setings page if you expect a reply to this message"""})
    
    return (output_objects, returnvalues.OK)
Ejemplo n.º 16
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'
                          : 'Remove %s Member' % 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]
    cert_id = accepted['cert_id'][-1]
    cert_dir = client_id_dir(cert_id)

    # 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,
                                  'member', 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 a member

    if not vgrid_is_member(vgrid_name, cert_id, configuration):
        output_objects.append({'object_type': 'error_text', 'text'
                              : '%s is not a member of %s or a parent %s.'
                               % (cert_id, vgrid_name,
                                  configuration.site_vgrid_label)})
        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)

    # TODO: we DO allow ownership of sub vgrids with parent membership so we
    # should support the (cumbersome) relinking of vgrid shares here. Leave it
    # to user to do it manually for now with temporary removal of ownership

    for subvgrid in subvgrids:
        if vgrid_is_owner(subvgrid, cert_id, configuration, recursive=False):
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : """%(cert_id)s is already an owner of a sub-%(_label)s
('%(subvgrid)s'). While we DO support members being owners of sub-%(_label)ss,
we do not support removing parent %(_label)s members at the moment. Please
(temporarily) remove the person as owner of all sub %(_label)ss first and then
try this operation again.""" % {'cert_id': cert_id, 'subvgrid': subvgrid,
                                '_label': configuration.site_vgrid_label}})
            return (output_objects, returnvalues.CLIENT_ERROR)

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

    base_dir = os.path.abspath(os.path.join(configuration.vgrid_home,
                               vgrid_name)) + os.sep

    # remove symlink from users home directory to vgrid directory

    # 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

    dst = user_dir + vgrid_name
    try:
        os.remove(dst)
    except Exception, exc:

        # ouch, not good. Email admin?

        pass
Ejemplo n.º 17
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'
                          : 'Remove %s Resource' % \
                           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]
    unique_resource_name = accepted['unique_resource_name'][-1].lower()

    # 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, ret_variables) = \
        init_vgrid_script_add_rem(vgrid_name, client_id,
                                  unique_resource_name, 'resource',
                                  configuration)
    if not ret_val:
        output_objects.append({'object_type': 'error_text', 'text'
                              : msg})
        return (output_objects, returnvalues.CLIENT_ERROR)
    elif msg:

        # In case of warnings, msg is non-empty while ret_val remains True

        output_objects.append({'object_type': 'warning', 'text': msg})

    if not vgrid_is_owner(vgrid_name, client_id, configuration):
        output_objects.append({'object_type': 'error_text', 'text'
                              : '''You must be an owner of the %s to
remove a resource!''' % configuration.site_vgrid_label
                              })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # don't remove if not a participant

    if not vgrid_is_resource(vgrid_name, unique_resource_name, configuration):
        output_objects.append({'object_type': 'error_text', 'text'
                              : '%s is not a resource in %s or a parent %s.'
                               % (unique_resource_name, vgrid_name,
                                  configuration.site_vgrid_label)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # remove

    (rm_status, rm_msg) = vgrid_remove_resources(configuration, vgrid_name,
                                                 [unique_resource_name])
    if not rm_status:
        output_objects.append({'object_type': 'error_text', 'text'
                              : rm_msg})
        output_objects.append({'object_type': 'error_text', 'text'
                              : '''%(res_name)s might be listed as a resource
of this %(_label)s because it is a resource of a parent %(_label)s. Removal
must be performed from the most significant %(_label)s possible.''' % \
                               {'res_name': unique_resource_name,
                                '_label': configuration.site_vgrid_label}})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    output_objects.append({'object_type': 'text', 'text'
                          : 'Resource %s successfully removed from %s %s!'
                           % (unique_resource_name, vgrid_name,
                              configuration.site_vgrid_label)})
    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)
Ejemplo n.º 18
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)

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

    # prepare support for confirm dialog and toggling the views (by css/jquery)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = "Administrate %s: %s" % \
                          (configuration.site_vgrid_label, vgrid_name)

    title_entry['style'] = themed_styles(configuration)
    title_entry['javascript'] = '''
<script type="text/javascript" src="/images/js/jquery.js"></script>
<script type="text/javascript" src="/images/js/jquery-ui.js"></script>
<script type="text/javascript" src="/images/js/jquery.confirm.js"></script>

<script type="text/javascript" >

    var toggleHidden = function(classname) {
        // classname supposed to have a leading dot 
        $(classname).toggleClass('hidden');
    }

$(document).ready(function() {

          // init confirmation dialog
          $( "#confirm_dialog" ).dialog(
              // see http://jqueryui.com/docs/dialog/ for options
              { autoOpen: false,
                modal: true, closeOnEscape: true,
                width: 500,
                buttons: {
                   "Cancel": function() { $( "#" + name ).dialog("close"); }
                }
              });
     }
);
</script>
'''

    output_objects.append({'object_type': 'html_form',
                           'text':'''
 <div id="confirm_dialog" title="Confirm" style="background:#fff;">
  <div id="confirm_text"><!-- filled by js --></div>
   <textarea cols="40" rows="4" id="confirm_input" style="display:none;"></textarea>
 </div>
'''                       })
    
    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 })
        js_name = 'reqvgridowner%s' % hexlify(vgrid_name)
        helper = html_post_helper(js_name, 'sendrequestaction.py',
                                  {'vgrid_name': vgrid_name,
                                   'request_type': 'vgridowner',
                                   'request_text': ''})
        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',
             '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']):
        output_objects.append({'object_type': 'sectionheader',
                               'text': "%ss" % item.title()
                               })
        if item == 'trigger':
            # Always run as rule creator to avoid users being able to act on
            # behalf of ANY other user using triggers (=exploit)
            extra_fields = [('path', None),
                            ('changes', [keyword_all] + valid_trigger_changes),
                            ('run_as', client_id),
                            ('action', [keyword_auto] + valid_trigger_actions),
                            ('arguments', None)]
        else:
            extra_fields = []

        (status, oobjs) = vgrid_add_remove_table(client_id, vgrid_name, item, 
                                                 scr, configuration,
                                                 extra_fields)
        if not 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',
                 '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',
                 'title': 'Toggle view',
                 'text': 'Show %ss' % item.title() })
            output_objects.append({'object_type': 'html_form', 
                                   'text': '</div>' })

    # Checking/fixing of missing components

    output_objects.append({'object_type': 'sectionheader',
                           'text': "Repair/Add Components"})
    output_objects.append({'object_type': 'html_form',
                           'text': '''
      <form method="post" action="updatevgrid.py">
          <input type="hidden" name="vgrid_name" value="%(vgrid)s" />
          <input type="submit" value="Repair components" />
      </form>
''' % {'vgrid': vgrid_name}})

    output_objects.append({'object_type': 'sectionheader',
                           'text': "Delete %s " % vgrid_name})
    output_objects.append({'object_type': 'html_form',
                           'text': '''
To delete <b>%(vgrid)s</b> remove all members and owners ending with yourself.
''' % {'vgrid': vgrid_name}})

    return (output_objects, returnvalues.OK)
Ejemplo n.º 19
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 Member' % 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)

    # 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,
                                  'member', 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 member

    if vgrid_is_member(vgrid_name, cert_id, configuration):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : '''%s is already a member of %s or a parent %s. Please remove
the person first and then try this operation again.''' % \
             (cert_id, vgrid_name, configuration.site_vgrid_label)
             })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # owner or member 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)

    # TODO: we DO allow ownership of sub vgrids with parent membership so we
    # should support the (cumbersome) relinking of vgrid shares here. Leave it
    # to user to do it manually for now with temporary removal of ownership

    for subvgrid in subvgrids:
        if vgrid_is_owner(subvgrid, cert_id, configuration, recursive=False):
            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : """%(cert_id)s is already an owner of a sub-%(_label)s
('%(subvgrid)s'). While we DO support members being owners of sub-%(_label)ss,
we do not support adding parent %(_label)s members at the moment. Please
(temporarily) remove the person as owner of all sub-%(_label)ss first and then
try this operation again.""" % {'cert_id': cert_id, 'subvgrid': subvgrid,
                                '_label': configuration.site_vgrid_label}})
            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)

    # getting here means cert_id is neither owner or member of any parent or
    # sub-vgrids.

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

    base_dir = os.path.abspath(os.path.join(configuration.vgrid_home,
                               vgrid_name)) + os.sep
    user_dir = os.path.abspath(os.path.join(configuration.user_home,
                               cert_dir)) + 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 member)

    if os.path.exists(user_dir + vgrid_name):
        output_objects.append(
            {'object_type': 'error_text', 'text'
             : '''Could not add member, a file or directory in the home
directory called %s exists! (%s)''' % (vgrid_name, user_dir + vgrid_name)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Add

    (add_status, add_msg) = vgrid_add_members(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

    if is_subvgrid:
        try:

            # vgrid_name = IMADA/STUD/BACH
            # vgrid_name_last_fragment = BACH

            vgrid_name_last_fragment = \
                vgrid_name_parts[len(vgrid_name_parts)
                                     - 1].strip()

            # vgrid_name_without_last_fragment = IMADA/STUD/

            vgrid_name_without_last_fragment = \
                ('/'.join(vgrid_name_parts[0:len(vgrid_name_parts)
                  - 1]) + os.sep).strip()

            # create dirs if they do not exist

            dir1 = user_dir + vgrid_name_without_last_fragment
            if not os.path.isdir(dir1):
                os.makedirs(dir1)
        except Exception, exc:

            # out of range? should not be possible due to is_subvgrid check

            output_objects.append(
                {'object_type': 'error_text', 'text'
                 : ('Could not create needed dirs on %s server! %s'
                    % (configuration.short_title, exc))})
            logger.error('%s when looking for dir %s.' % (exc, dir1))
            return (output_objects, returnvalues.SYSTEM_ERROR)
Ejemplo n.º 20
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)
    status = returnvalues.OK
    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)

    (stat, vgrid_list) = vgrid_list_vgrids(configuration)
    if not stat:
        output_objects.append({'object_type': 'error_text', 'text'
                              : 'Error getting list of %s.' % \
                               configuration.site_vgrid_label})

    # Check if user wants advanced VGrid component links

    settings = load_settings(client_id, configuration)        
    collaboration_links = settings.get('SITE_COLLABORATION_LINKS', 'default')
    if not collaboration_links in configuration.site_collaboration_links or \
           collaboration_links == 'default':
        active_vgrid_links = configuration.site_default_vgrid_links
    elif collaboration_links == 'advanced':
        active_vgrid_links = configuration.site_advanced_vgrid_links

    # Iterate through vgrids and print details for each

    member_list = {'object_type': 'vgrid_list', 'vgrids': [],
                   'components': active_vgrid_links}
    if 'monitor' in active_vgrid_links:
        vgrid_list = [all_vgrids] + vgrid_list
    else:
        vgrid_list.remove(default_vgrid)
    for vgrid_name in vgrid_list:
        vgrid_obj = {'object_type': 'vgrid', 'name': vgrid_name}

        if vgrid_name == default_vgrid:

            # Everybody is member and allowed to see statistics, Noone
            # can own it or leave it. Do not add any page links.

            vgrid_obj['privatemonitorlink'] = {'object_type': 'link',
                                               'destination': 'showvgridmonitor.py?vgrid_name=%s'\
                                               % vgrid_name,
                                               'class': 'monitorlink',
                                               'title': 'View %s monitor' % vgrid_name, 
                                               'text': 'View'}
            vgrid_obj['memberlink'] = {'object_type': 'link',
                                       'destination':'',
                                       'class': 'infolink',
                                       'title': 'Every user is member of the %s %s' \
                                       % (default_vgrid,
                                          configuration.site_vgrid_label),
                                       'text': ''}
            vgrid_obj['administratelink'] = {'object_type': 'link',
                                       'destination':'',
                                       'class': 'infolink',
                                       'title': 'Nobody owns the %s %s' \
                                       % (default_vgrid,
                                          configuration.site_vgrid_label),
                                       'text': ''}
            member_list['vgrids'].append(vgrid_obj)
            continue
        elif vgrid_name == all_vgrids:

            # Only show global monitor link for all_vgrids, Noone
            # can own it or leave it. Do not add any page links.

            vgrid_obj['privatemonitorlink'] = {'object_type': 'link',
                                               'destination': 'showvgridmonitor.py?vgrid_name=%s'\
                                               % vgrid_name,
                                               'class': 'monitorlink',
                                               'title': 'View global monitor', 
                                               'text': 'View'}
            vgrid_obj['memberlink'] = {'object_type': 'link',
                                       'destination':'',
                                       'class': 'infolink',
                                       'title': 'Not a real %s - only for global monitor' % \
                                       configuration.site_vgrid_label,
                                       'text': ''}
            vgrid_obj['administratelink'] = {'object_type': 'link',
                                       'destination':'',
                                       'class': 'infolink',
                                       'title': 'Not a real %s - only for global monitor' % \
                                             configuration.site_vgrid_label,
                                       'text': ''}
            member_list['vgrids'].append(vgrid_obj)
            continue

        # links for everyone: public pages and membership request

        vgrid_obj['publicscmlink'] = {'object_type': 'link',
                'destination': '%s/vgridpublicscm/%s'\
                                       % (configuration.migserver_http_url,
                                          vgrid_name),
                                       'class': 'scmlink public',
                                       'title': 'Open %s public SCM' % \
                                       vgrid_name,
                                       'text': 'Open'}
        vgrid_obj['publictrackerlink'] = {'object_type': 'link',
                'destination': '%s/vgridpublictracker/%s'\
                                       % (configuration.migserver_http_url,
                                          vgrid_name),
                                       'class': 'trackerlink public',
                                       'title': 'Open %s public tracker' % \
                                       vgrid_name,
                                       'text': 'Open'}
        vgrid_obj['enterpubliclink'] = {'object_type': 'link',
                                        'destination':
                                        '%s/vgrid/%s/path/index.html' % \
                                        (configuration.migserver_http_url,
                                         vgrid_name),
                                        'class': 'urllink member',
                                        'title': 'View public %s web page' % \
                                        vgrid_name,
                                        'text': 'View'}

        # link to become member: overwritten later for members

        js_name = 'reqvgridmember%s' % hexlify(vgrid_name)
        helper = html_post_helper(js_name, 'sendrequestaction.py',
                                  {'vgrid_name': vgrid_name,
                                   'request_type': 'vgridmember',
                                   'request_text': ''})
        output_objects.append({'object_type': 'html_form', 'text': helper})
        vgrid_obj['memberlink'] = \
                                {'object_type': 'link',
                                 'destination':
                                 "javascript: confirmDialog(%s, '%s', '%s');"\
                                 % (js_name, "Request membership of " + \
                                    vgrid_name + ":<br/>" + \
                                    "\nPlease write a message to the owners (field below).",
                                    'request_text'),
                                 'class': 'addlink',
                                 'title': 'Request membership of %s' % \
                                 vgrid_name,
                                 'text': ''}

        # link to become owner: overwritten later for owners

        js_name = 'reqvgridowner%s' % hexlify(vgrid_name)
        helper = html_post_helper(js_name, 'sendrequestaction.py',
                                  {'vgrid_name': vgrid_name,
                                   'request_type': 'vgridowner',
                                   'request_text': ''})
        output_objects.append({'object_type': 'html_form', 'text': helper})
        vgrid_obj['administratelink'] = \
                                      {'object_type': 'link',
                                       'destination':
                                       "javascript: confirmDialog(%s, '%s', '%s');"\
                                       % (js_name, "Request ownership of " + \
                                          vgrid_name + ":<br/>" + \
                                          "\nPlease write a message to the owners (field below).",
                                          'request_text'),
                                       'class': 'addadminlink',
                                       'title': 'Request ownership of %s' % \
                                       vgrid_name,
                                       'text': ''}

        # members/owners are allowed to view private pages and monitor

        if vgrid_is_owner_or_member(vgrid_name, client_id, configuration):
            vgrid_obj['enterprivatelink'] = {'object_type': 'link',
                                             'destination':
                                             '../vgrid/%s/path/index.html' % \
                                             vgrid_name,
                                             'class': 'urllink owner',
                                             'title':
                                             'View private %s web page' % \
                                             vgrid_name, 
                                             'text': 'View'}
            vgrid_obj['sharedfolderlink'] = {'object_type': 'link',
                                             'destination':
                                             'fileman.py?path=%s/' % vgrid_name,
                                             'class': 'sharedfolderlink',
                                             'title': 'Open shared %s folder' \
                                             % vgrid_name, 
                                             'text': 'Open'}
            vgrid_obj['memberscmlink'] = {'object_type': 'link',
                                          'destination': '/vgridscm/%s' % \
                                          vgrid_name,
                                          'class': 'scmlink member',
                                          'title': 'View %s members scm' % \
                                          vgrid_name,
                                          'text': 'View'}
            vgrid_obj['membertrackerlink'] = {'object_type': 'link',
                                          'destination': '/vgridtracker/%s' % \
                                          vgrid_name,
                                          'class': 'trackerlink member',
                                          'title': 'View %s members tracker' % \
                                          vgrid_name,
                                          'text': 'View'}
            vgrid_obj['privateforumlink'] = {'object_type': 'link',
                                             'destination':
                                             'vgridforum.py?vgrid_name=%s' % \
                                             vgrid_name,
                                             'class': 'forumlink',
                                             'title': 'Open %s private forum' \
                                             % vgrid_name, 
                                               'text': 'Open'}
            vgrid_obj['privateworkflowslink'] = {'object_type': 'link',
                                             'destination':
                                             'vgridworkflows.py?vgrid_name=%s' % \
                                             vgrid_name,
                                             'class': 'workflowslink',
                                             'title': 'Open %s private workflows' \
                                             % vgrid_name, 
                                               'text': 'Open'}
            vgrid_obj['privatemonitorlink'] = {'object_type': 'link',
                                               'destination':
                                               'showvgridmonitor.py?vgrid_name=%s'\
                                               % vgrid_name,
                                               'class': 'monitorlink',
                                               'title': 'View %s monitor' % \
                                               vgrid_name, 
                                               'text': 'View'}

            # to leave this VGrid (remove ourselves). Note that we are
            # going to overwrite the link later for owners.

            js_name = 'rmvgridmember%s' % hexlify(vgrid_name)
            helper = html_post_helper(js_name, 'rmvgridmember.py',
                                      {'vgrid_name': vgrid_name,
                                       'cert_id': client_id})
            output_objects.append({'object_type': 'html_form', 'text': helper})
            vgrid_obj['memberlink'] = \
                                    {'object_type': 'link',
                                     'destination':
                                     "javascript: confirmDialog(%s, '%s');"\
                                     % (js_name, "Really leave " + vgrid_name + "?"),
                                     'class': 'removelink',
                                     'title': 'Leave %s members' % vgrid_name, 
                                     'text': ''}
            
        # owners are allowed to edit pages and administrate

        if vgrid_is_owner(vgrid_name, client_id, configuration):
            vgrid_obj['ownerscmlink'] = {'object_type': 'link',
                                         'destination': '/vgridownerscm/%s' % \
                                         vgrid_name,
                                         'class': 'scmlink owner',
                                         'title': 'View %s owners scm' % \
                                         vgrid_name,
                                         'text': 'View'}
            vgrid_obj['ownertrackerlink'] = {'object_type': 'link',
                                         'destination': '/vgridownertracker/%s' % \
                                         vgrid_name,
                                         'class': 'trackerlink owner',
                                         'title': 'View %s owners tracker' % \
                                         vgrid_name,
                                         'text': 'View'}

            # correct the link to leave the VGrid

            js_name = 'rmvgridowner%s' % hexlify(vgrid_name)
            helper = html_post_helper(js_name, 'rmvgridowner.py',
                                      {'vgrid_name': vgrid_name,
                                       'cert_id': client_id})
            output_objects.append({'object_type': 'html_form', 'text': helper})
            vgrid_obj['memberlink']['destination'] = \
                      "javascript: confirmDialog(%s,'%s');" % \
                      (js_name, "Really leave " + vgrid_name + "?")
            vgrid_obj['memberlink']['class'] = 'removeadminlink'
            vgrid_obj['memberlink']['title'] = 'Leave %s owners' % vgrid_name

            # add more links: administrate and edit pages

            vgrid_obj['administratelink'] = {'object_type': 'link',
                                             'destination': 'adminvgrid.py?vgrid_name=%s'\
                                             % vgrid_name,
                                             'class': 'adminlink',
                                             'title': 'Administrate %s' % vgrid_name,
                                             'text': ''}
            vgrid_obj['editprivatelink'] = {'object_type': 'link',
                                            'destination': 'fileman.py?path=private_base/%s/'\
                                            % vgrid_name,
                                            'class': 'editlink owner',
                                            'title': 'Edit private %s web page' % vgrid_name,
                                            'text': 'Edit'}
            vgrid_obj['editpubliclink'] = {'object_type': 'link',
                                           'destination': 'fileman.py?path=public_base/%s/'\
                                           % vgrid_name,
                                           'class': 'editlink member',
                                           'title': 'Edit public %s web page' % vgrid_name,
                                           'text': 'Edit'}


        member_list['vgrids'].append(vgrid_obj)

    title_entry = find_entry(output_objects, 'title')
    label = "%ss" % configuration.site_vgrid_label
    # Append VGrid note if custom
    if label != 'VGrid':
        label += ' (i.e. VGrids)'
    title_entry['text'] = '%s administration' % label

    # jquery support for tablesorter and confirmation on "leave":

    title_entry['style'] = themed_styles(configuration)
    title_entry['javascript'] = '''
<script type="text/javascript" src="/images/js/jquery.js"></script>
<script type="text/javascript" src="/images/js/jquery.tablesorter.js"></script>
<script type="text/javascript" src="/images/js/jquery.tablesorter.pager.js"></script>
<script type="text/javascript" src="/images/js/jquery.tablesorter.widgets.js"></script>
<script type="text/javascript" src="/images/js/jquery-ui.js"></script>
<script type="text/javascript" src="/images/js/jquery.confirm.js"></script>

<script type="text/javascript" >

$(document).ready(function() {

          // init confirmation dialog
          $( "#confirm_dialog" ).dialog(
              // see http://jqueryui.com/docs/dialog/ for options
              { autoOpen: false,
                modal: true, closeOnEscape: true,
                width: 500,
                buttons: {
                   "Cancel": function() { $( "#" + name ).dialog("close"); }
                }
              });

          // table initially sorted by col. 1 (admin), then 2 (member), then 0 (name)
          var sortOrder = [[1,1],[2,1],[0,0]];

          // use image path for sorting if there is any inside
          var imgTitle = function(contents) {
              var key = $(contents).find("a").attr("class");
              if (key == null) {
                  key = $(contents).html();
              }
              return key;
          }

          $("#vgridtable").tablesorter({widgets: ["zebra", "saveSort"],
                                        sortList:sortOrder,
                                        textExtraction: imgTitle
                                        })
                          .tablesorterPager({ container: $("#pager"),
                                        size: %s
                                        });
     }
);
</script>
''' % default_pager_entries

    output_objects.append({'object_type': 'html_form',
                           'text':'''
 <div id="confirm_dialog" title="Confirm" style="background:#fff;">
  <div id="confirm_text"><!-- filled by js --></div>
   <textarea cols="40" rows="4" id="confirm_input" style="display:none;"></textarea>
 </div>
'''                       })

    output_objects.append({'object_type': 'header', 'text': label})
    output_objects.append({'object_type': 'text', 'text'
                          : '''
%ss share files, a number of collaboration tools and resources. Members can access web pages, files, tools and resources. Owners can additionally edit pages, as well as add and remove members or resources.
''' % configuration.site_vgrid_label
                       })

    if configuration.site_vgrid_label != 'VGrid':
        output_objects.append({'object_type': 'text', 'text'
                          : """Please note that for historical reasons %ss are
also referred to as VGrids in some contexts.""" % \
                               configuration.site_vgrid_label})

    output_objects.append({'object_type': 'sectionheader', 'text'
                          : '%ss managed on this server' % \
                           configuration.site_vgrid_label})
    output_objects.append({'object_type': 'table_pager', 'entry_name': '%ss' % \
                           configuration.site_vgrid_label,
                           'default_entries': default_pager_entries})
    output_objects.append(member_list)

    user_map = get_full_user_map(configuration)
    user_dict = user_map.get(client_id, None)
    # Optional limitation of create vgrid permission
    if user_dict and vgrid_create_allowed(configuration, user_dict):
        output_objects.append({'object_type': 'sectionheader', 'text'
                               : 'Additional %ss' % \
                               configuration.site_vgrid_label})

        output_objects.append(
            {'object_type': 'text', 'text':
             '''Please enter a name for the new %(label)s to add, using slashes to
 specify nesting. I.e. if you own a %(label)s called ABC, you can create a
 sub-%(label)s called DEF by entering ABC/DEF below.''' % \
             {'label': configuration.site_vgrid_label}})
        output_objects.append({'object_type': 'html_form', 'text':
                                '''<form method="post" action="createvgrid.py">
    <input type="text" size=40 name="vgrid_name" />
    <input type="hidden" name="output_format" value="html" />
    <input type="submit" value="Create %s" />
    </form>
 ''' % configuration.site_vgrid_label})

    output_objects.append({'object_type': 'sectionheader', 'text'
                               : 'Request Access to %ss' % \
                               configuration.site_vgrid_label})

    output_objects.append(
        {'object_type': 'text', 'text':
         '''You can request access to %(label)ss using the individual plus-icons above directly or by entering the name of the %(label)s to request access to, what kind of access and an optional message to the admins below''' % \
             {'label': configuration.site_vgrid_label}})
    output_objects.append({'object_type': 'html_form', 'text':
                           '''<form method="post" action="sendrequestaction.py">
    <input type="text" size=40 name="vgrid_name" />
    <select name="request_type">
        <option value="vgridmember">membership</option> 
        <option value="vgridowner">ownership</option>
    </select>
    <input type="text" size=50 name="request_text" />
    <input type="hidden" name="output_format" value="html" />
    <input type="submit" value="Request %s access" />
    </form>
 ''' % configuration.site_vgrid_label})

    return (output_objects, status)