def test_branched_from_must_be_a_node_or_draft_node(self): with pytest.raises(DraftRegistrationStateError): DraftRegistration.create_from_node( user=user, node=factories.RegistrationFactory(), schema=factories.get_default_metaschema()) with pytest.raises(DraftRegistrationStateError): DraftRegistration.create_from_node( user=user, node=factories.CollectionFactory(), schema=factories.get_default_metaschema())
def make_draft_registration(node=None): draft_registration = DraftRegistration.create_from_node( user=user, schema=get_default_metaschema(), data={}, node=node if node else None ) user.affiliated_institutions.add(institution) draft_registration.set_title(title, Auth(user)) draft_registration.set_description(description, Auth(user)) draft_registration.category = category draft_registration.add_contributor(write_contrib, permissions=WRITE) draft_registration.set_node_license( { 'id': license.license_id, 'year': NEW_YEAR, 'copyrightHolders': COPYLEFT_HOLDERS }, auth=Auth(user), save=True ) draft_registration.add_tag('savanna', Auth(user)) draft_registration.add_tag('taxonomy', Auth(user)) draft_registration.set_subjects([[subject._id]], auth=Auth(draft_registration.creator)) draft_registration.affiliated_institutions.add(institution) draft_registration.save() return draft_registration
def test_can_view_property(self, user): project = factories.ProjectFactory(creator=user) write_contrib = factories.UserFactory() read_contrib = factories.UserFactory() non_contrib = factories.UserFactory() draft = DraftRegistration.create_from_node( user=user, node=project, schema=factories.get_default_metaschema() ) project.add_contributor(non_contrib, ADMIN, save=True) draft.add_contributor(write_contrib, WRITE, save=True) draft.add_contributor(read_contrib, READ, save=True) assert draft.get_permissions(user) == [READ, WRITE, ADMIN] assert draft.get_permissions(write_contrib) == [READ, WRITE] assert draft.get_permissions(read_contrib) == [READ] assert draft.can_view(Auth(user)) is True assert draft.can_view(Auth(write_contrib)) is True assert draft.can_view(Auth(read_contrib)) is True assert draft.can_view(Auth(non_contrib)) is False
def create(self, validated_data): node = validated_data.pop('node') initiator = validated_data.pop('initiator') metadata = validated_data.pop('registration_metadata', None) schema_id = validated_data.pop('registration_schema').get('_id') schema = get_object_or_error(MetaSchema, schema_id, self.context['request']) if schema.schema_version != LATEST_SCHEMA_VERSION or not schema.active: raise exceptions.ValidationError( 'Registration supplement must be an active schema.') draft = DraftRegistration.create_from_node(node=node, user=initiator, schema=schema) reviewer = is_prereg_admin_not_project_admin(self.context['request'], draft) if metadata: try: # Required fields are only required when creating the actual registration, not updating the draft. draft.validate_metadata(metadata=metadata, reviewer=reviewer, required_fields=False) except ValidationError as e: raise exceptions.ValidationError(e.message) draft.update_metadata(metadata) draft.save() return draft
def new_draft_registration(auth, node, *args, **kwargs): """Create a new draft registration for the node :return: Redirect to the new draft's edit page :rtype: flask.redirect :raises: HTTPError """ if node.is_registration: raise HTTPError(http.FORBIDDEN, data={ 'message_short': "Can't create draft", 'message_long': 'Creating draft registrations on registered projects is not allowed.' }) data = request.values schema_name = data.get('schema_name') if not schema_name: raise HTTPError( http.BAD_REQUEST, data={ 'message_short': 'Must specify a schema_name', 'message_long': 'Please specify a schema_name' } ) schema_version = data.get('schema_version', 2) meta_schema = get_schema_or_fail(schema_name, int(schema_version)) draft = DraftRegistration.create_from_node( node, user=auth.user, schema=meta_schema, data={} ) return redirect(node.web_url_for('edit_draft_registration_page', draft_id=draft._id, _guid=True))
def new_draft_registration(auth, node, *args, **kwargs): """Create a new draft registration for the node :return: Redirect to the new draft's edit page :rtype: flask.redirect :raises: HTTPError """ if node.is_registration: raise HTTPError(http.FORBIDDEN, data={ 'message_short': "Can't create draft", 'message_long': 'Creating draft registrations on registered projects is not allowed.' }) data = request.values schema_name = data.get('schema_name') if not schema_name: raise HTTPError( http.BAD_REQUEST, data={ 'message_short': 'Must specify a schema_name', 'message_long': 'Please specify a schema_name' } ) schema_version = data.get('schema_version', 2) meta_schema = get_schema_or_fail(Q(name=schema_name, schema_version=int(schema_version))) draft = DraftRegistration.create_from_node( node, user=auth.user, schema=meta_schema, data={} ) return redirect(node.web_url_for('edit_draft_registration_page', draft_id=draft._id))
def test_create_draft_registration_without_node(self, user): data = {'some': 'data'} draft = DraftRegistration.create_from_node( user=user, schema=get_default_metaschema(), data=data, ) assert draft.title == 'Untitled' assert draft.branched_from.title == 'Untitled' assert draft.branched_from.type == 'osf.draftnode' assert draft.branched_from.creator == user assert len(draft.logs.all()) == 0
def test_create_from_node(self): proj = NodeFactory() user = proj.creator schema = MetaSchema.objects.first() data = {'some': 'data'} draft = DraftRegistration.create_from_node( proj, user=user, schema=schema, data=data, ) assert user == draft.initiator assert schema == draft.registration_schema assert data == draft.registration_metadata assert proj == draft.branched_from
def bulk_upload_create_draft_registration(auth, initiator, schema, node, data, provider, row, title, external_id): """Create a draft registration from one registration row. """ draft = None try: draft = DraftRegistration.create_from_node( initiator, schema, node=node, data=data, provider=provider, ) # Remove all contributors except the initiator if created from an existing node if node: # Temporarily make initiator contributor visible so that removal of the others can succeed. initiator_contributor = draft.contributor_set.get(user=initiator) if not initiator_contributor.visible: initiator_contributor.visible = True initiator_contributor.save() contributor_set = draft.contributor_set.all() for contributor in contributor_set: if initiator != contributor.user: is_removed = draft.remove_contributor(contributor, auth) assert is_removed, 'Removal of an non-initiator contributor from the draft has failed' draft.save() assert len(draft.contributor_set.all( )) == 1, 'Draft should only have one contributor upon creation.' # Remove the initiator from the citation list initiator_contributor = draft.contributor_set.get(user=initiator) initiator_contributor.visible = False initiator_contributor.save() # Relate the draft to the row row.draft_registration = draft row.save() except Exception as e: # If the draft has been created already but failure happens before it is related to the registration row, # provide the draft id to the exception object for the caller to delete it after the exception is caught. draft_id = draft.id if draft else None raise RegistrationBulkCreationRowError( row.upload.id, row.id, title, external_id, draft_id=draft_id, error=repr(e), ) return draft
def _create(cls, *args, **kwargs): branched_from = kwargs.get('branched_from') initiator = kwargs.get('initiator') registration_schema = kwargs.get('registration_schema') registration_metadata = kwargs.get('registration_metadata') if not branched_from: project_params = {} if initiator: project_params['creator'] = initiator branched_from = ProjectFactory(**project_params) initiator = branched_from.creator registration_schema = registration_schema or MetaSchema.find()[0] registration_metadata = registration_metadata or {} draft = DraftRegistration.create_from_node( branched_from, user=initiator, schema=registration_schema, data=registration_metadata, ) return draft
def test_create_from_node_draft_node(self, user): draft = DraftRegistration.create_from_node( user=user, schema=factories.get_default_metaschema(), ) assert draft.title == 'Untitled' assert draft.description == '' assert draft.category == '' assert user in draft.contributors.all() assert len(draft.contributors.all()) == 1 assert draft.get_permissions(user) == [READ, WRITE, ADMIN] assert draft.node_license is None draft_tags = draft.tags.values_list('name', flat=True) assert len(draft_tags) == 0 assert draft.subjects.count() == 0 assert draft.affiliated_institutions.count() == 0
def create(self, validated_data): node = validated_data.pop('node') initiator = validated_data.pop('initiator') metadata = validated_data.pop('registration_metadata', None) schema_id = validated_data.pop('registration_schema').get('_id') schema = get_object_or_error(MetaSchema, schema_id) if schema.schema_version != LATEST_SCHEMA_VERSION or not schema.active: raise exceptions.ValidationError('Registration supplement must be an active schema.') draft = DraftRegistration.create_from_node(node=node, user=initiator, schema=schema) reviewer = is_prereg_admin_not_project_admin(self.context['request'], draft) if metadata: try: # Required fields are only required when creating the actual registration, not updating the draft. draft.validate_metadata(metadata=metadata, reviewer=reviewer, required_fields=False) except ValidationError as e: raise exceptions.ValidationError(e.message) draft.update_metadata(metadata) draft.save() return draft
def main(guid, creator_username): egap_schema = ensure_egap_schema() creator, creator_auth = get_creator_auth_header(creator_username) egap_assets_path = get_egap_assets(guid, creator_auth) # __MACOSX is a hidden file created by the os when zipping directory_list = [ directory for directory in os.listdir(egap_assets_path) if directory not in ('egap_assets.zip', '__MACOSX') and not directory.startswith('.') ] for egap_project_dir in directory_list: logger.info('Attempting to import the follow directory: {}'.format( egap_project_dir)) # Node Creation try: node = create_node_from_project_json(egap_assets_path, egap_project_dir, creator=creator) except Exception as err: logger.error( 'There was an error attempting to create a node from the ' '{} directory. Attempting to rollback node and contributor creation' .format(egap_project_dir)) logger.error(str(err)) try: rollback_node_from_project_json(egap_assets_path, egap_project_dir, creator=creator) except Exception as err: logger.error(str(err)) continue # Node File Upload non_anon_files = os.path.join(egap_assets_path, egap_project_dir, 'data', 'nonanonymous') non_anon_metadata = recursive_upload(creator_auth, node, non_anon_files) anon_files = os.path.join(egap_assets_path, egap_project_dir, 'data', 'anonymous') if os.path.isdir(anon_files): anon_metadata = recursive_upload(creator_auth, node, anon_files) else: anon_metadata = {} # DraftRegistration Metadata Handling with open( os.path.join(egap_assets_path, egap_project_dir, 'registration-schema.json'), 'r') as fp: registration_metadata = json.load(fp) # add selectedFileName Just so filenames are listed in the UI for data in non_anon_metadata: data['selectedFileName'] = data['data']['attributes']['name'] for data in anon_metadata: data['selectedFileName'] = data['data']['attributes']['name'] non_anon_titles = ', '.join( [data['data']['attributes']['name'] for data in non_anon_metadata]) registration_metadata['q37'] = { 'comments': [], 'extra': non_anon_metadata, 'value': non_anon_titles } anon_titles = ', '.join( [data['data']['attributes']['name'] for data in anon_metadata]) registration_metadata['q38'] = { 'comments': [], 'extra': anon_metadata, 'value': anon_titles } # DraftRegistration Creation draft_registration = DraftRegistration.create_from_node( node, user=creator, schema=egap_schema, data=registration_metadata, ) # Registration Creation logger.info( 'Attempting to create a Registration for Project {}'.format( node._id)) # Retrieve EGAP registration date and potential embargo go-public date if registration_metadata.get('q4'): egap_registration_date_string = registration_metadata['q4'][ 'value'] egap_registration_date = dt.strptime( egap_registration_date_string, '%m/%d/%Y - %H:%M').replace(tzinfo=pytz.UTC) else: logger.error( 'DraftRegistration associated with Project {} ' 'does not have a valid registration date in registration_metadata' .format(node._id)) continue if registration_metadata.get('q12'): if bool(registration_metadata['q12'].get('value')): egap_embargo_public_date_string = registration_metadata['q12'][ 'value'] egap_embargo_public_date = dt.strptime( egap_embargo_public_date_string, '%m/%d/%y').replace(tzinfo=pytz.UTC) else: egap_embargo_public_date = None else: egap_embargo_public_date = None sanction_type = 'RegistrationApproval' if egap_embargo_public_date and (egap_embargo_public_date > dt.today().replace(tzinfo=pytz.UTC)): sanction_type = 'Embargo' logger.info('Attempting to register {} silently'.format(node._id)) try: register_silently(draft_registration, Auth(creator), sanction_type, egap_registration_date, egap_embargo_public_date) except Exception as err: logger.error( 'Unexpected error raised when attempting to silently register ' 'project {}. Continuing...'.format(node._id)) logger.info(str(err)) continue # Update contributors on project to Admin contributors = node.contributor_set.all() for contributor in contributors: if contributor.user == creator: pass else: node.update_contributor(contributor.user, permission=ADMIN, visible=True, auth=Auth(creator), save=True) shutil.rmtree(egap_assets_path)
def main(guid, creator_username): egap_schema = ensure_egap_schema() creator, creator_auth = get_creator_auth_header(creator_username) egap_assets_path = get_egap_assets(guid, creator_auth) # __MACOSX is a hidden file created by the os when zipping directory_list = [ directory for directory in os.listdir(egap_assets_path) if directory not in ('egap_assets.zip', '__MACOSX') ] for epag_project_dir in directory_list: node = create_node_from_project_json(egap_assets_path, epag_project_dir, creator=creator) non_anon_files = os.path.join(egap_assets_path, epag_project_dir, 'data', 'nonanonymous') non_anon_metadata = recursive_upload(creator_auth, node, non_anon_files) anon_files = os.path.join(egap_assets_path, epag_project_dir, 'data', 'anonymous') if os.path.isdir(anon_files): anon_metadata = recursive_upload(creator_auth, node, anon_files) else: anon_metadata = {} with open( os.path.join(egap_assets_path, epag_project_dir, 'registration-schema.json'), 'r') as fp: registration_metadata = json.load(fp) # add selectedFileName Just so filenames are listed in the UI for data in non_anon_metadata: data['selectedFileName'] = data['data']['attributes']['name'] for data in anon_metadata: data['selectedFileName'] = data['data']['attributes']['name'] non_anon_titles = ', '.join( [data['data']['attributes']['name'] for data in non_anon_metadata]) registration_metadata['q37'] = { 'comments': [], 'extra': non_anon_metadata, 'value': non_anon_titles } anon_titles = ', '.join( [data['data']['attributes']['name'] for data in anon_metadata]) registration_metadata['q38'] = { 'comments': [], 'extra': anon_metadata, 'value': anon_titles } DraftRegistration.create_from_node( node, user=creator, schema=egap_schema, data=registration_metadata, ) shutil.rmtree(egap_assets_path)
def test_create_from_node_existing(self, user): node = factories.ProjectFactory(creator=user) member = factories.AuthUserFactory() osf_group = factories.OSFGroupFactory(creator=user) osf_group.make_member(member, auth=Auth(user)) node.add_osf_group(osf_group, ADMIN) write_contrib = factories.AuthUserFactory() subject = factories.SubjectFactory() institution = factories.InstitutionFactory() user.affiliated_institutions.add(institution) title = 'A Study of Elephants' description = 'Loxodonta africana' category = 'Methods and Materials' node.set_title(title, Auth(user)) node.set_description(description, Auth(user)) node.category = category node.add_contributor(write_contrib, permissions=WRITE) GPL3 = NodeLicense.objects.get(license_id='GPL3') NEW_YEAR = '2014' COPYLEFT_HOLDERS = ['Richard Stallman'] node.set_node_license( { 'id': GPL3.license_id, 'year': NEW_YEAR, 'copyrightHolders': COPYLEFT_HOLDERS }, auth=Auth(user), save=True ) node.add_tag('savanna', Auth(user)) node.add_tag('taxonomy', Auth(user)) node.set_subjects([[subject._id]], auth=Auth(node.creator)) node.affiliated_institutions.add(institution) node.save() draft = DraftRegistration.create_from_node( node=node, user=user, schema=factories.get_default_metaschema(), ) # Assert existing metadata-like node attributes are copied to the draft assert draft.title == title assert draft.description == description assert draft.category == category assert user in draft.contributors.all() assert write_contrib in draft.contributors.all() assert member not in draft.contributors.all() assert not draft.has_permission(member, 'read') assert draft.get_permissions(user) == [READ, WRITE, ADMIN] assert draft.get_permissions(write_contrib) == [READ, WRITE] assert draft.node_license.license_id == GPL3.license_id assert draft.node_license.name == GPL3.name assert draft.node_license.copyright_holders == COPYLEFT_HOLDERS draft_tags = draft.tags.values_list('name', flat=True) assert 'savanna' in draft_tags assert 'taxonomy' in draft_tags assert subject in draft.subjects.all() assert institution in draft.affiliated_institutions.all() assert draft.branched_from == node