コード例 #1
0
ファイル: deletefreeze.py プロジェクト: heromod/migrid
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)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Delete frozen archive'
    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)

    flavor = accepted['flavor'][-1]

    if not flavor in freeze_flavors.keys():
        output_objects.append({'object_type': 'error_text', 'text':
                           'Invalid freeze flavor: %s' % flavor})
        return (output_objects, returnvalues.CLIENT_ERROR)

    title = freeze_flavors[flavor]['deletefreeze_title']
    output_objects.append({'object_type': 'header', 'text': title})
    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = title

    if not configuration.site_enable_freeze:
        output_objects.append({'object_type': 'text', 'text':
                               '''Freezing archives is disabled on this site.
Please contact the Grid admins %s if you think it should be enabled.
''' % configuration.admin_email})
        return (output_objects, returnvalues.OK)

    freeze_id = accepted['freeze_id'][-1]

    # NB: the restrictions on freeze_id prevents illegal directory traversal

    if not is_frozen_archive(freeze_id, configuration):
        logger.error("%s: invalid freeze '%s': %s" % (op_name,
                                                      client_id, freeze_id))
        output_objects.append({'object_type': 'error_text',
                               'text': "No such frozen archive: '%s'"
                               % freeze_id})
        return (output_objects, returnvalues.CLIENT_ERROR)
    
    (load_status, freeze_dict) = get_frozen_archive(freeze_id, configuration)
    if not load_status:
        logger.error("%s: load failed for '%s': %s" % \
                     (op_name, freeze_id, freeze_dict))
        output_objects.append(
            {'object_type': 'error_text',
             'text': 'Could not read frozen archive details for %s'
             % freeze_id})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # Prevent easy delete if the frozen archive if configuration forbids it
    if configuration.site_permanent_freeze:
        output_objects.append(
            {'object_type': 'error_text', 'text':
             "Can't delete frozen archive '%s' yourself due to site policy"
             % freeze_id})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Make sure the frozen archive belongs to the user trying to delete it
    if client_id != freeze_dict['CREATOR']:
        logger.error("%s: illegal access attempt for '%s': %s" % \
                         (op_name, freeze_id, client_id))
        output_objects.append({'object_type': 'error_text', 'text': \
        'You are not the owner of frozen archive "%s"' % freeze_id})
        return (output_objects, returnvalues.CLIENT_ERROR)

    if freeze_dict.get('FLAVOR','freeze') != flavor:
        logger.error("%s: flavor mismatch for '%s': %s vs %s" % \
                     (op_name, freeze_id, flavor, freeze_dict))
        output_objects.append({'object_type': 'error_text', 'text'
                               : 'No such %s archive "%s"' % (flavor,
                                                              freeze_id)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Delete the frozen archive
    (status, msg) = delete_frozen_archive(freeze_id, configuration)
    
    # If something goes wrong when trying to delete frozen archive
    # freeze_id, an error is displayed.
    if not status:
        logger.error("%s: failed for '%s': %s" % (op_name,
                                                  freeze_id, msg))
        output_objects.append({'object_type': 'error_text', 'text'
                               : 'Could not remove %s frozen archive: %s'
                               % (freeze_id, msg)})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # If deletion of frozen archive freeze_id is successful, we just
    # return OK
    else:
        logger.info("%s: successful for '%s': %s" % (op_name,
                                                      freeze_id, client_id))
        output_objects.append(
            {'object_type': 'text', 'text'
             : 'Successfully deleted frozen archive: "%s"' % freeze_id})
        output_objects.append({'object_type': 'link', 'destination':
                               'freezedb.py',
                               'class': 'infolink',
                               'title': 'Show frozen archives',
                               'text': 'Show frozen archives'})
        return (output_objects, returnvalues.OK) 
コード例 #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')
    title_entry['text'] = "Show freeze"
    (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)

    freeze_id = accepted['freeze_id'][-1]
    flavor = accepted['flavor'][-1]
    checksum_list = [i for i in accepted['checksum'] if i]
    operation = accepted['operation'][-1]

    if not flavor in freeze_flavors.keys():
        output_objects.append({
            'object_type': 'error_text',
            'text': 'Invalid freeze flavor: %s' % flavor
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    title = freeze_flavors[flavor]['showfreeze_title']
    title_entry['text'] = title
    output_objects.append({'object_type': 'header', 'text': title})

    sorted_algos = supported_hash_algos()
    sorted_algos.sort()
    for checksum in checksum_list:
        if not checksum in sorted_algos:
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Invalid checksum algo(s): %s' % checksum
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

    if not configuration.site_enable_freeze:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''Freezing archives is disabled on this site.
Please contact the site admins %s if you think it should be enabled.
''' % configuration.admin_email
        })
        return (output_objects, returnvalues.OK)

    if not operation in allowed_operations:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''Operation must be one of %s.''' % ', '.join(allowed_operations)
        })
        return (output_objects, returnvalues.OK)

    # We don't generally know checksum and edit status until AJAX returns
    hide_elems = {'edit': 'hidden', 'update': 'hidden', 'register': 'hidden'}
    for algo in sorted_algos:
        hide_elems['%ssum' % algo] = 'hidden'

    if operation in show_operations:

        # jquery support for tablesorter and confirmation dialog
        # table initially sorted by col. 0 (filename)

        refresh_call = 'ajax_showfreeze("%s", "%s", %s, "%s", "%s", "%s", "%s")' % \
                       (freeze_id, flavor, checksum_list, keyword_updating,
                        keyword_final, configuration.site_freeze_doi_url,
                        configuration.site_freeze_doi_url_field)
        table_spec = {
            'table_id': 'frozenfilestable',
            'sort_order': '[[0,0]]',
            'refresh_call': refresh_call
        }
        (add_import, add_init,
         add_ready) = man_base_js(configuration, [table_spec])
        if operation == "show":
            add_ready += '%s;' % refresh_call

        # Only show requested checksums
        for algo in sorted_algos:
            if algo in checksum_list:
                add_ready += """
        $('.%ssum').show();
""" % checksum
            else:
                add_ready += """
        $('.%ssum').hide();
        """ % algo

        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)
        })
        output_objects.append({
            'object_type': 'table_pager',
            'entry_name': 'frozen files',
            'default_entries': default_pager_entries,
            'refresh_button': False
        })

        # Helper form for removes

        form_method = 'post'
        csrf_limit = get_csrf_limit(configuration)
        target_op = 'deletefreeze'
        csrf_token = make_csrf_token(configuration, form_method, target_op,
                                     client_id, csrf_limit)
        helper = html_post_helper(
            'delfreeze', '%s.py' % target_op, {
                'freeze_id': '__DYNAMIC__',
                'flavor': '__DYNAMIC__',
                'path': '__DYNAMIC__',
                'target': TARGET_PATH,
                csrf_field: csrf_token
            })
        output_objects.append({'object_type': 'html_form', 'text': helper})

    # NB: the restrictions on freeze_id prevents illegal directory traversal

    if not is_frozen_archive(client_id, freeze_id, configuration):
        logger.error("%s: invalid freeze '%s': %s" %
                     (op_name, client_id, freeze_id))
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            "'%s' is not an existing frozen archive!" % freeze_id
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    if operation in list_operations:
        (load_status,
         freeze_dict) = get_frozen_archive(client_id, freeze_id, configuration,
                                           checksum_list)
        if not load_status:
            logger.error("%s: load failed for '%s': %s" %
                         (op_name, freeze_id, freeze_dict))
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Could not read details for "%s"' % freeze_id
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)

        if freeze_dict.get('FLAVOR', 'freeze') != flavor:
            logger.error("%s: flavor mismatch for '%s': %s vs %s" %
                         (op_name, freeze_id, flavor, freeze_dict))
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'No such %s archive "%s"' % (flavor, freeze_id)
            })
            return (output_objects, returnvalues.CLIENT_ERROR)

        # Allow edit if not in updating/final state and allow request DOI if
        # finalized and not a backup archive.
        freeze_state = freeze_dict.get('STATE', keyword_final)
        if freeze_state == keyword_updating:
            hide_elems['update'] = ''
        elif freeze_state != keyword_final:
            hide_elems['edit'] = ''
        elif flavor != 'backup' and configuration.site_freeze_doi_url and \
                freeze_dict.get('PUBLISH_URL', ''):
            hide_elems['register'] = ''

        logger.debug("%s: build obj for '%s': %s" %
                     (op_name, freeze_id, brief_freeze(freeze_dict)))
        output_objects.append(
            build_freezeitem_object(configuration, freeze_dict))

    if operation == "show":
        # insert dummy placeholder to build table
        output_objects.append({
            'object_type': 'frozenarchive',
            'id': freeze_id,
            'creator': client_id,
            'flavor': flavor,
            'frozenfiles': [],
            'name': 'loading ...',
            'description': 'loading ...',
            'created': 'loading ...',
            'state': 'loading ...'
        })
    if operation in show_operations:
        output_objects.append({
            'object_type':
            'html_form',
            'text':
            """<p>
Show archive with file checksums - might take quite a while to calculate:
</p>"""
        })
        for algo in sorted_algos:
            output_objects.append({'object_type': 'html_form', 'text': '<p>'})
            output_objects.append({
                'object_type':
                'link',
                'destination':
                "showfreeze.py?freeze_id=%s;flavor=%s;checksum=%s" %
                (freeze_id, flavor, algo),
                'class':
                'infolink iconspace genericbutton',
                'title':
                'View archive with %s checksums' % algo.upper(),
                'text':
                'Show with %s checksums' % algo.upper()
            })
            output_objects.append({'object_type': 'html_form', 'text': '</p>'})

        # We don't know state of archive in this case until AJAX returns
        # so we hide the section and let AJAX show it if relevant
        output_objects.append({
            'object_type':
            'html_form',
            'text':
            """
<div class='updatearchive %(update)s'>
<p class='warn_message'>
Archive is currently in the process of being updated. No further changes can be
applied until running archive operations are completed. 
</p>
</div>
<div class='editarchive %(edit)s'>
<p>
You can continue inspecting and changing your archive until you're satisfied,
then finalize it for actual persistent freezing.
</p>
<p>""" % hide_elems
        })
        output_objects.append({
            'object_type':
            'link',
            'destination':
            "adminfreeze.py?freeze_id=%s;flavor=%s" % (freeze_id, flavor),
            'class':
            'editarchivelink iconspace genericbutton',
            'title':
            'Further modify your pending %s archive' % flavor,
            'text':
            'Edit archive'
        })
        output_objects.append({'object_type': 'html_form', 'text': '</p>'})
        form_method = 'post'
        target_op = 'createfreeze'
        csrf_limit = get_csrf_limit(configuration)
        csrf_token = make_csrf_token(configuration, form_method, target_op,
                                     client_id, csrf_limit)
        helper = html_post_helper(
            'createfreeze', '%s.py' % target_op, {
                'freeze_id': freeze_id,
                'flavor': flavor,
                'freeze_state': keyword_final,
                csrf_field: csrf_token
            })
        output_objects.append({'object_type': 'html_form', 'text': helper})
        output_objects.append({
            'object_type':
            'link',
            'destination':
            "javascript: confirmDialog(%s, '%s');" %
            ('createfreeze', 'Really finalize %s?' % freeze_id),
            'class':
            'finalizearchivelink iconspace genericbutton',
            'title':
            'Finalize %s archive to prevent further changes' % flavor,
            'text':
            'Finalize archive',
        })
        output_objects.append({
            'object_type':
            'html_form',
            'text':
            """
</div>
<div class='registerarchive %(register)s'>
<p>
You can register a <a href='http://www.doi.org/index.html'>Digital Object
Identifier (DOI)</a> for finalized archives. This may be useful in case you
want to reference the contents in a publication.
</p>
""" % hide_elems
        })
        form_method = 'post'
        target_op = 'registerfreeze'
        csrf_limit = get_csrf_limit(configuration)
        csrf_token = make_csrf_token(configuration, form_method, target_op,
                                     client_id, csrf_limit)
        helper = html_post_helper(
            'registerfreeze', configuration.site_freeze_doi_url, {
                'freeze_id': freeze_id,
                'freeze_author': client_id,
                configuration.site_freeze_doi_url_field: '__DYNAMIC__',
                'callback_url': "%s.py" % target_op,
                csrf_field: csrf_token
            })
        output_objects.append({'object_type': 'html_form', 'text': helper})
        output_objects.append({
            'object_type': 'html_form',
            'text': configuration.site_freeze_doi_text
        })
        output_objects.append({
            'object_type':
            'link',
            'destination':
            "javascript: confirmDialog(%s, '%s');" %
            ('registerfreeze', 'Really request DOI for %s?' % freeze_id),
            'class':
            'registerarchivelink iconspace genericbutton',
            'title':
            'Register a DOI for %s archive %s' % (flavor, freeze_id),
            'text':
            'Request archive DOI',
        })
        output_objects.append({
            'object_type': 'html_form',
            'text': """
</div>"""
        })

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

    return (output_objects, returnvalues.OK)
コード例 #3
0
                         % (op_name, share_id))
            output_objects.append(
                {'object_type': 'error_text', 'text': """Import is only
supported for directory sharelinks!"""})
            return (output_objects, returnvalues.CLIENT_ERROR)
        elif not os.path.isdir(src_base):
            logger.error('%s called import with non-existant sharelink: %s'
                         % (client_id, share_id))
            output_objects.append(
                {'object_type': 'error_text', 'text': 'No such sharelink: %s'
                 % share_id})
            return (output_objects, returnvalues.CLIENT_ERROR)

    # Archive import if freeze_id is given - change to archive as src base
    if freeze_id:
        if not is_frozen_archive(client_id, freeze_id, configuration):
            logger.error('%s called with invalid freeze_id: %s' %
                         (op_name, freeze_id))
            output_objects.append(
                {'object_type': 'error_text', 'text':
                 'Invalid archive ID: %s' % freeze_id})
            return (output_objects, returnvalues.CLIENT_ERROR)
        target_dir = os.path.join(client_dir, freeze_id)
        src_base = os.path.abspath(os.path.join(configuration.freeze_home,
                                                target_dir)) + os.sep
        if not os.path.isdir(src_base):
            logger.error('%s called import with non-existant archive: %s'
                         % (client_id, freeze_id))
            output_objects.append(
                {'object_type': 'error_text', 'text': 'No such archive: %s'
                 % freeze_id})
コード例 #4
0
ファイル: createfreeze.py プロジェクト: ucphhpc/migrid
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'] = "Create Archive"
    # NOTE: Delay header entry here to include freeze flavor
    # All non-file fields must be validated
    validate_args = dict([(key, user_arguments_dict.get(key, val)) for
                          (key, val) in defaults.items()])
    # IMPORTANT: we must explicitly inlude CSRF token
    validate_args[csrf_field] = user_arguments_dict.get(csrf_field, [
                                                        'AllowMe'])
    (validate_status, accepted) = validate_input_and_cert(
        validate_args,
        defaults,
        output_objects,
        client_id,
        configuration,
        allow_rejects=False,
    )
    if not validate_status:
        return (accepted, returnvalues.CLIENT_ERROR)

    flavor = accepted['flavor'][-1].strip()
    freeze_state = accepted['freeze_state'][-1].strip()

    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 flavor in freeze_flavors.keys():
        output_objects.append({'object_type': 'error_text', 'text':
                               'Invalid freeze flavor: %s' % flavor})
        return (output_objects, returnvalues.CLIENT_ERROR)
    if not freeze_state in freeze_flavors[flavor]['states'] + [keyword_auto]:
        output_objects.append({'object_type': 'error_text', 'text':
                               'Invalid freeze state: %s' % freeze_state})
        return (output_objects, returnvalues.CLIENT_ERROR)

    title = freeze_flavors[flavor]['createfreeze_title']
    output_objects.append({'object_type': 'header', 'text': title})

    if not configuration.site_enable_freeze:
        output_objects.append({'object_type': 'text', 'text':
                               '''Freezing archives is disabled on this site.
Please contact the site admins %s if you think it should be enabled.
''' % configuration.admin_email})
        return (output_objects, returnvalues.OK)

    # jquery support for confirmation on freeze
    (add_import, add_init, add_ready) = man_base_js(configuration, [])
    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)})

    freeze_id = accepted['freeze_id'][-1].strip()
    freeze_name = accepted['freeze_name'][-1].strip()
    freeze_description = accepted['freeze_description'][-1]
    freeze_author = accepted['freeze_author'][-1].strip()
    freeze_department = accepted['freeze_department'][-1].strip()
    freeze_organization = accepted['freeze_organization'][-1].strip()
    freeze_publish = accepted['freeze_publish'][-1].strip()
    do_publish = (freeze_publish.lower() in ('on', 'true', 'yes', '1'))

    # Share init of base meta with lookup of default state in freeze_flavors
    if not freeze_state or freeze_state == keyword_auto:
        freeze_state = freeze_flavors[flavor]['states'][0]
    freeze_meta = {'ID': freeze_id, 'STATE': freeze_state}

    # New archives must have name and description set
    if freeze_id == keyword_auto:
        logger.debug("creating a new %s archive for %s" % (flavor, client_id))
        if not freeze_name or freeze_name == keyword_auto:
            freeze_name = '%s-%s' % (flavor, datetime.datetime.now())
        if not freeze_description:
            if flavor == 'backup':
                freeze_description = 'manual backup archive created on %s' % \
                                     datetime.datetime.now()
            else:
                output_objects.append(
                    {'object_type': 'error_text', 'text':
                     'You must provide a description for the archive!'})
                return (output_objects, returnvalues.CLIENT_ERROR)
        if flavor == 'phd' and (not freeze_author or not freeze_department):
            output_objects.append({'object_type': 'error_text', 'text': """
You must provide author and department for the thesis!"""})
            return (output_objects, returnvalues.CLIENT_ERROR)
        freeze_meta.update(
            {'FLAVOR': flavor, 'NAME': freeze_name,
             'DESCRIPTION': freeze_description,
             'AUTHOR': freeze_author, 'DEPARTMENT': freeze_department,
             'ORGANIZATION': freeze_organization, 'PUBLISH': do_publish})
    elif is_frozen_archive(client_id, freeze_id, configuration):
        logger.debug("updating existing %s archive for %s" % (flavor,
                                                              client_id))
        # Update any explicitly provided fields (may be left empty on finalize)
        changes = {}
        if freeze_name and freeze_name != keyword_auto:
            changes['NAME'] = freeze_name
        if freeze_author:
            changes['AUTHOR'] = freeze_author
        if freeze_description:
            changes['DESCRIPTION'] = freeze_description
        if freeze_publish:
            changes['PUBLISH'] = do_publish
        logger.debug("updating existing %s archive for %s with: %s" %
                     (flavor, client_id, changes))
        logger.debug("publish is %s based on %s" %
                     (do_publish, freeze_publish))
        freeze_meta.update(changes)
    else:
        logger.error("no such %s archive for %s: %s" % (flavor, client_id,
                                                        freeze_id))
        output_objects.append({'object_type': 'error_text', 'text': """
Invalid archive ID %s - you must either create a new archive or edit an
existing archive of yours!""" % freeze_id})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Now parse and validate files to archive

    for name in defaults.keys():
        if user_arguments_dict.has_key(name):
            del user_arguments_dict[name]

    (copy_files, copy_rejected) = parse_form_copy(user_arguments_dict,
                                                  client_id, configuration)
    (move_files, move_rejected) = parse_form_move(user_arguments_dict,
                                                  client_id, configuration)
    (upload_files, upload_rejected) = parse_form_upload(user_arguments_dict,
                                                        client_id,
                                                        configuration)
    if copy_rejected + move_rejected + upload_rejected:
        output_objects.append({'object_type': 'error_text', 'text':
                               'Errors parsing freeze files: %s' %
                               '\n '.join(copy_rejected + move_rejected +
                                          upload_rejected)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    # NOTE: this may be a new or an existing pending archive, and it will fail
    #       if archive is already under update
    (retval, retmsg) = create_frozen_archive(freeze_meta, copy_files,
                                             move_files, upload_files,
                                             client_id, configuration)
    if not retval:
        output_objects.append({'object_type': 'error_text', 'text':
                               'Error creating/updating archive: %s'
                               % retmsg})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # Make sure we have freeze_id and other updated fields
    freeze_meta.update(retmsg)
    freeze_id = freeze_meta['ID']
    logger.info("%s: successful for '%s': %s" % (op_name,
                                                 freeze_id, client_id))
    # Return simple status mainly for use in scripting
    output_objects.append({'object_type': 'freezestatus', 'freeze_id': freeze_id,
                           'flavor': flavor, 'freeze_state': freeze_state})
    publish_note = ''
    if freeze_state == keyword_pending:
        publish_hint = 'Preview published archive page in a new window/tab'
        publish_text = 'Preview publishing'
        output_objects.append({'object_type': 'text', 'text': """
Saved *preliminary* %s archive with ID %s . You can continue inspecting and
changing it until you're satisfied, then finalize it for actual persistent
freezing.""" % (flavor, freeze_id)})
    else:
        publish_hint = 'View published archive page in a new window/tab'
        publish_text = 'Open published archive'
        output_objects.append({'object_type': 'text', 'text':
                               'Successfully froze %s archive with ID %s .'
                               % (flavor, freeze_id)})

    if do_publish:
        public_url = published_url(freeze_meta, configuration)
        output_objects.append({'object_type': 'text', 'text': ''})
        output_objects.append({
            'object_type': 'link',
            'destination': public_url,
            'class': 'previewarchivelink iconspace genericbutton',
            'title': publish_hint,
            'text': publish_text,
            'target': '_blank',
        })
        output_objects.append({'object_type': 'text', 'text': ''})

    # Always allow show archive
    output_objects.append({
        'object_type': 'link',
        'destination': 'showfreeze.py?freeze_id=%s;flavor=%s' % (freeze_id,
                                                                 flavor),
        'class': 'viewarchivelink iconspace genericbutton',
        'title': 'View details about your %s archive' % flavor,
        'text': 'View details',
    })

    if freeze_state == keyword_pending:
        output_objects.append({'object_type': 'text', 'text': ''})
        output_objects.append({
            'object_type': 'link',
            'destination': 'adminfreeze.py?freeze_id=%s' % freeze_id,
            'class': 'editarchivelink iconspace genericbutton',
            'title': 'Further modify your pending %s archive' % flavor,
            'text': 'Edit archive',
        })
        output_objects.append({'object_type': 'text', 'text': ''})
        output_objects.append({'object_type': 'html_form', 'text': """
<br/><hr/><br/>
<p class='warn_message'>IMPORTANT: you still have to explicitly finalize your
archive before you get the additional data integrity/persistance guarantees
like tape archiving.
</p>"""})

        form_method = 'post'
        target_op = 'createfreeze'
        csrf_limit = get_csrf_limit(configuration)
        csrf_token = make_csrf_token(configuration, form_method, target_op,
                                     client_id, csrf_limit)
        helper = html_post_helper('createfreeze', '%s.py' % target_op,
                                  {'freeze_id': freeze_id,
                                   'freeze_state': keyword_final,
                                   'flavor': flavor,
                                   csrf_field: csrf_token})
        output_objects.append({'object_type': 'html_form', 'text': helper})

        output_objects.append({
            'object_type': 'link',
            'destination':
            "javascript: confirmDialog(%s, '%s');" %
            ('createfreeze', 'Really finalize %s?' % freeze_id),
            'class': 'finalizearchivelink iconspace genericbutton',
            'title': 'Finalize %s archive to prevent further changes' % flavor,
            'text': 'Finalize archive',
        })

    return (output_objects, returnvalues.OK)
コード例 #5
0
ファイル: showfreeze.py プロジェクト: heromod/migrid
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)

    flavor = accepted["flavor"][-1]

    if not flavor in freeze_flavors.keys():
        output_objects.append({"object_type": "error_text", "text": "Invalid freeze flavor: %s" % flavor})
        return (output_objects, returnvalues.CLIENT_ERROR)

    title = freeze_flavors[flavor]["showfreeze_title"]
    output_objects.append({"object_type": "header", "text": title})
    title_entry = find_entry(output_objects, "title")
    title_entry["text"] = title

    if not configuration.site_enable_freeze:
        output_objects.append(
            {
                "object_type": "text",
                "text": """Freezing archives is disabled on this site.
Please contact the Grid admins %s if you think it should be enabled.
"""
                % configuration.admin_email,
            }
        )
        return (output_objects, returnvalues.OK)

    # jquery support for tablesorter

    css_helpers = {
        "css_base": os.path.join(configuration.site_images, "css"),
        "skin_base": configuration.site_skin_base,
    }
    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" >

$(document).ready(function() {

          // table initially sorted by col. 0 (filename)
          var sortOrder = [[0,1]];

          // 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;
          }


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

    freeze_id = accepted["freeze_id"][-1]

    # NB: the restrictions on freeze_id prevents illegal directory traversal

    if not is_frozen_archive(freeze_id, configuration):
        logger.error("%s: invalid freeze '%s': %s" % (op_name, client_id, freeze_id))
        output_objects.append(
            {"object_type": "error_text", "text": "'%s' is not an existing frozen archive!" % freeze_id}
        )
        return (output_objects, returnvalues.CLIENT_ERROR)

    (load_status, freeze_dict) = get_frozen_archive(freeze_id, configuration)
    if not load_status:
        logger.error("%s: load failed for '%s': %s" % (op_name, freeze_id, freeze_dict))
        output_objects.append({"object_type": "error_text", "text": 'Could not read details for "%s"' % freeze_id})
        return (output_objects, returnvalues.SYSTEM_ERROR)

    if freeze_dict.get("FLAVOR", "freeze") != flavor:
        logger.error("%s: flavor mismatch for '%s': %s vs %s" % (op_name, freeze_id, flavor, freeze_dict))
        output_objects.append({"object_type": "error_text", "text": 'No such %s archive "%s"' % (flavor, freeze_id)})
        return (output_objects, returnvalues.CLIENT_ERROR)

    output_objects.append(
        {"object_type": "table_pager", "entry_name": "frozen files", "default_entries": default_pager_entries}
    )
    output_objects.append(build_freezeitem_object(configuration, freeze_dict))

    return (output_objects, returnvalues.OK)
コード例 #6
0
ファイル: deletefreeze.py プロジェクト: ucphhpc/migrid
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)

    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = 'Delete frozen archive'
    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)

    flavor = accepted['flavor'][-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 flavor in freeze_flavors.keys():
        output_objects.append({
            'object_type': 'error_text',
            'text': 'Invalid freeze flavor: %s' % flavor
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    title = freeze_flavors[flavor]['deletefreeze_title']
    output_objects.append({'object_type': 'header', 'text': title})
    title_entry = find_entry(output_objects, 'title')
    title_entry['text'] = title

    if not configuration.site_enable_freeze:
        output_objects.append({
            'object_type':
            'text',
            'text':
            '''Freezing archives is disabled on this site.
Please contact the site admins %s if you think it should be enabled.
''' % configuration.admin_email
        })
        return (output_objects, returnvalues.OK)

    freeze_id = accepted['freeze_id'][-1]
    target = accepted['target'][-1]
    path_list = accepted['path']

    if not target in valid_targets:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Invalid delete freeze target: %s' % target
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # NB: the restrictions on freeze_id prevents illegal directory traversal

    if not is_frozen_archive(client_id, freeze_id, configuration):
        logger.error("%s: invalid freeze '%s': %s" %
                     (op_name, client_id, freeze_id))
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            "No such frozen archive: '%s'" % freeze_id
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    (load_status, freeze_dict) = get_frozen_archive(client_id,
                                                    freeze_id,
                                                    configuration,
                                                    checksum_list=[])
    if not load_status:
        logger.error("%s: load failed for '%s': %s" %
                     (op_name, freeze_id, freeze_dict))
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Could not read frozen archive details for %s' % freeze_id
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)

    # Make sure the frozen archive belongs to the user trying to delete it
    if client_id != freeze_dict['CREATOR']:
        logger.error("%s: illegal access attempt for '%s': %s" %
                     (op_name, freeze_id, client_id))
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'You are not the owner of frozen archive "%s"' % freeze_id
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    if freeze_dict.get('FLAVOR', 'freeze') != flavor:
        logger.error("%s: flavor mismatch for '%s': %s vs %s" %
                     (op_name, freeze_id, flavor, freeze_dict))
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'No such %s archive "%s"' % (flavor, freeze_id)
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    # Prevent user-delete of the frozen archive if configuration forbids it.
    # We exclude any archives in the pending intermediate freeze state.
    # Freeze admins are also excluded from the restrictions.
    state = freeze_dict.get('STATE', keyword_final)
    if state == keyword_updating:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            "Can't change %s archive %s which is currently being updated" %
            (flavor, freeze_id)
        })
        output_objects.append({
            'object_type':
            'link',
            'destination':
            'showfreeze.py?freeze_id=%s;flavor=%s' % (freeze_id, flavor),
            'class':
            'viewarchivelink iconspace genericbutton',
            'title':
            'View details about your %s archive' % flavor,
            'text':
            'View details',
        })
        return (output_objects, returnvalues.CLIENT_ERROR)
    elif state == keyword_final and \
            flavor in configuration.site_permanent_freeze and \
            not client_id in configuration.site_freeze_admins:
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            "Can't change %s archives like '%s' yourself due to site policy" %
            (flavor, freeze_id)
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    client_dir = client_id_dir(client_id)
    user_archives = os.path.join(configuration.freeze_home, client_dir)

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

    base_dir = os.path.abspath(os.path.join(user_archives, freeze_id)) + os.sep

    if target == TARGET_ARCHIVE:
        # Delete the entire freeze archive
        (del_status, msg) = delete_frozen_archive(freeze_dict, client_id,
                                                  configuration)

        # If something goes wrong when trying to delete freeze archive
        # freeze_id, an error is displayed.
        if not del_status:
            logger.error("%s: failed for '%s': %s" % (op_name, freeze_id, msg))
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Could not remove entire %s archive %s: %s' %
                (flavor, freeze_id, msg)
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)

        # If deletion of frozen archive freeze_id is successful, we just
        # return OK
        else:
            logger.info("%s: successful for '%s': %s" %
                        (op_name, freeze_id, client_id))
            output_objects.append({
                'object_type':
                'text',
                'text':
                'Successfully deleted %s archive: "%s"' % (flavor, freeze_id)
            })
    elif target == TARGET_PATH:
        # Delete individual files in non-final archive
        del_paths = []
        for path in path_list:
            # IMPORTANT: path must be expanded to abs for proper chrooting
            server_path = os.path.join(base_dir, path)
            abs_path = os.path.abspath(server_path)
            if not valid_user_path(configuration, abs_path, base_dir, False):

                # Out of bounds!

                logger.warning(
                    '%s tried to %s del restricted path %s ! ( %s)' %
                    (client_id, op_name, abs_path, path))
                output_objects.append({
                    'object_type':
                    'error_text',
                    'text':
                    'Not allowed to delete %s - outside archive %s !' %
                    (path, freeze_id)
                })
                continue
            del_paths.append(path)

        (del_status, msg_list) = delete_archive_files(freeze_dict, client_id,
                                                      del_paths, configuration)

        # If something goes wrong when trying to delete files from archive
        # freeze_id, an error is displayed.
        if not del_status:
            logger.error("%s: delete archive file(s) failed for '%s':\n%s" %
                         (op_name, freeze_id, '\n'.join(msg_list)))
            output_objects.append({
                'object_type':
                'error_text',
                'text':
                'Could not remove file(s) from archive %s: %s' %
                (freeze_id, '\n '.join(msg_list))
            })
            return (output_objects, returnvalues.SYSTEM_ERROR)

        # If deletion of files from archive freeze_id is successful, we just
        # return OK
        else:
            logger.info("%s: delete %d files successful for '%s': %s" %
                        (op_name, len(path_list), freeze_id, client_id))
            output_objects.append({
                'object_type':
                'text',
                'text':
                'Successfully deleted %d file(s) from archive: "%s"' %
                (len(path_list), freeze_id)
            })

    # Success - show link to overview
    output_objects.append({
        'object_type': 'link',
        'destination': 'freezedb.py',
        'class': 'infolink iconspace',
        'title': 'Show archives',
        'text': 'Show archives'
    })
    return (output_objects, returnvalues.OK)
コード例 #7
0
ファイル: showfreezefile.py プロジェクト: ucphhpc/migrid
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)

    freeze_id = accepted['freeze_id'][-1]
    path = accepted['path'][-1]

    if not is_frozen_archive(client_id, freeze_id, configuration):
        output_objects.append({'object_type': 'error_text', 'text':
                               '''No such archive %s owned by you''' % \
                               freeze_id})
        return (output_objects, returnvalues.CLIENT_ERROR)

    client_dir = client_id_dir(client_id)

    # 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.freeze_home, client_dir,
                     freeze_id)) + os.sep

    # TODO: remove this legacy fall back when done migrating archives
    if not os.path.isdir(base_dir):
        base_dir = os.path.abspath(
            os.path.join(configuration.freeze_home, freeze_id)) + os.sep

    # Strip leading slashes to avoid join() throwing away prefix

    rel_path = 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_path))
    if not valid_user_path(configuration, abs_path, base_dir, True):
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            '''You are not allowed to use paths outside the
archive dir.'''
        })
        return (output_objects, returnvalues.CLIENT_ERROR)

    logger.debug('reading archive private file %s' % abs_path)
    try:
        private_fd = open(abs_path, 'rb')
        entry = {'object_type': 'binary', 'data': private_fd.read()}
        logger.info('return %db from archive private file %s of size %db' % \
                    (len(entry['data']), abs_path, os.path.getsize(abs_path)))
        # Cut away all the usual web page formatting to show only contents
        # Insert explicit content type to make sure clients don't break download
        # early because they think it is plain text and find a bogus EOF in
        # binary data.
        (content_type, content_encoding) = mimetypes.guess_type(abs_path)
        if not content_type:
            content_type = 'application/octet-stream'
        output_objects = [{'object_type': 'start',
                           'headers': [
                               ('Content-Type', content_type),
                               ('Content-Disposition',
                                'attachment; filename="%s";' % \
                                os.path.basename(abs_path))
                               ]
                           },
                          entry,
                          {'object_type': 'script_status'},
                          {'object_type': 'end'}]
        private_fd.close()
    except Exception, exc:
        logger.error('Error reading archive private file %s' % exc)
        output_objects.append({
            'object_type':
            'error_text',
            'text':
            'Error reading archive private file %s' % rel_path
        })
        return (output_objects, returnvalues.SYSTEM_ERROR)