def test_record_delete(mocker, app, db, users, deposit, deposit_file): """Delete the record with a single version.""" dc_mock = mocker.patch( 'invenio_pidstore.providers.datacite.DataCiteMDSClient') deposit = publish_and_expunge(db, deposit) recid, record = deposit.fetch_published() # Stash a copy of record metadata for later rec = deepcopy(record) record_uuid = str(record.id) assert dc_mock().metadata_delete.call_count == 0 # users[0] is not an Admin but it doesn't matter in this case. delete_record(record.id, 'spam', users[0]['id']) # Make sure all PIDs are deleted # TODO: oai PID is left registered # assert PID.get('oai', rec['_oai']['id']) == PIDStatus.DELETED assert PID.get('doi', rec['doi']).status == PIDStatus.DELETED assert PID.get('doi', rec['conceptdoi']).status == PIDStatus.DELETED assert PID.get('recid', rec['recid']).status == PIDStatus.DELETED assert PID.get('recid', rec['conceptrecid']).status == PIDStatus.DELETED assert PID.get('depid', rec['_deposit']['id']).status == PIDStatus.DELETED assert dc_mock().metadata_delete.call_count == 2 dc_mock().metadata_delete.assert_any_call('10.5072/zenodo.1') dc_mock().metadata_delete.assert_any_call('10.5072/zenodo.2') record = Record.get_record(record_uuid) assert record['removed_by'] == users[0]['id'] assert record['removal_reason'] == 'Spam record, removed by Zenodo staff.'
def test_record_delete_legacy(dc_mock, app, db, users, deposit, deposit_file): """Delete the non-versioned record.""" deposit = publish_and_expunge(db, deposit) recid, record = deposit.fetch_published() # 'Simulate' a non-versioned record by removing 'conceptdoi' key del deposit['conceptdoi'] del record['conceptdoi'] deposit.commit() record.commit() db.session.commit() # Stash a copy of record metadata for later rec = deepcopy(record) record_uuid = str(record.id) assert dc_mock().metadata_delete.call_count == 0 # users[0] is not an Admin but it doesn't matter in this case. delete_record(record.id, 'spam', users[0]['id']) # Make sure all PIDs are deleted # TODO: oai PID is left registered # assert PID.get('oai', rec['_oai']['id']) == PIDStatus.DELETED assert PID.get('doi', rec['doi']).status == PIDStatus.DELETED assert PID.get('recid', rec['recid']).status == PIDStatus.DELETED assert PID.get('recid', rec['conceptrecid']).status == PIDStatus.DELETED assert PID.get('depid', rec['_deposit']['id']).status == PIDStatus.DELETED assert dc_mock().metadata_delete.call_count == 1 dc_mock().metadata_delete.assert_any_call('10.5072/zenodo.2') record = Record.get_record(record_uuid) assert record['removed_by'] == users[0]['id'] assert record['removal_reason'] == 'Spam record, removed by Zenodo staff.'
def test_record_delete_v2(mocker, app, db, users, deposit, deposit_file): """Delete a record (only last version) with multiple versions.""" dc_mock = mocker.patch( 'invenio_pidstore.providers.datacite.DataCiteMDSClient') deposit_v1 = publish_and_expunge(db, deposit) recid_v1, record_v1 = deposit.fetch_published() recid_v1_value = recid_v1.pid_value deposit_v1.newversion() recid_v1, record_v1 = record_resolver.resolve(recid_v1_value) # Stash a copy of v1 for later rec1 = deepcopy(record_v1) pv = PIDVersioning(child=recid_v1) depid_v2 = pv.draft_child_deposit deposit_v2 = ZenodoDeposit.get_record(depid_v2.get_assigned_object()) deposit_v2.files['file.txt'] = BytesIO(b('file1')) deposit_v2 = publish_and_expunge(db, deposit_v2) recid_v2, record_v2 = deposit_v2.fetch_published() # Stash a copy of v2 for later rec2 = deepcopy(record_v2) rec2_id = str(record_v2.id) assert dc_mock().metadata_delete.call_count == 0 # Remove the first version delete_record(rec2_id, 'spam', users[0]['id']) # Make sure all PIDs are deleted assert PID.get('doi', rec2['doi']).status == PIDStatus.DELETED assert PID.get('recid', rec2['recid']).status == PIDStatus.DELETED assert PID.get('depid', rec2['_deposit']['id']).status == PIDStatus.DELETED # Concept DOI should be left registered assert PID.get('doi', rec2['conceptdoi']).status == PIDStatus.REGISTERED # Make sure conceptrecid is redirecting to v1 crecid = PID.get('recid', rec2['conceptrecid']) assert crecid.status == PIDStatus.REDIRECTED assert crecid.get_redirect() == PID.get('recid', rec1['recid']) # Make sure the v1 PIDs are kept intact assert PID.get('oai', rec1['_oai']['id']).status == PIDStatus.REGISTERED assert PID.get('doi', rec1['doi']).status == PIDStatus.REGISTERED assert PID.get('recid', rec1['recid']).status == PIDStatus.REGISTERED assert PID.get('depid', rec1['_deposit']['id']).status == \ PIDStatus.REGISTERED # Only the v1 DOI should be deleted assert dc_mock().doi_post.call_count == 2 assert dc_mock().doi_post.has_any_call('10.5072/zenodo.2') assert dc_mock().doi_post.has_any_call('10.5072/zenodo.1') assert dc_mock().metadata_delete.call_count == 1 dc_mock().metadata_delete.assert_any_call('10.5072/zenodo.3') record = Record.get_record(rec2_id) assert record['removed_by'] == users[0]['id'] assert record['removal_reason'] == 'Spam record, removed by Zenodo staff.'
def delete(user_id): """Delete spam.""" # Only admin can access this view if not Permission(ActionNeed('admin-access')).can(): abort(403) user = User.query.get(user_id) deleteform = DeleteSpamForm() communities = Community.query.filter_by(id_user=user.id) rs = RecordsSearch(index='records').query( Q('query_string', query="owners: {0}".format(user.id))) rec_count = rs.count() ctx = { 'user': user, 'form': deleteform, 'is_new': False, 'communities': communities, 'rec_count': rec_count, } if deleteform.validate_on_submit(): if deleteform.remove_all_communities.data: for c in communities: if not c.deleted_at: if not c.description.startswith('--SPAM--'): c.description = '--SPAM--' + c.description if c.oaiset: db.session.delete(c.oaiset) c.delete() db.session.commit() if deleteform.deactivate_user.data: _datastore.deactivate_user(user) db.session.commit() # delete_record function commits the session internally # for each deleted record if deleteform.remove_all_records.data: for r in rs.scan(): delete_record(r.meta.id, 'spam', int(current_user.get_id())) flash("Spam removed", category='success') return redirect(url_for('.delete', user_id=user.id)) else: records = islice(rs.scan(), 10) ctx.update(records=records) return render_template('zenodo_spam/delete.html', **ctx)
def delete(user_id): """Delete spam.""" # Only admin can access this view if not Permission(ActionNeed('admin-access')).can(): abort(403) user = User.query.get(user_id) deleteform = DeleteSpamForm() communities = Community.query.filter_by(id_user=user.id) rs = RecordsSearch(index='records').query( Q('query_string', query="owners: {0}".format(user.id))) rec_count = rs.count() ctx = { 'user': user, 'form': deleteform, 'is_new': False, 'communities': communities, 'rec_count': rec_count, } if deleteform.validate_on_submit(): if deleteform.remove_all_communities.data: for c in communities: if not c.deleted_at: if not c.description.startswith('--SPAM--'): c.description = '--SPAM--' + c.description if c.oaiset: db.session.delete(c.oaiset) c.delete() db.session.commit() if deleteform.deactivate_user.data: _datastore.deactivate_user(user) db.session.commit() # delete_record function commits the session internally # for each deleted record if deleteform.remove_all_records.data: for r in rs.scan(): delete_record(r.meta.id, 'spam', int(current_user.get_id())) flash("Spam removed", category='success') return redirect(url_for('.delete', user_id=user.id)) else: records = islice(rs.scan(), 10) ctx.update(records=records) return render_template('zenodo_spam/delete.html', **ctx)
def delete(pid=None, record=None, depid=None, deposit=None): """Delete a record.""" # View disabled until properly implemented and tested. try: doi = PersistentIdentifier.get('doi', record['doi']) except PIDDoesNotExistError: doi = None owners = User.query.filter(User.id.in_(record.get('owners', []))).all() pids = [pid, depid, doi] if 'conceptdoi' in record: conceptdoi = PersistentIdentifier.get('doi', record['conceptdoi']) pids.append(conceptdoi) else: conceptdoi = None if 'conceptrecid' in record: conceptrecid = PersistentIdentifier.get('recid', record['conceptrecid']) pids.append(conceptrecid) else: conceptrecid = None form = RecordDeleteForm() form.standard_reason.choices = current_app.config['ZENODO_REMOVAL_REASONS'] if form.validate_on_submit(): reason = form.reason.data or dict( current_app.config['ZENODO_REMOVAL_REASONS'] )[form.standard_reason.data] delete_record(record.id, reason, int(current_user.get_id())) flash( _('Record %(recid)s and associated objects successfully deleted.', recid=pid.pid_value), category='success' ) return redirect(url_for('zenodo_frontpage.index')) return render_template( 'zenodo_deposit/delete.html', form=form, owners=owners, pid=pid, pids=pids, record=record, deposit=deposit, )
def delete(pid=None, record=None, depid=None, deposit=None): """Delete a record.""" # View disabled until properly implemented and tested. try: doi = PersistentIdentifier.get('doi', record['doi']) except PIDDoesNotExistError: doi = None owners = User.query.filter(User.id.in_(record.get('owners', []))).all() pids = [pid, depid, doi] if 'conceptdoi' in record: conceptdoi = PersistentIdentifier.get('doi', record['conceptdoi']) pids.append(conceptdoi) else: conceptdoi = None if 'conceptrecid' in record: conceptrecid = PersistentIdentifier.get('recid', record['conceptrecid']) pids.append(conceptrecid) else: conceptrecid = None form = RecordDeleteForm() form.standard_reason.choices = current_app.config['ZENODO_REMOVAL_REASONS'] if form.validate_on_submit(): reason = form.reason.data or dict( current_app.config['ZENODO_REMOVAL_REASONS'] )[form.standard_reason.data] delete_record(record.id, reason, int(current_user.get_id())) flash( _('Record %(recid)s and associated objects successfully deleted.', recid=pid.pid_value), category='success' ) return redirect(url_for('zenodo_frontpage.index')) return render_template( 'zenodo_deposit/delete.html', form=form, owners=owners, pid=pid, pids=pids, record=record, deposit=deposit, )