Skip to content

Commit

Permalink
Merge pull request #9 from oarepo/onmodel-create-url
Browse files Browse the repository at this point in the history
create url for request types on model
  • Loading branch information
SilvyPuzzlewell authored Mar 15, 2024
2 parents 1b43724 + bea3a2e commit c8e7f70
Show file tree
Hide file tree
Showing 27 changed files with 367 additions and 235 deletions.
2 changes: 0 additions & 2 deletions oarepo_requests/actions/edit_topic.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from invenio_records_resources.services.uow import RecordDeleteOp

# from .generic import AcceptAction
from invenio_requests.customizations import actions

Expand Down
12 changes: 12 additions & 0 deletions oarepo_requests/ext.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from invenio_base.utils import obj_or_import_string

from oarepo_requests.resources.oarepo.config import OARepoRequestsResourceConfig
from oarepo_requests.resources.oarepo.resource import OARepoRequestsResource
from oarepo_requests.services.oarepo.config import OARepoRequestsServiceConfig
Expand All @@ -22,6 +24,16 @@ def init_app(self, app):
def entity_reference_ui_resolvers(self):
return self.app.config["ENTITY_REFERENCE_UI_RESOLVERS"]

def default_request_receiver(self, request_type_id):
"""
returns function that returns default request receiver
def receiver_getter(identity, request_type, topic, creator):
return <dark magic here>
"""
return obj_or_import_string(
self.app.config["OAREPO_REQUESTS_DEFAULT_RECEIVER"]
)[request_type_id]

# copied from invenio_requests for now
def service_configs(self, app):
"""Customized service configs."""
Expand Down
1 change: 1 addition & 0 deletions oarepo_requests/resources/draft/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ class DraftRecordRequestsResourceConfig(RecordRequestsResourceConfig):
routes = {
**RecordRequestsResourceConfig.routes,
"list-drafts": "/<pid_value>/draft/requests",
"type-draft": "/<pid_value>/draft/requests/<request_type>",
}
27 changes: 27 additions & 0 deletions oarepo_requests/resources/draft/resource.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from flask import g
from flask_resources import resource_requestctx, response_handler, route
from invenio_records_resources.resources.records.resource import (
request_data,
request_extra_args,
request_search_args,
request_view_args,
)
from invenio_records_resources.resources.records.utils import search_preference

from oarepo_requests.resources.record.resource import RecordRequestsResource
from oarepo_requests.utils import stringify_first_val


class DraftRecordRequestsResource(RecordRequestsResource):
Expand All @@ -18,6 +20,7 @@ def create_url_rules(self):

url_rules = [
route("GET", routes["list-drafts"], self.search_requests_for_draft),
route("POST", routes["type-draft"], self.create_for_draft),
]
return url_rules + old_rules

Expand All @@ -35,3 +38,27 @@ def search_requests_for_draft(self):
expand=resource_requestctx.args.get("expand", False),
)
return hits.to_dict(), 200

@request_extra_args
@request_view_args
@request_data
@response_handler()
def create_for_draft(self):
"""Create an item."""
items = self.service.create_for_draft(
identity=g.identity,
data=resource_requestctx.data,
request_type=resource_requestctx.view_args["request_type"],
topic_id=resource_requestctx.view_args[
"pid_value"
], # do in service; put type_id into service config, what about draft/not draft, different url?
expand=(
stringify_first_val(
resource_requestctx.data.pop("expand", False)
) # for what is this used, or can i just delete it
if resource_requestctx.data
else None
),
)

return items.to_dict(), 201
29 changes: 3 additions & 26 deletions oarepo_requests/resources/oarepo/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
)
from invenio_requests.resources import RequestsResource

from oarepo_requests.utils import stringify_first_val


class OARepoRequestsResource(RequestsResource, ErrorHandlersMixin):
"""
Expand Down Expand Up @@ -43,26 +45,11 @@ def s(route):
@request_data
@response_handler()
def create(self):
def stringify_first_val(dct):
if isinstance(dct, dict):
for k, v in dct.items():
dct[k] = str(v)
return dct

items = self.service.create(
identity=g.identity,
data=resource_requestctx.data,
request_type=resource_requestctx.data.pop("request_type", None),
receiver=(
stringify_first_val(resource_requestctx.data.pop("receiver", None))
if resource_requestctx.data
else None
),
creator=(
stringify_first_val(resource_requestctx.data.pop("creator", None))
if resource_requestctx.data
else None
),
topic=(
stringify_first_val(resource_requestctx.data.pop("topic", None))
if resource_requestctx.data
Expand All @@ -88,17 +75,7 @@ def stringify_first_val(dct):
items = self.service.create(
identity=g.identity,
data=resource_requestctx.data,
request_type=resource_requestctx.data.pop("request_type", None),
receiver=(
stringify_first_val(resource_requestctx.data.pop("receiver", None))
if resource_requestctx.data
else None
),
creator=(
stringify_first_val(resource_requestctx.data.pop("creator", None))
if resource_requestctx.data
else None
),
type_id=resource_requestctx.data.pop("request_type", None),
topic=(
stringify_first_val(resource_requestctx.data.pop("topic", None))
if resource_requestctx.data
Expand Down
11 changes: 9 additions & 2 deletions oarepo_requests/resources/record/config.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import marshmallow as ma
from invenio_records_resources.resources import RecordResourceConfig


class RecordRequestsResourceConfig(RecordResourceConfig):
routes = {"list": "/<pid_value>/requests"}
class RecordRequestsResourceConfig:
routes = {
"list": "/<pid_value>/requests",
"type": "/<pid_value>/requests/<request_type>",
}
request_view_args = RecordResourceConfig.request_view_args | {
"request_type": ma.fields.Str()
}
"""
@property
def response_handlers(self):
Expand Down
26 changes: 23 additions & 3 deletions oarepo_requests/resources/record/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from flask_resources import resource_requestctx, response_handler, route
from invenio_records_resources.resources import RecordResource
from invenio_records_resources.resources.records.resource import (
request_data,
request_extra_args,
request_search_args,
request_view_args,
Expand All @@ -12,16 +13,19 @@


class RecordRequestsResource(RecordResource):
def __init__(self, config, service, record_requests_config):
def __init__(self, record_requests_config, config, service):
"""
:param config: main record resource config
:param service:
:param record_requests_config: config specific for the record request serivce
"""
actual_config = copy.deepcopy(config)
actual_config.blueprint_name = f"{config.blueprint_name}_requests"
# possibly do some nontrivial merge
actual_config.routes = record_requests_config.routes
vars_to_overwrite = [
x for x in dir(record_requests_config) if not x.startswith("_")
]
for var in vars_to_overwrite:
setattr(actual_config, var, getattr(record_requests_config, var))
super().__init__(actual_config, service)

def create_url_rules(self):
Expand All @@ -30,6 +34,7 @@ def create_url_rules(self):

url_rules = [
route("GET", routes["list"], self.search_requests_for_record),
route("POST", routes["type"], self.create),
]
return url_rules

Expand All @@ -47,3 +52,18 @@ def search_requests_for_record(self):
expand=resource_requestctx.args.get("expand", False),
)
return hits.to_dict(), 200

@request_extra_args
@request_view_args
@request_data
@response_handler()
def create(self):
"""Create an item."""
items = self.service.create(
identity=g.identity,
data=resource_requestctx.data,
request_type=resource_requestctx.view_args["request_type"],
topic_id=resource_requestctx.view_args["pid_value"],
)

return items.to_dict(), 201
22 changes: 22 additions & 0 deletions oarepo_requests/services/draft/service.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from invenio_records_resources.services.uow import unit_of_work
from invenio_search.engine import dsl

from oarepo_requests.services.record.service import RecordRequestsService
Expand Down Expand Up @@ -47,3 +48,24 @@ def search_requests_for_draft(
extra_filter=search_filter,
**kwargs,
)

@unit_of_work()
def create_for_draft(
self,
identity,
data,
request_type,
topic_id,
expires_at=None,
uow=None,
expand=False,
):
record = self.draft_cls.pid.resolve(topic_id, registered_only=False)
return self.oarepo_requests_service.create(
identity=identity,
data=data,
request_type=request_type,
topic=record,
expand=expand,
uow=uow,
)
11 changes: 10 additions & 1 deletion oarepo_requests/services/oarepo/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from invenio_requests.services import RequestsService

from oarepo_requests.errors import UnknownRequestType
from oarepo_requests.proxies import current_oarepo_requests


class OARepoRequestsService(RequestsService):
Expand All @@ -12,7 +13,7 @@ def create(
identity,
data,
request_type,
receiver,
receiver=None,
creator=None,
topic=None,
expires_at=None,
Expand All @@ -22,6 +23,14 @@ def create(
type_ = current_request_type_registry.lookup(request_type, quiet=True)
if not type_:
raise UnknownRequestType(request_type)

if receiver is None:
receiver_getter = current_oarepo_requests.default_request_receiver(
request_type
)
receiver = receiver_getter(identity, request_type, topic, creator)
if data is None:
data = {}
if hasattr(type_, "can_create"):
error = type_.can_create(identity, data, receiver, topic, creator)
else:
Expand Down
25 changes: 24 additions & 1 deletion oarepo_requests/services/record/service.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
from types import SimpleNamespace

from invenio_records_resources.services.uow import unit_of_work
from invenio_search.engine import dsl

from oarepo_requests.proxies import current_oarepo_requests
from oarepo_requests.utils import get_type_id_for_record_cls


class RecordRequestsService:
def __init__(self, record_service):
def __init__(self, record_service, oarepo_requests_service):
self.record_service = record_service
self.oarepo_requests_service = oarepo_requests_service

# so api doesn't fall apart
@property
Expand Down Expand Up @@ -66,3 +68,24 @@ def search_requests_for_record(
extra_filter=search_filter,
**kwargs,
)

@unit_of_work()
def create(
self,
identity,
data,
request_type,
topic_id,
expires_at=None,
uow=None,
expand=False,
):
record = self.record_cls.pid.resolve(topic_id)
return self.oarepo_requests_service.create(
identity=identity,
data=data,
request_type=request_type,
topic=record,
expand=expand,
uow=uow,
)
6 changes: 2 additions & 4 deletions oarepo_requests/services/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ def update_data(self, identity, record, projection):
)
request_type_link = data
request_types_list.append(request_type_link)
if request_types_list:
projection["request_types"] = request_types_list
projection["request_types"] = request_types_list


class RequestsComponent:
Expand All @@ -45,5 +44,4 @@ def update_data(self, identity, record, projection):
requests = list(reader(identity, record["id"]).hits)
except PermissionDeniedError:
requests = []
if requests:
projection["requests"] = requests
projection["requests"] = requests
24 changes: 20 additions & 4 deletions oarepo_requests/services/schema.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import marshmallow as ma
from invenio_drafts_resources.services.records.config import is_record
from invenio_records_resources.services import ConditionalLink
from invenio_records_resources.services.base.links import Link, LinksTemplate
from invenio_requests.proxies import current_request_type_registry
from invenio_requests.services.schemas import GenericRequestSchema
from marshmallow import fields

from oarepo_requests.proxies import current_oarepo_requests_resource
from oarepo_requests.utils import get_matching_service_for_record


def get_links_schema():
Expand All @@ -19,11 +21,25 @@ class RequestTypeSchema(ma.Schema):

@ma.post_dump
def create_link(self, data, **kwargs):
if "links" in data:
return data
if "record" not in self.context:
raise ma.ValidationError(
"record not in context for request types serialization"
)
type_id = data["type_id"]
type = current_request_type_registry.lookup(type_id, quiet=True)
link = Link(f"{{+api}}{current_oarepo_requests_resource.config.url_prefix}")
template = LinksTemplate({"create": link})
data["links"] = {"actions": template.expand(self.context["identity"], type)}
record = self.context["record"]
service = get_matching_service_for_record(record)
link = ConditionalLink(
cond=is_record,
if_=Link(f"{{+api}}{service.config.url_prefix}{{id}}/requests/{type_id}"),
else_=Link(
f"{{+api}}{service.config.url_prefix}{{id}}/draft/requests/{type_id}"
),
)
template = LinksTemplate({"create": link}, context={"id": record["id"]})
data["links"] = {"actions": template.expand(self.context["identity"], record)}
return data


Expand Down
2 changes: 1 addition & 1 deletion oarepo_requests/types/delete_record.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from invenio_requests.customizations import RequestType
from oarepo_runtime.i18n import lazy_gettext as _

from oarepo_requests.actions.delete_topic import DeleteTopicAcceptAction

from .generic import OARepoRequestType

from oarepo_runtime.i18n import lazy_gettext as _

class DeleteRecordRequestType(OARepoRequestType):
available_actions = {
Expand Down
Loading

0 comments on commit c8e7f70

Please sign in to comment.