def get_facet_configuration(search_index): """Get facet configuration from request. It takes also in account the permissions of the current user, returning different facets if the user is either logged in or not. Args: search_index(str): the index for which facets needs to be loaded. Returns: dict: the configuration for the requested index. """ facet_name = request.values.get("facet_name") if is_superuser_or_cataloger_logged_in(): facet_data = current_app.config["CATALOGER_RECORDS_REST_FACETS"] else: facet_data = current_app.config["RECORDS_REST_FACETS"] facet = facet_data.get(facet_name) or facet_data.get(search_index) if isinstance(facet, string_types): facet = import_string(facet) if callable(facet): facet = facet() return facet
def put(self, pid_value): """Updates existing record in db""" data = self.load_data_from_request() try: pid, _ = pid_value.data record = JobsRecord.get_record_by_pid_value(pid.pid_value) if not self.user_can_edit(record): return ( jsonify( {"message": "You are not allowed to edit this Job opening"} ), 403, ) except PIDDoesNotExistError: abort(404) self.raise_if_user_can_not_modify_status(data, record) builder = self.get_builder_with_updated_record(data, record) data = self.get_valid_record_data_from_builder(builder) record.update(data) db.session.commit() if not is_superuser_or_cataloger_logged_in(): self.create_ticket(record, "rt/update_job.html") return jsonify({"pid_value": record["control_number"]})
def is_job_editable(data): """Check if the given job is editable A job is editable if one of the following is true: * current user is superadmin or cataloger * the job 'status' is not 'closed' and the job's author is logged-in. Args: data (dict): the jobs metadata. Returns: bool: True if the job can be edited, False otherwise. """ if is_superuser_or_cataloger_logged_in(): return True submitter_orcid = get_value(data, "acquisition_source.orcid") if submitter_orcid != get_current_user_orcid(): return False status = get_value(data, "status") if status != "closed": return True deadline = get_value(data, "deadline_date") if status == "closed" and not has_30_days_passed_after_deadline( deadline): return True return False
def prepare_update_record(self, data, record): # This contains all fields which can be removed from record (they are optional) # if new value sent from the form is None, or empty in any other way # (after de-serialization if it's missing from input data) # this fields will be removed from record additional_fields = [ "external_job_identifier", "accelerator_experiments", "urls", "contact_details", "reference_letters", ] if not is_superuser_or_cataloger_logged_in(): old_status = record.get("status", "pending") new_status = data.get("status", old_status) if ( new_status != old_status and new_status not in self.user_allowed_status_changes[old_status] ): raise RESTDataError( f"Only curator can change status from '{old_status}' to '{new_status}'." ) record_data = dict(record) for key in additional_fields: if key not in data and key in record_data: del record_data[key] record_data.update(data) builder = JobBuilder(record=record_data) return builder
def resolve(self, pid_value): """Override the `pid.is_deleted` case Now if user is cataloger or superuser, PIDDeletedError is not raised """ pid = PersistentIdentifier.get(self.pid_type, pid_value) if pid.is_new() or pid.is_reserved(): raise PIDUnregistered(pid) if pid.is_deleted() and not is_superuser_or_cataloger_logged_in(): obj_id = pid.get_assigned_object(object_type=self.object_type) try: obj = self.object_getter(obj_id) if obj_id else None except NoResultFound: obj = None raise PIDDeletedError(pid, obj) if pid.is_redirected(): if request.method != "PUT": raise PIDRedirectedError(pid, InspireRedirect.get_redirect(pid)) obj_id = pid.get_assigned_object(object_type=self.object_type) if not obj_id: raise PIDMissingObjectError(self.pid_type, pid_value) return pid, self.object_getter(obj_id)
def get_ui_display(self, data): try: ui_display = json.loads(get_value(data, "metadata._ui_display", "")) if is_superuser_or_cataloger_logged_in(): ui_display["can_edit"] = True return ui_display except json.JSONDecodeError: return {}
def query_by_user_role(self, query_string): if is_superuser_or_cataloger_logged_in(): return self.query(IQ(query_string, self)) searched_collections = ["Literature"] if "_collections" in query_string: searched_collections = list(get_allowed_collections_for_user()) user_query = Q(IQ(query_string, self)) return self.query(user_query).filter("terms", _collections=searched_collections)
def query_from_iq(self, query_string): """Initialize ES DSL object using INSPIRE query parser. :param query_string: Query string as a user would input in INSPIRE's search box. :type query_string: string :returns: Elasticsearch DSL search class """ if not is_superuser_or_cataloger_logged_in(): user_query = Q(IQ(query_string, self) & Q("term", status="open")) return self.query(user_query) return self.query(IQ(query_string, self))
def user_can_edit(self, record): if is_superuser_or_cataloger_logged_in(): return True acquisition_source = record.get("acquisition_source", {}) if ( acquisition_source.get("orcid") == self.get_user_orcid() and acquisition_source.get("email") == current_user.email and record.get("status") != "closed" ): return True return False
def get_ui_display(self, data): try: ui_display = json.loads(get_value(data, "metadata._ui_display", "")) if is_superuser_or_cataloger_logged_in(): ui_display["can_edit"] = True if is_assign_view_enabled(): ui_display["curated_relation"] = get_value( data, "metadata.curated_relation", False) return ui_display except json.JSONDecodeError: return {}
def post(self): """Adds new conference record""" data = self.load_data_from_request() data["acquisition_source"] = self.get_acquisition_source() record = SeminarsRecord.create(data) db.session.commit() if not is_superuser_or_cataloger_logged_in(): self.create_ticket(record, "rt/new_seminar.html") send_seminar_confirmation_email(current_user.email, record) return (jsonify({"pid_value": record["control_number"]}), 201)
def query_for_superuser_or_users(self, query_string): if not is_superuser_or_cataloger_logged_in(): if "_collections" in query_string: user_query = Q(IQ(query_string, self)) return self.query(user_query).filter( "terms", _collections=current_app. config["NON_PRIVATE_LITERATURE_COLLECTIONS"], ) else: user_query = Q( IQ(query_string, self) & Q("term", _collections="Literature")) return self.query(user_query) return self.query(IQ(query_string, self))
def get_builder_with_new_record(self, data): if "$schema" not in data: data["$schema"] = url_for( "invenio_jsonschemas.get_schema", schema_path="records/jobs.json", _external=True, ) if not is_superuser_or_cataloger_logged_in(): data["status"] = "pending" builder = JobBuilder(record=data) if "acquisition_source" not in builder.record: acquisition_source = self.get_acquisition_source() builder.add_acquisition_source(**acquisition_source) return builder
def post(self): """Adds new conference record""" data = self.load_data_from_request() record = ConferencesRecord.create(data) db.session.commit() if not is_superuser_or_cataloger_logged_in(): self.create_ticket(record, "rt/new_conference.html") send_conference_confirmation_email(current_user.email, record) return ( jsonify( {"pid_value": record["control_number"], "cnum": record.get("cnum")} ), 201, )
def is_job_editable(data): """Check if the given job is editable A job is editable if one of the following is true: * current user is superadmin or cataloger * the job 'status' is not 'closed' and the job's author is logged-in. Args: data (dict): the jobs metadata. Returns: bool: True if the job can be edited, False otherwise. """ if is_superuser_or_cataloger_logged_in(): return True email = get_value(data, "acquisition_source.email") return data.get("status") != "closed" and is_loggedin_user_email(email)
def get(self, pid_value): try: pid, _ = pid_value.data record = JobsRecord.get_record_by_pid_value(pid.pid_value) except PIDDoesNotExistError: abort(404) serialized_record = job_v1.dump(record) deadline = serialized_record.get("deadline_date") can_modify_status = is_superuser_or_cataloger_logged_in( ) or not has_30_days_passed_after_deadline(deadline) return jsonify({ "data": serialized_record, "meta": { "can_modify_status": can_modify_status }, })
def raise_if_user_can_not_modify_status(self, data, existing_record): if is_superuser_or_cataloger_logged_in(): return old_status = existing_record.get("status", "pending") new_status = data.get("status", old_status) deadline = data.get("deadline_date") has_status_changed = new_status != old_status is_change_to_new_status_allowed = ( new_status in self.user_allowed_status_changes[old_status]) can_change_status = (is_change_to_new_status_allowed and not has_30_days_passed_after_deadline(deadline)) if has_status_changed and not can_change_status: raise RESTDataError( f"Only curator can change status from '{old_status}' to '{new_status}'." )
def put(self, pid_value): try: record = SeminarsRecord.get_record_by_pid_value(pid_value) if not can_user_edit_record(record): return ( jsonify({"message": "You are not allowed to edit this seminar"}), 403, ) except PIDDoesNotExistError: abort(404) data = self.load_data_from_request() updated_record_data = self.get_updated_record_data(data, record) record.update(updated_record_data) db.session.commit() if not is_superuser_or_cataloger_logged_in(): self.create_ticket(record, "rt/update_seminar.html") return jsonify({"pid_value": record["control_number"]})
def get_ui_display(self, data): try: ui_display = orjson.loads( get_value(data, "metadata._ui_display", "")) if is_superuser_or_cataloger_logged_in(): ui_display["can_edit"] = True if is_assign_view_enabled(): ui_display["curated_relation"] = get_value( data, "metadata.curated_relation", False) if ui_display.get("authors"): ui_display.update( {"authors": get_authors_without_emails(ui_display)}) acquisition_source = ui_display.get("acquisition_source") if acquisition_source and "email" in acquisition_source: del acquisition_source["email"] ui_display.update({"acquisition_source": acquisition_source}) return ui_display except orjson.JSONDecodeError: return {}
def query_from_iq(self, query_string): """Initialize ES DSL object using INSPIRE query parser. :param query_string: Query string as a user would input in INSPIRE's search box. :type query_string: string :returns: Elasticsearch DSL search class """ if not is_superuser_or_cataloger_logged_in(): if not query_string: user_query = Q("term", status="open") else: user_query = Q( "bool", must=[ Q("query_string", query=query_string, default_operator="AND"), Q("term", status="open"), ], ) return self.query(user_query) return super().query_from_iq(query_string)
def put(self, pid_value): try: record = AuthorsRecord.get_record_by_pid_value(pid_value) # check if we need to check the orcid in the acquisition source or the one in ids if not can_user_edit_author_record(record): return ( jsonify({"message": "You are not allowed to edit this author"}), 403, ) except PIDDoesNotExistError: abort(404) data = self.load_data_from_request() self.update_author_record(data, record) db.session.commit() if not is_superuser_or_cataloger_logged_in(): self.create_ticket(record, "rt/update_author.html") if current_app.config.get("FEATURE_FLAG_ENABLE_WORKFLOW_ON_AUTHOR_UPDATE"): self.start_workflow_for_submission(record) return jsonify({"pid_value": record["control_number"]})
def put(self, pid_value): """Updates existing record in db""" data = job_loader_v1() try: pid, _ = pid_value.data record = JobsRecord.get_record_by_pid_value(pid.pid_value) if not self.user_can_edit(record): return ( jsonify( {"message": "You are not allowed to edit this Job opening"} ), 403, ) except PIDDoesNotExistError: abort(404) data = self.prepare_data(data, record) record.update(data) db.session.commit() if not is_superuser_or_cataloger_logged_in(): self.create_ticket(record, "rt/update_job.html") return jsonify({"pid_value": record["control_number"]})
def user_can_edit(self, record): orcid = get_value(record, "acquisition_source.orcid") email = get_value(record, "acquisition_source.email") return is_superuser_or_cataloger_logged_in() or ( orcid == self.get_user_orcid() and email == current_user.email )
def is_assign_view_enabled(): return (is_superuser_or_cataloger_logged_in() and request.values.get( "search_type", "", type=str) == "hep-author-publication" and request.values.get("author", "", type=str))
# -*- coding: utf-8 -*- # # Copyright (C) 2019 CERN. # # inspirehep is free software; you can redistribute it and/or modify it under # the terms of the MIT License; see LICENSE file for more details. from invenio_records_rest.serializers.response import record_responsify from inspirehep.accounts.api import is_superuser_or_cataloger_logged_in from inspirehep.records.marshmallow.base import EnvelopeSchema, ForbiddenSchema from inspirehep.serializers import ConditionalMultiSchemaJSONSerializer records_raw_json = ConditionalMultiSchemaJSONSerializer( [ ( lambda _: is_superuser_or_cataloger_logged_in(), EnvelopeSchema, ), (None, ForbiddenSchema), ] ) raw_json_detail_response = record_responsify( records_raw_json, "application/vnd+inspire.record.raw+json", )
def query_for_superuser_or_users(self, query_string): if not is_superuser_or_cataloger_logged_in(): user_query = Q( IQ(query_string, self) & Q("term", _collections="Literature")) return self.query(user_query) return self.query(IQ(query_string, self))
def set_can_edit(data, orginal_data): if is_superuser_or_cataloger_logged_in(): data["can_edit"] = True return data