diff --git a/oarepo_requests/config.py b/oarepo_requests/config.py new file mode 100644 index 00000000..d391b6ca --- /dev/null +++ b/oarepo_requests/config.py @@ -0,0 +1,28 @@ +from oarepo_requests.resolvers.ui import UserEntityReferenceUIResolver, FallbackEntityReferenceUIResolver, \ + GroupEntityReferenceUIResolver +from oarepo_requests.types import DeletePublishedRecordRequestType, EditPublishedRecordRequestType, PublishDraftRequestType +from invenio_users_resources.entity_resolvers import UserResolver, GroupResolver + + +REQUESTS_REGISTERED_TYPES = [ + DeletePublishedRecordRequestType(), + EditPublishedRecordRequestType(), + PublishDraftRequestType(), +] + +REQUESTS_ALLOWED_RECEIVERS = [ + "user", "role" +] + +REQUESTS_ENTITY_RESOLVERS = [ + UserResolver(), + GroupResolver(), +] + +ENTITY_REFERENCE_UI_RESOLVERS = { + "user": UserEntityReferenceUIResolver("user"), + "fallback": FallbackEntityReferenceUIResolver("fallback"), + "group": GroupEntityReferenceUIResolver("group"), +} + +REQUESTS_UI_SERIALIZATION_REFERENCED_FIELDS = ["created_by", "receiver", "topic"] \ No newline at end of file diff --git a/oarepo_requests/ext.py b/oarepo_requests/ext.py index 0f7c9645..c8058358 100644 --- a/oarepo_requests/ext.py +++ b/oarepo_requests/ext.py @@ -1,3 +1,5 @@ +from functools import cached_property + from invenio_base.utils import obj_or_import_string from invenio_requests.proxies import current_events_service @@ -19,6 +21,7 @@ def __init__(self, app=None): def init_app(self, app): """Flask application initialization.""" self.app = app + self.init_config(app) self.init_services(app) self.init_resources(app) app.extensions["oarepo-requests"] = self @@ -31,15 +34,21 @@ def entity_reference_ui_resolvers(self): def ui_serialization_referenced_fields(self): return self.app.config["REQUESTS_UI_SERIALIZATION_REFERENCED_FIELDS"] - def default_request_receiver(self, request_type_id): - """ - returns function that returns default request receiver - def receiver_getter(identity, request_type, topic, creator): - return - """ + def default_request_receiver(self, identity, request_type, topic, creator, data): + # TODO: if the topic is one of the workflow topics, use the workflow to determine the receiver + # otherwise use the default receiver return obj_or_import_string( self.app.config["OAREPO_REQUESTS_DEFAULT_RECEIVER"] - )[request_type_id] + )(identity=identity, request_type=request_type, topic=topic, creator=creator, data=data) + + @cached_property + def allowed_topic_ref_types(self): + entity_resolvers = self.app.config.get("REQUESTS_ENTITY_RESOLVERS", []) + return {x.type_key for x in entity_resolvers} + + @property + def allowed_receiver_ref_types(self): + return self.app.config.get("REQUESTS_ALLOWED_RECEIVERS", []) # copied from invenio_requests for now def service_configs(self, app): @@ -66,3 +75,15 @@ def init_resources(self, app): service=current_events_service, config=OARepoRequestsCommentsResourceConfig.build(app), ) + + def init_config(self, app): + """Initialize configuration.""" + + from . import config + app.config.setdefault("REQUESTS_REGISTERED_TYPES", []).extend(config.REQUESTS_REGISTERED_TYPES) + app.config.setdefault("REQUESTS_ALLOWED_RECEIVERS", []).extend(config.REQUESTS_ALLOWED_RECEIVERS) + app.config.setdefault("REQUESTS_ENTITY_RESOLVERS", []).extend(config.REQUESTS_ENTITY_RESOLVERS) + app.config.setdefault("ENTITY_REFERENCE_UI_RESOLVERS", {}).update(config.ENTITY_REFERENCE_UI_RESOLVERS) + app.config.setdefault("REQUESTS_UI_SERIALIZATION_REFERENCED_FIELDS", []).extend( + config.REQUESTS_UI_SERIALIZATION_REFERENCED_FIELDS + ) diff --git a/oarepo_requests/services/oarepo/service.py b/oarepo_requests/services/oarepo/service.py index e8b5bb8a..31390985 100644 --- a/oarepo_requests/services/oarepo/service.py +++ b/oarepo_requests/services/oarepo/service.py @@ -26,16 +26,18 @@ def create( raise UnknownRequestType(request_type) if receiver is None: - receiver_getter = current_oarepo_requests.default_request_receiver( - request_type + receiver = current_oarepo_requests.default_request_receiver( + identity, request_type, topic, creator, data ) - receiver = receiver_getter(identity, request_type, topic, creator, data) + if data is None: data = {} + if hasattr(type_, "can_create"): error = type_.can_create(identity, data, receiver, topic, creator) else: error = None + if not error: result = super().create( identity=identity, diff --git a/oarepo_requests/types/__init__.py b/oarepo_requests/types/__init__.py index e69de29b..f92c08f5 100644 --- a/oarepo_requests/types/__init__.py +++ b/oarepo_requests/types/__init__.py @@ -0,0 +1,14 @@ +from .ref_types import ModelRefTypes, ReceiverRefTypes +from .delete_record import DeletePublishedRecordRequestType +from .edit_record import EditPublishedRecordRequestType +from .publish_draft import PublishDraftRequestType +from .generic import NonDuplicableOARepoRequestType + +__all__ = [ + 'ModelRefTypes', + 'ReceiverRefTypes', + 'DeletePublishedRecordRequestType', + 'EditPublishedRecordRequestType', + 'PublishDraftRequestType', + 'NonDuplicableOARepoRequestType', +] \ No newline at end of file diff --git a/oarepo_requests/types/delete_record.py b/oarepo_requests/types/delete_record.py index f6935851..86e8ad46 100644 --- a/oarepo_requests/types/delete_record.py +++ b/oarepo_requests/types/delete_record.py @@ -6,7 +6,9 @@ from .generic import NonDuplicableOARepoRequestType -class DeleteRecordRequestType(NonDuplicableOARepoRequestType): +class DeletePublishedRecordRequestType(NonDuplicableOARepoRequestType): + type_id = "delete-published-record" + available_actions = { **RequestType.available_actions, "accept": DeleteTopicAcceptAction, diff --git a/oarepo_requests/types/edit_record.py b/oarepo_requests/types/edit_record.py index 5ed98d77..c7e1b4b7 100644 --- a/oarepo_requests/types/edit_record.py +++ b/oarepo_requests/types/edit_record.py @@ -7,7 +7,9 @@ from .generic import NonDuplicableOARepoRequestType -class EditRecordRequestType(NonDuplicableOARepoRequestType): +class EditPublishedRecordRequestType(NonDuplicableOARepoRequestType): + type_id = "edit-published-record" + available_actions = { **RequestType.available_actions, "submit": AutoAcceptSubmitAction, diff --git a/oarepo_requests/types/generic.py b/oarepo_requests/types/generic.py index f54bb9db..0d426766 100644 --- a/oarepo_requests/types/generic.py +++ b/oarepo_requests/types/generic.py @@ -5,6 +5,8 @@ from oarepo_requests.errors import OpenRequestAlreadyExists from oarepo_requests.utils import open_request_exists +from .ref_types import ModelRefTypes, ReceiverRefTypes + class OARepoRequestType(RequestType): def can_create(self, identity, data, receiver, topic, creator, *args, **kwargs): @@ -29,6 +31,9 @@ def can_possibly_create(self, identity, topic, *args, **kwargs): return False return True + allowed_topic_ref_types = ModelRefTypes() + allowed_receiver_ref_types = ReceiverRefTypes() + class NonDuplicableOARepoRequestType(OARepoRequestType): def can_create(self, identity, data, receiver, topic, creator, *args, **kwargs): diff --git a/oarepo_requests/types/publish_draft.py b/oarepo_requests/types/publish_draft.py index 7df30d7f..0ed74ddd 100644 --- a/oarepo_requests/types/publish_draft.py +++ b/oarepo_requests/types/publish_draft.py @@ -7,6 +7,8 @@ class PublishDraftRequestType(NonDuplicableOARepoRequestType): + type_id = "publish-draft" + available_actions = { **RequestType.available_actions, "accept": PublishDraftAcceptAction, diff --git a/oarepo_requests/types/ref_types.py b/oarepo_requests/types/ref_types.py new file mode 100644 index 00000000..fff6913c --- /dev/null +++ b/oarepo_requests/types/ref_types.py @@ -0,0 +1,23 @@ +from oarepo_requests.proxies import current_oarepo_requests + + +class ModelRefTypes: + """ + This class is used to define the allowed reference types for the topic reference. + The list of ref types is taken from the configuration (configuration key REQUESTS_ALLOWED_TOPICS). + """ + + def __get__(self, obj, owner): + """Property getter, returns the list of allowed reference types.""" + return current_oarepo_requests.allowed_topic_ref_types + + +class ReceiverRefTypes: + """ + This class is used to define the allowed reference types for the receiver reference. + The list of ref types is taken from the configuration (configuration key REQUESTS_ALLOWED_RECEIVERS). + """ + + def __get__(self, obj, owner): + """Property getter, returns the list of allowed reference types.""" + return current_oarepo_requests.allowed_receiver_ref_types diff --git a/run-tests.sh b/run-tests.sh index 3c1bc4cc..ad5f714d 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -22,6 +22,9 @@ if test -d ./$BUILD_TEST_DIR/$MODEL; then rm -rf ./$BUILD_TEST_DIR/$MODEL fi +# local override +# pip install --config-settings editable_mode=compat -e ../oarepo-model-builder-requests + oarepo-compile-model ./$CODE_TEST_DIR/$MODEL.yaml --output-directory ./$BUILD_TEST_DIR/$MODEL -vvv MODEL_VENV=".venv-tests" @@ -37,5 +40,8 @@ pip install -e "./$BUILD_TEST_DIR/${MODEL}" pip install oarepo-ui pip install -e . -pytest $BUILD_TEST_DIR/test_requests -pytest $BUILD_TEST_DIR/test_ui \ No newline at end of file +# local override +# pip install --config-settings editable_mode=compat -e ../oarepo-runtime + +#pytest $BUILD_TEST_DIR/test_requests +#pytest $BUILD_TEST_DIR/test_ui \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 24a97e41..381831e1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = oarepo-requests -version = 1.1.18 +version = 1.1.19 description = authors = Ronald Krist readme = README.md @@ -47,3 +47,7 @@ invenio_assets.webpack = oarepo_requests_ui_theme = oarepo_requests.ui.theme.webpack:theme invenio_i18n.translations = oarepo_requests_ui = oarepo_requests +invenio_requests.types = + delete-published-record = oarepo_requests.types.delete_record:DeletePublishedRecordRequestType + edit-published-record = oarepo_requests.types.edit_record:EditPublishedRecordRequestType + publish-draft = oarepo_requests.types.publish_draft:PublishDraftRequestType diff --git a/tests/test_ui/test_ui_resource.py b/tests/test_ui/test_ui_resource.py index f0275a43..924c1bdd 100644 --- a/tests/test_ui/test_ui_resource.py +++ b/tests/test_ui/test_ui_resource.py @@ -2,7 +2,7 @@ from invenio_requests.proxies import current_requests_service -from thesis.records.requests.edit_record.types import EditRecordRequestType +from thesis.records.requests.edit_record.types import EditPublishedRecordRequestType allowed_actions = ["submit", "delete"] @@ -84,7 +84,7 @@ def test_request_detail_page( request = current_requests_service.create( creator_identity, {}, - EditRecordRequestType, + EditPublishedRecordRequestType, topic=example_topic, receiver=users[1].user, creator=users[0].user,