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))
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()
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
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())
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
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
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
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)
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': [] } }
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_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)
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))
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
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' } }
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
def can_user_update(self, obj): deposit = CAPDeposit.get_record(obj['pid'].object_uuid) return UpdateRecordPermission(deposit).can()
def can_user_admin(self, obj): deposit = CAPDeposit.get_record(obj['pid'].object_uuid) return AdminRecordPermission(deposit).can()
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