Esempio n. 1
0
def download_repo(record_id,
                  filename,
                  download_url,
                  auth_headers=None,
                  from_snapshot_id=None):
    """Download a repository as a .tar file under record files."""
    response = requests.get(download_url, stream=True, headers=auth_headers)

    # retrieve the data with the correct content length
    if 'Content-Length' not in response.headers:
        response = ensure_content_length(response)

    size = int(response.headers.get('Content-Length'))
    response = response.raw

    from cap.modules.deposit.api import CAPDeposit
    record = CAPDeposit.get_record(record_id)

    # temporary workaround, we save empty file, when downloading failed
    # so we can show it in UI (with tag FAILED)
    failed = True if response.status != 200 else False
    if failed:
        print(f'Downloading content from {download_url}'
              f'failed ({response.status}).')

    obj_ver = record.save_file(response, filename, size, failed)

    if from_snapshot_id:
        obj_ver.snapshot_id = from_snapshot_id
        db.session.commit()
def synchronize_cadi_entries(limit=None):
    """Add/update all CADI entries connecting with CADI database."""

    entries = get_entries_from_cadi_db()
    for entry in entries[0:limit]:
        # remove artefact from code names
        cadi_id = re.sub('^d', '', entry.get('code', None))

        try:  # update if already exists
            parser = HTMLParser()
            uuid = get_entry_uuid_by_unique_field('deposits-records-cms-analysis-v0.0.1',
                                                  {'basic_info__cadi_id': cadi_id})

            deposit = CAPDeposit.get_record(uuid)

            if 'cadi_info' not in deposit:
                deposit['cadi_info'] = {}
            for cadi_key, cap_key in CADI_FIELD_TO_CAP_MAP.items():
                # sometimes they store data in HTML format.. need to escape chars
                deposit['cadi_info'][cap_key] = parser.unescape(entry.get(cadi_key, '')) or ''
            deposit.commit()

            print('Cadi entry {} updated.'.format(cadi_id))

        except DepositDoesNotExist:  # or create new cadi entry
            data = construct_cadi_entry(cadi_id, {
                'cadi_info': {v: parser.unescape(entry.get(k, '')) or ''
                              for k, v in CADI_FIELD_TO_CAP_MAP.items()}
            })

            deposit = CAPDeposit.create(data=data)
            add_read_permission_for_egroup(deposit, '*****@*****.**')

            print('Cadi entry {} added.'.format(cadi_id))
Esempio n. 3
0
def download_repo(record_id, host, owner, repo, branch, source_url,
                  download_url):
    """Download a repository as a .tar file under record files."""
    response = requests.get(download_url, stream=True)
    filename = 'repositories/{}/{}/{}/{}.tar.gz'.format(
        host, owner, repo, branch)

    # retrieve the data with the correct content length
    if 'Content-Length' not in response.headers:
        response = ensure_content_length(response)

    size = int(response.headers.get('Content-Length'))
    response = response.raw

    from cap.modules.deposit.api import CAPDeposit
    record = CAPDeposit.get_record(record_id)

    # temporary workaround, we save empty file, when downloading failed
    # so we can show it in UI (with tag FAILED)
    failed = True if response.status != 200 else False
    if failed:
        print('Downloading content from {} failed ({}).'.format(
            download_url, response.status))

    record.save_file(response, filename, size, source_url, failed)
        def _create_deposit(user, schema_name, metadata=None, experiment=None, publish=False):
            """
            Create a new deposit for given user and schema name
            e.g cms-analysis-v0.0.1,
            with minimal metadata defined for this schema type.
            """
            with app.test_request_context():
                # create schema for record
                create_schema('records/{}'.format(schema_name), is_deposit=False,
                              experiment='CMS')

                # create schema for deposit
                schema = create_schema('deposits/records/{}'.format(schema_name), 
                                       experiment=experiment)
                metadata = metadata or minimal_metadata(jsonschemas_host,
                                                        'deposits/records/{}'.format(schema_name))
                login_user(user)
                id_ = uuid4()
                deposit_minter(id_, metadata)
                deposit = Deposit.create(metadata, id_=id_)

            if publish:
                deposit.publish()
                _, record = deposit.fetch_published()
                RecordIndexer().index(record)

                current_search.flush_and_refresh('records')

            current_search.flush_and_refresh(schema.index_name)

            return Deposit.get_record(deposit.id)
def download_url(record_id, url):
    """Create new file object and assign it to object version."""
    record = CAPDeposit.get_record(record_id)
    record.files[url].file.set_contents(
        requests.get(url, stream=True).raw,
        default_location=record.files.bucket.location.uri,
    )
    db.session.commit()
Esempio n. 6
0
    def get_record_schemas(self, obj):
        deposit = CAPDeposit.get_record(obj['pid'].object_uuid)

        schema = current_jsonschemas.get_schema(deposit.schema.record_path,
                                                with_refs=True,
                                                resolved=True)
        uiSchema = deposit.schema.record_options

        return dict(schema=copy.deepcopy(schema), uiSchema=uiSchema)
    def preprocess_search_hit(self, pid, record_hit, links_factory=None):
        """."""
        result = super(CAPSchemaSerializer, self).preprocess_search_hit(
            pid, record_hit, links_factory=links_factory
        )
        deposit = CAPDeposit.get_record(record_hit['_id'])

        result = self._get_user_rights_to_record(deposit, result)
        result = self._transform_record_owners(result)

        return result
Esempio n. 8
0
    def can_user_review(self, obj):
        deposit_pid = obj.get("metadata", {}).get("_deposit", {}).get("id")

        resolver = Resolver(pid_type='depid',
                            object_type='rec',
                            getter=lambda x: x)

        _, rec_uuid = resolver.resolve(deposit_pid)
        deposit = CAPDeposit.get_record(rec_uuid)

        return (deposit.schema_is_reviewable() and
                ReviewDepositPermission(deposit).can())
Esempio n. 9
0
    def preprocess_search_hit(self, pid, record_hit, links_factory=None):
        """."""
        result = super(CAPSchemaSerializer,
                       self).preprocess_search_hit(pid,
                                                   record_hit,
                                                   links_factory=links_factory)
        deposit = CAPDeposit.get_record(record_hit['_id'])

        result = self._get_user_rights_to_record(deposit, result)
        result = self._transform_record_owners(result)

        return result
    def preprocess_record(self, pid, record, links_factory=None, **kwargs):
        """Preprocess record serializing for record retrievals from the db.

        Call base serializer with deposit_links_factory explicitly.
        (bug in invenio doesn't pass correct one on deposit actions
        (e.g. /actions/publish)
        """
        result = super().preprocess_record(pid,
                                           record,
                                           links_factory=deposit_links_factory)

        result['deposit'] = CAPDeposit.get_record(pid.object_uuid)
        return result
Esempio n. 11
0
    def get_review(self, obj):
        depid = obj.get("metadata", {}).get("_deposit", {}).get("id")
        resolver = Resolver(pid_type='depid',
                            object_type='rec',
                            getter=lambda x: x)

        _, rec_uuid = resolver.resolve(depid)
        deposit = CAPDeposit.get_record(rec_uuid)

        if deposit.schema_is_reviewable():
            _reviews = deposit.get('_review', [])
            return ReviewSchema(many=True).dump(_reviews).data
        else:
            return None
Esempio n. 12
0
    def get_links_with_review(self, obj):
        deposit_pid = obj.get("metadata", {}).get("_deposit", {}).get("id")

        resolver = Resolver(pid_type='depid',
                            object_type='rec',
                            getter=lambda x: x)

        _, rec_uuid = resolver.resolve(deposit_pid)
        deposit = CAPDeposit.get_record(rec_uuid)
        links = obj['links']

        if (deposit.schema_is_reviewable() and
                ReviewDepositPermission(deposit).can()):
            links['review'] = clean_api_url_for(
                'invenio_deposit_rest.depid_actions',
                deposit.pid,
                action="review")

        return links
Esempio n. 13
0
    def _create_deposit(user,
                        schema_name,
                        metadata=None,
                        experiment=None,
                        files={},
                        publish=False,
                        mapping=None):
        """Create a new deposit for given user and schema name.

        e.g cms-analysis-v0.0.1,
        with minimal metadata defined for this schema type.
        """
        # create schema for record
        with app.test_request_context():
            schema = create_schema(schema_name,
                                   experiment=experiment,
                                   deposit_mapping=mapping)
            deposit_schema_url = current_jsonschemas.path_to_url(
                schema.deposit_path)

            metadata = metadata or minimal_metadata(deposit_schema_url)
            login_user(user)
            id_ = uuid4()
            deposit_minter(id_, metadata)
            deposit = Deposit.create(metadata, id_=id_)

            for k, v in files.items():
                deposit.files[k] = v
            if files:
                deposit.commit()

            db.session.commit()

        if publish:
            deposit.publish()
            _, record = deposit.fetch_published()
            RecordIndexer().index(record)

            current_search.flush_and_refresh(schema.record_index)

        current_search.flush_and_refresh(schema.deposit_index)

        return Deposit.get_record(deposit.id)
Esempio n. 14
0
def get_deposit_by_cadi_id(cadi_id):
    """Return deposit with given cadi id.

    :params str cadi_id: CADI identifier

    :rtype `cap.modules.deposits.api:CAPDeposit`
    """
    rs = RecordsSearch(index='deposits-records')

    res = rs.query(Q('match', basic_info__cadi_id__keyword=cadi_id)) \
        .execute().hits.hits

    if not res:
        raise DepositDoesNotExist
    else:
        uuid = res[0]['_id']
        deposit = CAPDeposit.get_record(uuid)

    return deposit
def get_deposit_by_cadi_id(cadi_id):
    """Return deposit with given cadi id.

    :params str cadi_id: CADI identifier

    :rtype `cap.modules.deposits.api:CAPDeposit`
    """
    rs = RecordsSearch(index='deposits-records')

    res = rs.query(Q('match', basic_info__cadi_id__keyword=cadi_id)) \
        .execute().hits.hits

    if not res:
        raise DepositDoesNotExist
    else:
        uuid = res[0]['_id']
        deposit = CAPDeposit.get_record(uuid)

    return deposit
def synchronize_cadi_entries(limit=None):
    """Add/update CADI info in all cms-analysis syncing with CADI db."""
    parser = HTMLParser()
    entries = get_all_entries_from_cadi()

    def parse_field(field):
        """Escape HTML characters."""
        if isinstance(field, unicode):
            return parser.unescape(parser.unescape(field))
        else:
            return ''

    for entry in entries[:limit]:
        # remove artefact from cadi names
        cadi_id = re.sub('^d', '', entry.get('code', None))

        cadi_info = {
            cap_key: parse_field(entry.get(cadi_key, None))
            for cadi_key, cap_key in CADI_FIELD_TO_CAP_MAP.items()
        }

        try:  # update if already exists
            uuid = get_entry_uuid_by_unique_field(
                'deposits-records-cms-analysis-v0.0.1',
                {'basic_info__cadi_id__keyword': cadi_id}
            )

            deposit = CAPDeposit.get_record(uuid)
            deposit['cadi_info'] = cadi_info
            deposit.commit()

            print('Cadi entry {} updated.'.format(cadi_id))

        except (DepositDoesNotExist, NoResultFound):
            data = construct_cadi_entry(cadi_id, {
                'cadi_info': cadi_info
            })

            deposit = CAPDeposit.create(data=data)
            add_read_permission_for_egroup(deposit, '*****@*****.**')

            print('Cadi entry {} added.'.format(cadi_id))
def download_url(record_id, url):
    """Create new file object and assign it to object version."""
    record = CAPDeposit.get_record(record_id)
    if url.startswith("root://"):
        from xrootdpyfs.xrdfile import XRootDPyFile
        response = XRootDPyFile(url, mode='r-')
        total = response.size
    else:
        try:
            from cap.modules.repoimporter.repo_importer import RepoImporter
            link = RepoImporter.create(url).archive_repository()
            response = requests.get(link, stream=True).raw
            total = int(response.headers.get('Content-Length'))
        except TypeError as exc:
            download_url.retry(exc=exc)
    record.files[url].file.set_contents(
        response,
        default_location=record.files.bucket.location.uri,
        size=total)
    db.session.commit()
def test_add_user_permissions_set_access_object_properly(app, db, users, create_deposit):
    owner, other_user = users['cms_user'], users['cms_user2']
    deposit = create_deposit(owner, 'alice-analysis-v0.0.1')

    assert deposit['_access'] == {
        'deposit-read': {
            'users': [owner.id],
            'roles': []
        },
        'deposit-update': {
            'users': [owner.id],
            'roles': []
        },
        'deposit-admin': {
            'users': [owner.id],
            'roles': []
        }
    }

    deposit._add_user_permissions(other_user,
                                  ['deposit-read',
                                   'deposit-update'],
                                  db.session)

    deposit = Deposit.get_record(deposit.id)

    assert deposit['_access'] == {
        'deposit-read': {
            'users': [owner.id, other_user.id],
            'roles': []
        },
        'deposit-update': {
            'users': [owner.id, other_user.id],
            'roles': []
        },
        'deposit-admin': {
            'users': [owner.id],
            'roles': []
        }
    }
def test_add_user_permissions_set_access_object_properly(
        app, db, users, create_deposit):
    owner, other_user = users['cms_user'], users['cms_user2']
    deposit = create_deposit(owner, 'alice-analysis-v0.0.1')

    assert deposit['_access'] == {
        'deposit-read': {
            'users': [owner.id],
            'roles': []
        },
        'deposit-update': {
            'users': [owner.id],
            'roles': []
        },
        'deposit-admin': {
            'users': [owner.id],
            'roles': []
        }
    }

    deposit._add_user_permissions(other_user,
                                  ['deposit-read', 'deposit-update'],
                                  db.session)

    deposit = Deposit.get_record(deposit.id)

    assert deposit['_access'] == {
        'deposit-read': {
            'users': [owner.id, other_user.id],
            'roles': []
        },
        'deposit-update': {
            'users': [owner.id, other_user.id],
            'roles': []
        },
        'deposit-admin': {
            'users': [owner.id],
            'roles': []
        }
    }
Esempio n. 20
0
def synchronize_cadi_entries(limit=None):
    """Add/update CADI info in all cms-analysis syncing with CADI db."""
    parser = HTMLParser()
    entries = get_all_entries_from_cadi()

    def parse_field(field):
        """Escape HTML characters."""
        if isinstance(field, unicode):
            return parser.unescape(parser.unescape(field))
        else:
            return ''

    for entry in entries[:limit]:
        # remove artefact from cadi names
        cadi_id = re.sub('^d', '', entry.get('code', None))

        cadi_info = {
            cap_key: parse_field(entry.get(cadi_key, None))
            for cadi_key, cap_key in CADI_FIELD_TO_CAP_MAP.items()
        }

        try:  # update if already exists
            uuid = get_entry_uuid_by_unique_field(
                'deposits-records-cms-analysis-v0.0.1',
                {'basic_info__cadi_id__keyword': cadi_id})

            deposit = CAPDeposit.get_record(uuid)
            deposit['cadi_info'] = cadi_info
            deposit.commit()

            print('Cadi entry {} updated.'.format(cadi_id))

        except (DepositDoesNotExist, NoResultFound):
            data = construct_cadi_entry(cadi_id, {'cadi_info': cadi_info})

            deposit = CAPDeposit.create(data=data)
            add_read_permission_for_egroup(deposit, '*****@*****.**')

            print('Cadi entry {} added.'.format(cadi_id))
Esempio n. 21
0
def download_repo_file(record_id,
                       filename,
                       download_url,
                       size=None,
                       auth_headers=None):
    """Download a single file from a git repo under record files."""
    response = requests.get(download_url, stream=True,
                            headers=auth_headers).raw

    response.decode_content = True
    size = size or int(response.headers.get('Content-Length'))

    from cap.modules.deposit.api import CAPDeposit
    record = CAPDeposit.get_record(record_id)

    # temporary workaround, we save empty file, when downloading failed
    # so we can show it in UI (with tag FAILED)
    failed = True if response.status != 200 else False
    if failed:
        print(f'Downloading content from {download_url}'
              f'failed ({response.status}).')

    record.save_file(response, filename, size, failed)
Esempio n. 22
0
def download_repo_file(record_id, host, owner, repo, branch, filepath,
                       source_url, download_url, size, token):
    """Download a single file from a git repo."""
    filename = 'repositories/{}/{}/{}/{}/{}'.format(host, owner, repo, branch,
                                                    filepath)
    headers = {'Authorization': 'token {}'.format(token)} if token else {}

    response = requests.get(download_url, stream=True, headers=headers).raw

    response.decode_content = True
    size = size or int(response.headers.get('Content-Length'))

    from cap.modules.deposit.api import CAPDeposit
    record = CAPDeposit.get_record(record_id)

    # temporary workaround, we save empty file, when downloading failed
    # so we can show it in UI (with tag FAILED)
    failed = True if response.status != 200 else False
    if failed:
        print('Downloading content from {} failed ({}).'.format(
            download_url, response.status))

    record.save_file(response, filename, size, source_url)
def synchronize_cadi_entries(limit=None):
    """Add/update all CADI entries connecting with CADI database."""
    entries = get_entries_from_cadi_db()
    for entry in entries[:limit]:
        # remove artefact from code names
        cadi_id = re.sub('^d', '', entry.get('code', None))

        try:  # update if already exists
            parser = HTMLParser()
            uuid = get_entry_uuid_by_unique_field(
                'deposits-records-cms-analysis-v0.0.1',
                {'basic_info__cadi_id__keyword': cadi_id}
            )

            deposit = CAPDeposit.get_record(uuid)

            if 'cadi_info' not in deposit:
                deposit['cadi_info'] = {}
            for cadi_key, cap_key in CADI_FIELD_TO_CAP_MAP.items():
                # sometimes they store data in HTML format.. need to escape
                # chars
                deposit['cadi_info'][cap_key] = parser.unescape(
                    entry.get(cadi_key, '') or '') or ''
            deposit.commit()

            print('Cadi entry {} updated.'.format(cadi_id))

        except (DepositDoesNotExist, NoResultFound):
            data = construct_cadi_entry(cadi_id, {
                'cadi_info': {v: parser.unescape(entry.get(k, '') or '') or ''
                              for k, v in CADI_FIELD_TO_CAP_MAP.items()}
            })

            deposit = CAPDeposit.create(data=data)
            add_read_permission_for_egroup(deposit, '*****@*****.**')

            print('Cadi entry {} added.'.format(cadi_id))
Esempio n. 24
0
        def _create_deposit(user, schema_name, metadata=None, experiment=None, publish=False):
            """
            Create a new deposit for given user and schema name
            e.g cms-analysis-v0.0.1,
            with minimal metadata defined for this schema type.
            """
            with app.test_request_context():
                # create schema for record
                schema = create_schema('records/{}'.format(schema_name), is_deposit=False,
                                       experiment=experiment)
                if not experiment:
                    schema.add_read_access_to_all()

                # create schema for deposit
                schema = create_schema('deposits/records/{}'.format(schema_name),
                                       experiment=experiment)
                if not experiment:
                    schema.add_read_access_to_all()

                metadata = metadata or minimal_metadata(jsonschemas_host,
                                                        'deposits/records/{}'.format(schema_name))
                login_user(user)
                id_ = uuid4()
                deposit_minter(id_, metadata)
                deposit = Deposit.create(metadata, id_=id_)

            if publish:
                deposit.publish()
                _, record = deposit.fetch_published()
                RecordIndexer().index(record)

                current_search.flush_and_refresh('records')

            current_search.flush_and_refresh(schema.index_name)

            return Deposit.get_record(deposit.id)
    def get_workflows(self, obj):
        deposit = CAPDeposit.get_record(obj['pid'].object_uuid)
        workflows = deposit.model.reana_workflows

        return ReanaWorkflowSchema(many=True).dump(workflows).data
Esempio n. 26
0
def test_create_deposit_with_required_fields_success(client, location, users,
                                                     create_schema,
                                                     auth_headers_for_user,
                                                     json_headers):
    owner = users['cms_user']
    headers = auth_headers_for_user(users['cms_user']) + json_headers
    create_schema('test-analysis',
                  experiment='CMS',
                  deposit_schema={
                      'type': 'object',
                      'required': ['title'],
                      'properties': {
                          'title': {
                              'type': 'string'
                          },
                          'abstract': {
                              'type': 'string'
                          }
                      }
                  })

    resp = client.post('/deposits/',
                       headers=headers,
                       data=json.dumps({
                           '$ana_type': 'test-analysis',
                           'title': 'test'
                       }))

    metadata = RecordMetadata.query.first()
    deposit = CAPDeposit.get_record(metadata.id)
    depid = deposit['_deposit']['id']

    assert resp.status_code == 201
    assert resp.json == {
        'id': depid,
        'type': 'deposit',
        'revision': 0,
        'schema': {
            'fullname': '',
            'name': 'test-analysis',
            'version': '1.0.0'
        },
        'labels': [],
        'files': [],
        'experiment': 'CMS',
        'status': 'draft',
        'is_owner': True,
        'created_by': owner.email,
        'created': metadata.created.strftime('%Y-%m-%dT%H:%M:%S.%f+00:00'),
        'updated': metadata.updated.strftime('%Y-%m-%dT%H:%M:%S.%f+00:00'),
        'metadata': {
            'title': 'test'
        },
        'access': {
            'deposit-admin': {
                'roles': [],
                'users': [owner.email]
            },
            'deposit-update': {
                'roles': [],
                'users': [owner.email]
            },
            'deposit-read': {
                'roles': [],
                'users': [owner.email]
            }
        },
        'links': {
            'bucket':
            f'http://analysispreservation.cern.ch/api/files/{deposit.files.bucket}',
            'clone':
            f'http://analysispreservation.cern.ch/api/deposits/{depid}/actions/clone',
            'discard':
            f'http://analysispreservation.cern.ch/api/deposits/{depid}/actions/discard',
            'disconnect_webhook':
            f'http://analysispreservation.cern.ch/api/deposits/{depid}/actions/disconnect_webhook',
            'edit':
            f'http://analysispreservation.cern.ch/api/deposits/{depid}/actions/edit',
            'files':
            f'http://analysispreservation.cern.ch/api/deposits/{depid}/files',
            'html':
            f'http://analysispreservation.cern.ch/drafts/{depid}',
            'permissions':
            f'http://analysispreservation.cern.ch/api/deposits/{depid}/actions/permissions',
            'publish':
            f'http://analysispreservation.cern.ch/api/deposits/{depid}/actions/publish',
            'self':
            f'http://analysispreservation.cern.ch/api/deposits/{depid}',
            'upload':
            f'http://analysispreservation.cern.ch/api/deposits/{depid}/actions/upload'
        }
    }
Esempio n. 27
0
def test_create_deposit_set_fields_correctly(client, location, users,
                                             create_schema,
                                             auth_headers_for_user,
                                             json_headers):
    owner = users['cms_user']
    schema = create_schema('test-analysis',
                           experiment='CMS',
                           fullname='CMS Schema')
    metadata = {
        '$schema':
        'https://analysispreservation.cern.ch/schemas/deposits/records/test-analysis-v1.0.0.json',
        'basic_info': {
            'analysis_number': 'dream_team'
        }
    }

    resp = client.post('/deposits/',
                       headers=auth_headers_for_user(owner) + json_headers,
                       data=json.dumps(metadata))

    metadata = RecordMetadata.query.first()
    deposit = CAPDeposit.get_record(metadata.id)
    depid = deposit['_deposit']['id']

    assert resp.status_code == 201
    assert resp.json == {
        'id': depid,
        'type': 'deposit',
        'revision': 0,
        'schema': {
            'fullname': 'CMS Schema',
            'name': 'test-analysis',
            'version': '1.0.0'
        },
        'labels': [],
        'experiment': 'CMS',
        'status': 'draft',
        'created_by': owner.email,
        'created': metadata.created.strftime('%Y-%m-%dT%H:%M:%S.%f+00:00'),
        'updated': metadata.updated.strftime('%Y-%m-%dT%H:%M:%S.%f+00:00'),
        'metadata': {
            'basic_info': {
                'analysis_number': 'dream_team'
            }
        },
        'files': [],
        'access': {
            'deposit-admin': {
                'roles': [],
                'users': [owner.email]
            },
            'deposit-update': {
                'roles': [],
                'users': [owner.email]
            },
            'deposit-read': {
                'roles': [],
                'users': [owner.email]
            }
        },
        'is_owner': True,
        'links': {
            'bucket':
            'http://analysispreservation.cern.ch/api/files/{}'.format(
                deposit.files.bucket),
            'clone':
            'http://analysispreservation.cern.ch/api/deposits/{}/actions/clone'
            .format(depid),
            'discard':
            'http://analysispreservation.cern.ch/api/deposits/{}/actions/discard'
            .format(depid),
            'disconnect_webhook':
            'http://analysispreservation.cern.ch/api/deposits/{}/actions/disconnect_webhook'
            .format(depid),
            'edit':
            'http://analysispreservation.cern.ch/api/deposits/{}/actions/edit'.
            format(depid),
            'files':
            'http://analysispreservation.cern.ch/api/deposits/{}/files'.format(
                depid),
            'html':
            'http://analysispreservation.cern.ch/drafts/{}'.format(depid),
            'permissions':
            'http://analysispreservation.cern.ch/api/deposits/{}/actions/permissions'
            .format(depid),
            'publish':
            'http://analysispreservation.cern.ch/api/deposits/{}/actions/publish'
            .format(depid),
            'self':
            'http://analysispreservation.cern.ch/api/deposits/{}'.format(
                depid),
            'upload':
            'http://analysispreservation.cern.ch/api/deposits/{}/actions/upload'
            .format(depid)
        }
    }
def test_files_workflow(client, users, auth_headers_for_user, create_deposit):
    owner = users['cms_user']
    member_of_collaboration = users['cms_user2']
    non_member_of_collaboration = users['lhcb_user2']
    deposit = create_deposit(owner, 'test-analysis-v0.0.1', experiment='CMS')
    pid = deposit['_deposit']['id']
    auth_headers = auth_headers_for_user(owner)

    deposit_bucket = deposit.files.bucket

    # deposit created, bucket is unlocked
    assert deposit_bucket.locked is False

    # user can add new files
    resp = client.put('/files/{}/file_1.txt'.format(deposit_bucket),
                      input_stream=BytesIO(b'Original Hello world!'),
                      headers=auth_headers)

    assert resp.status_code == 200

    # and access them
    resp = client.get('/files/{}/file_1.txt'.format(deposit_bucket),
                      headers=auth_headers)

    assert resp.status_code == 200
    assert resp.data == b'Original Hello world!'

    # member of collaboration cannot access file
    resp = client.get('/files/{}/file_1.txt'.format(deposit_bucket),
                      headers=auth_headers_for_user(member_of_collaboration))

    assert resp.status_code == 404  # TOFIX shouldnt be 403?

    # user can update and delete  a file
    resp = client.put('/files/{}/file_1.txt'.format(deposit_bucket),
                      input_stream=BytesIO(b'Updated Hello world!'),
                      headers=auth_headers)

    assert resp.status_code == 200

    resp = client.get('/files/{}/file_1.txt'.format(deposit_bucket),
                      headers=auth_headers)

    assert resp.status_code == 200
    assert resp.data == b'Updated Hello world!'

    resp = client.delete('/files/{}/file_1.txt'.format(deposit_bucket),
                         headers=auth_headers)

    assert resp.status_code == 204

    resp = client.put('/files/{}/file_1.txt'.format(deposit_bucket),
                      input_stream=BytesIO(b'Original Hello world!'),
                      headers=auth_headers)

    assert resp.status_code == 200

    # when user publishes a deposit, deposit_bucket is locked
    resp = client.post('/deposits/{}/actions/publish'.format(pid),
                       headers=auth_headers)

    assert resp.status_code == 202

    deposit = CAPDeposit.get_record(deposit.id)

    # deposit_bucket is locked after deposit was published
    assert deposit_bucket.locked is True

    # record  has a differrent bucket, that is also locked
    _, record = deposit.fetch_published()
    record_bucket = record.files.bucket
    assert record_bucket != deposit_bucket
    assert record_bucket.locked is True

    # user and member of collaboration can access file for the published record
    resp = client.get('/files/{}/file_1.txt'.format(record_bucket),
                      headers=auth_headers)

    assert resp.status_code == 200

    resp = client.get('/files/{}/file_1.txt'.format(record_bucket),
                      headers=auth_headers_for_user(member_of_collaboration))

    assert resp.status_code == 200

    # user outside of collaboration cant access file for the published record
    resp = client.get(
        '/files/{}/file_1.txt'.format(record_bucket),
        headers=auth_headers_for_user(non_member_of_collaboration))

    assert resp.status_code == 404

    resp = client.get('/files/{}/file_1.txt'.format(record_bucket),
                      headers=auth_headers_for_user(member_of_collaboration))

    assert resp.status_code == 200

    # user cannot add/update/delete a file for deposit
    resp = client.put('/files/{}/file_1.txt'.format(deposit_bucket),
                      input_stream=BytesIO(b'Try another Hello world!'),
                      headers=auth_headers)

    assert resp.status_code == 403

    resp = client.delete('/files/{}/file_1.txt'.format(deposit_bucket),
                         headers=auth_headers)

    assert resp.status_code == 403

    resp = client.put('/files/{}/file_2.txt'.format(deposit_bucket),
                      input_stream=BytesIO(b'Try another Hello world!'),
                      headers=auth_headers)

    assert resp.status_code == 403

    # unless he decides to edit deposit again
    resp = client.post('/deposits/{}/actions/edit'.format(pid),
                       headers=auth_headers)

    assert resp.status_code == 201
    assert deposit_bucket.locked is False

    # after edit, deposit deposit_bucket is unlocked again,
    # so he can add new files
    resp = client.put('/files/{}/file_2.txt'.format(deposit_bucket),
                      input_stream=BytesIO(b'Hello new world!'),
                      headers=auth_headers)

    assert resp.status_code == 200

    resp = client.get('/files/{}/file_2.txt'.format(deposit_bucket),
                      headers=auth_headers)

    assert resp.status_code == 200
    assert resp.data == b'Hello new world!'

    # user can upload a new version of file
    resp = client.put('/files/{}/file_1.txt'.format(deposit_bucket),
                      input_stream=BytesIO(b'After edit Hello world!'),
                      headers=auth_headers)

    assert resp.status_code == 200

    resp = client.get('/files/{}/file_1.txt'.format(deposit_bucket),
                      headers=auth_headers)
    assert resp.data == b'After edit Hello world!'

    # even delete it
    resp = client.delete('/files/{}/file_1.txt'.format(deposit_bucket),
                         headers=auth_headers)

    assert resp.status_code == 204

    # user can upload a new files
    resp = client.put('/files/{}/file_3.txt'.format(deposit_bucket),
                      input_stream=BytesIO(b'Hello world!'),
                      headers=auth_headers)

    assert resp.status_code == 200

    # original file with this name, referenced by bucket of published record,
    # remains unchanged
    resp = client.get('/files/{}/file_1.txt'.format(record_bucket),
                      headers=auth_headers)
    assert resp.data == b'Original Hello world!'

    # user cannot modify(add, update, delete) a record bucket
    resp = client.put('/files/{}/file_1.txt'.format(record_bucket),
                      input_stream=BytesIO(b'Updated Updated Hello world!'),
                      headers=auth_headers)

    assert resp.status_code == 403

    resp = client.delete('/files/{}/file_1.txt'.format(record_bucket),
                         headers=auth_headers)

    assert resp.status_code == 403

    resp = client.put('/files/{}/file_2.txt'.format(record_bucket),
                      input_stream=BytesIO(b'Hello new world!'),
                      headers=auth_headers)

    assert resp.status_code == 403
Esempio n. 29
0
 def can_user_update(self, obj):
     deposit = CAPDeposit.get_record(obj['pid'].object_uuid)
     return UpdateRecordPermission(deposit).can()
Esempio n. 30
0
 def can_user_admin(self, obj):
     deposit = CAPDeposit.get_record(obj['pid'].object_uuid)
     return AdminRecordPermission(deposit).can()
Esempio n. 31
0
    def get_webhooks(self, obj):
        deposit = CAPDeposit.get_record(obj['pid'].object_uuid)
        webhooks = deposit.model.webhooks

        return GitWebhookSubscriberSchema(many=True).dump(webhooks).data
    def get_repositories(self, obj):
        deposit = CAPDeposit.get_record(obj['pid'].object_uuid)
        webhooks = deposit.model.webhooks

        return DepositRepositoriesSchema(many=True).dump(webhooks).data