Example #1
0
 def test_get_data_curation_users(self):
     depadmin = core_factories.User(name='depadmin')
     curator1 = core_factories.User(name='curator1')
     curator2 = core_factories.User(name='curator2')
     deposit = factories.DataContainer(
         name='data-deposit',
         users=[
             {
                 'name': 'depadmin',
                 'capacity': 'admin'
             },
             {
                 'name': 'curator1',
                 'capacity': 'editor'
             },
             {
                 'name': 'curator2',
                 'capacity': 'editor'
             },
         ],
     )
     curators = helpers.get_data_curation_users(
         context={'user': '******'})
     curator_names = sorted([
         curator['name'] for curator in curators
         # Added to org by ckan
         if not curator['sysadmin']
     ])
     assert_equals(len(curator_names), 3)
     assert_equals(curator_names[0], 'curator1')
     assert_equals(curator_names[1], 'curator2')
     assert_equals(curator_names[2], 'depadmin')
    def withdraw(self, dataset_id):
        user_id = getattr(toolkit.c.userobj, 'id', None)

        # Get curation data
        try:
            context, dataset, curation = _get_curation_data(
                dataset_id, user_id)
        except (toolkit.ObjectNotFound, toolkit.NotAuthorized):
            message = 'Not authorized to read dataset "%s"'
            return toolkit.abort(403, message % dataset_id)

        # Authorize context
        if 'withdraw' not in curation['actions']:
            message = 'This action is not available for the dataset "%s"'
            toolkit.h.flash_error(message % dataset['title'])
            toolkit.redirect_to('deposited-dataset_read', id=dataset['name'])
        context['ignore_auth'] = True

        # Delete withdrawn dataset, but first update its name so it can be reused
        new_name = _get_withdrawn_dataset_name(dataset['name'])
        toolkit.get_action('package_patch')(context, {
            'id': dataset_id,
            'name': new_name
        })
        toolkit.get_action('package_delete')(context, {'id': dataset_id})

        # Update activity stream
        message = toolkit.request.params.get('message')
        helpers.create_curation_activity('dataset_withdrawn',
                                         dataset['id'],
                                         dataset['name'],
                                         user_id,
                                         message=message)

        # Send notification email
        message = toolkit.request.params.get('message')
        for user in helpers.get_data_curation_users():
            subj = mailer.compose_curation_email_subj(dataset)
            body = mailer.compose_curation_email_body(dataset,
                                                      curation,
                                                      user['display_name'],
                                                      'withdraw',
                                                      message=message)
            mailer.mail_user_by_id(user['id'], subj, body)

        # Show flash message and redirect
        message = 'Dataset "%s" withdrawn'
        toolkit.h.flash_error(message % dataset['title'])
        toolkit.redirect_to('data-container_read', id='data-deposit')
    def submit(self, dataset_id):
        user_id = getattr(toolkit.c.userobj, 'id', None)

        # Get curation data
        try:
            context, dataset, curation = _get_curation_data(
                dataset_id, user_id)
        except (toolkit.ObjectNotFound, toolkit.NotAuthorized):
            message = 'Not authorized to read dataset "%s"'
            return toolkit.abort(403, message % dataset_id)

        # Authorize context
        if 'submit' not in curation['actions']:
            message = 'This action is not available for the dataset "%s"'
            toolkit.h.flash_error(message % dataset['title'])
            toolkit.redirect_to('deposited-dataset_read', id=dataset['name'])
        context['ignore_auth'] = True

        # Update dataset
        dataset['curation_state'] = 'submitted'
        dataset = toolkit.get_action('package_update')(context, dataset)

        # Update activity stream
        message = toolkit.request.params.get('message')
        helpers.create_curation_activity('dataset_submitted',
                                         dataset['id'],
                                         dataset['name'],
                                         user_id,
                                         message=message)

        # Send notification email
        message = toolkit.request.params.get('message')
        curator = curation['contacts']['curator']
        # We don't bother all curators if someone is already assigned
        users = [curator] if curator else helpers.get_data_curation_users()
        for user in users:
            subj = mailer.compose_curation_email_subj(dataset)
            body = mailer.compose_curation_email_body(dataset,
                                                      curation,
                                                      user['display_name'],
                                                      'submit',
                                                      message=message)
            mailer.mail_user_by_id(user['id'], subj, body)

        # Show flash message and redirect
        message = 'Dataset "%s" submitted'
        toolkit.h.flash_success(message % dataset['title'])
        toolkit.redirect_to('deposited-dataset_read', id=dataset['name'])
Example #4
0
def resource_download(context, data_dict):
    '''
    This is a new auth function that specifically controls access to the download
    of a resource file, as opposed to seeing the metadata of a resource (handled
    by `resource_show`

    If this resource is marked as public or private in the custom visibility
    field, the authorization check is deferred to `resource_show` as the standard
    logic applies (we assume that the necessary validators are applied to keep
    `visibility` and `private` fields in sync).

    If this resource is marked as `restricted` then only users belonging to
    the dataset organization can download the file.
    '''

    # Prepare all the parts
    context['model'] = context.get('model') or model
    user = context.get('user')
    resource = get_resource_object(context, data_dict)
    dataset = toolkit.get_action('package_show')({
        'ignore_auth': True
    }, {
        'id': resource.package_id
    })
    visibility = resource.extras.get('visibility')

    # Use default check
    user_id = getattr(context.get('auth_user_obj'), 'id', None)
    is_deposit = dataset.get('type') == 'deposited-dataset'
    if is_deposit:
        is_depositor = dataset.get('creator_user_id') == user_id
        curators = [u['id'] for u in helpers.get_data_curation_users(dataset)]
        is_curator = user_id in curators
    else:
        is_depositor = False
        is_curator = False

    if not user or is_depositor or is_curator or not visibility or visibility != 'restricted':
        try:
            toolkit.check_access('resource_show', context, data_dict)
            return {'success': True}
        except toolkit.NotAuthorized:
            return {'success': False}

    # Restricted visibility (public metadata but private downloads)
    if dataset.get('owner_org'):
        user_orgs = toolkit.get_action('organization_list_for_user')(
            {
                'ignore_auth': True
            }, {
                'id': user
            })
        user_in_owner_org = any(org['id'] == dataset['owner_org']
                                for org in user_orgs)
        if user_in_owner_org:
            return {'success': True}

    # Check if the user is a dataset collaborator
    action = toolkit.get_action('package_collaborator_list_for_user')
    if user and action:
        datasets = action(context, {'id': user})
        return {
            'success': resource.package_id
            in [d['package_id'] for d in datasets]
        }

    return {'success': False}