Skip to content

Commit

Permalink
Merge pull request #42 from oarepo/miroslavsimek/be-413-add-request-t…
Browse files Browse the repository at this point in the history
…ypes-link-onto-a-record

REST for applicable requests
  • Loading branch information
mesemus authored Aug 22, 2024
2 parents 21f5267 + dd3a78c commit 24e008b
Show file tree
Hide file tree
Showing 9 changed files with 290 additions and 28 deletions.
5 changes: 3 additions & 2 deletions oarepo_requests/resources/draft/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class DraftRecordRequestsResourceConfig(RecordRequestsResourceConfig):

routes = {
**RecordRequestsResourceConfig.routes,
"list-drafts": "/<pid_value>/draft/requests",
"type-draft": "/<pid_value>/draft/requests/<request_type>",
"list-requests-draft": "/<pid_value>/draft/requests",
"list-applicable-requests-draft": "/<pid_value>/draft/requests/applicable",
"request-type-draft": "/<pid_value>/draft/requests/<request_type>",
}
15 changes: 13 additions & 2 deletions oarepo_requests/resources/draft/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ def create_url_rules(self):
routes = self.config.routes

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

Expand All @@ -39,6 +40,16 @@ def search_requests_for_draft(self):
)
return hits.to_dict(), 200

@request_view_args
@response_handler(many=True)
def get_applicable_request_types_for_draft(self):
"""List request types."""
hits = self.service.get_applicable_request_types_for_draft(
identity=g.identity,
record_id=resource_requestctx.view_args["pid_value"],
)
return hits.to_dict(), 200

@request_extra_args
@request_view_args
@request_data
Expand Down
5 changes: 3 additions & 2 deletions oarepo_requests/resources/record/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@

class RecordRequestsResourceConfig:
routes = {
"list": "/<pid_value>/requests",
"type": "/<pid_value>/requests/<request_type>",
"list-requests": "/<pid_value>/requests",
"list-applicable-requests": "/<pid_value>/requests/applicable",
"request-type": "/<pid_value>/requests/<request_type>",
}
request_view_args = RecordResourceConfig.request_view_args | {
"request_type": ma.fields.Str()
Expand Down
15 changes: 13 additions & 2 deletions oarepo_requests/resources/record/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ def create_url_rules(self):
routes = self.config.routes

url_rules = [
route("GET", routes["list"], self.search_requests_for_record),
route("POST", routes["type"], self.create),
route("GET", routes["list-requests"], self.search_requests_for_record),
route("GET", routes["list-applicable-requests"], self.get_applicable_request_types),
route("POST", routes["request-type"], self.create),
]
return url_rules

Expand All @@ -53,6 +54,16 @@ def search_requests_for_record(self):
)
return hits.to_dict(), 200

@request_view_args
@response_handler(many=True)
def get_applicable_request_types(self):
"""List request types."""
hits = self.service.get_applicable_request_types(
identity=g.identity,
record_id=resource_requestctx.view_args["pid_value"],
)
return hits.to_dict(), 200

@request_extra_args
@request_view_args
@request_data
Expand Down
11 changes: 10 additions & 1 deletion oarepo_requests/services/draft/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
from invenio_search.engine import dsl

from oarepo_requests.services.record.service import RecordRequestsService
from oarepo_requests.services.results import allowed_user_request_types, RequestTypesList
from oarepo_requests.services.schema import RequestTypeSchema
from oarepo_requests.utils import get_type_id_for_record_cls
from invenio_records_resources.services import LinksTemplate
from invenio_records_resources.services.base.links import Link


class DraftRecordRequestsService(RecordRequestsService):
Expand All @@ -24,7 +28,7 @@ def search_requests_for_draft(
):
"""Search for record's requests."""
record = self.draft_cls.pid.resolve(record_id, registered_only=False)
# self.record_service.require_permission(identity, "read_draft", record=record)
self.record_service.require_permission(identity, "read_draft", record=record)

search_filter = dsl.query.Bool(
"must",
Expand Down Expand Up @@ -69,3 +73,8 @@ def create_for_draft(
expand=expand,
uow=uow,
)


def get_applicable_request_types_for_draft(self, identity, record_id):
record = self.draft_cls.pid.resolve(record_id, registered_only=False)
return self._get_applicable_request_types(identity, record)
24 changes: 24 additions & 0 deletions oarepo_requests/services/record/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
from invenio_search.engine import dsl

from oarepo_requests.proxies import current_oarepo_requests
from oarepo_requests.services.results import allowed_user_request_types, RequestTypesList
from oarepo_requests.services.schema import RequestTypeSchema
from oarepo_requests.utils import get_type_id_for_record_cls
from invenio_records_resources.services import LinksTemplate
from invenio_records_resources.services.base.links import Link


class RecordRequestsService:
Expand Down Expand Up @@ -69,6 +73,26 @@ def search_requests_for_record(
**kwargs,
)

def get_applicable_request_types(self, identity, record_id):
record = self.record_cls.pid.resolve(record_id)
return self._get_applicable_request_types(identity, record)

def _get_applicable_request_types(self, identity, record):
self.record_service.require_permission(identity, "read", record=record)
allowed_request_types = allowed_user_request_types(identity, record)
return RequestTypesList(
service=self.record_service,
identity=identity,
results=list(allowed_request_types.values()),
links_tpl=LinksTemplate(
{
'self': Link("{+record_link_requests}/applicable")
}
),
schema=RequestTypeSchema,
record=record,
)

@unit_of_work()
def create(
self,
Expand Down
99 changes: 81 additions & 18 deletions oarepo_requests/services/results.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,48 @@
from invenio_records_resources.services.errors import PermissionDeniedError
from oarepo_runtime.datastreams.utils import get_record_service_for_record
from oarepo_runtime.services.results import ResultsComponent
from oarepo_runtime.services.results import ResultsComponent, RecordList

from oarepo_requests.services.schema import RequestTypeSchema
from oarepo_requests.utils import (
allowed_request_types_for_record,
get_requests_service_for_records_service,
)
from invenio_records_resources.services import LinksTemplate



class RequestTypesComponent(ResultsComponent):
def update_data(self, identity, record, projection, expand):
if not expand:
return
request_types_list = []
allowed_request_types = allowed_request_types_for_record(record)
for request_name, request_type in allowed_request_types.items():
if hasattr(
request_type, "can_possibly_create"
) and request_type.can_possibly_create(identity, record):
schema = RequestTypeSchema
data = schema(
context={
"identity": identity,
"record": record,
}
).dump(
request_type,
)
request_type_link = data
request_types_list.append(request_type_link)
allowed_request_types = allowed_user_request_types(identity, record)
request_types_list = serialize_request_types(allowed_request_types, identity, record)
projection["expanded"]["request_types"] = request_types_list

def allowed_user_request_types(identity, record):
allowed_request_types = allowed_request_types_for_record(record)
allowed_request_types = {
request_type_name: request_type
for request_type_name, request_type in allowed_request_types.items()
if hasattr(
request_type, "can_possibly_create"
) and request_type.can_possibly_create(identity, record)
}
return allowed_request_types


def serialize_request_types(request_types, identity, record):
request_types_list = []
for request_type in request_types.values():
request_types_list.append(serialize_request_type(request_type, identity, record))
return request_types_list


def serialize_request_type(request_type, identity, record):
return RequestTypeSchema(context={"identity": identity, "record": record}).dump(
request_type
)


class RequestsComponent(ResultsComponent):
def update_data(self, identity, record, projection, expand):
Expand All @@ -51,3 +62,55 @@ def update_data(self, identity, record, projection, expand):
except PermissionDeniedError:
requests = []
projection["expanded"]["requests"] = requests


class RequestTypesList(RecordList):
def __init__(self, *args, record=None, **kwargs):
self._record = record
super().__init__(*args, **kwargs)

def to_dict(self):
"""Return result as a dictionary."""
hits = list(self.hits)

record_links = self._service.config.links_item
rendered_record_links = LinksTemplate(record_links, context={}).expand(self._identity, self._record)
links_tpl = LinksTemplate(
self._links_tpl._links, context={
**{
f'record_link_{k}': v for k, v in rendered_record_links.items()
}
})
res = {
"hits": {
"hits": hits,
"total": self.total,
}
}
if self._links_tpl:
res["links"] = links_tpl.expand(self._identity, None)

return res

@property
def hits(self):
"""Iterator over the hits."""
for hit in self._results:
# Project the record
projection = self._schema(
context=dict(
identity=self._identity,
record=self._record,
)
).dump(
hit,
)
if self._links_item_tpl:
projection["links"] = self._links_item_tpl.expand(
self._identity, hit
)
yield projection

@property
def total(self):
return len(self._results)
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = oarepo-requests
version = 2.0.3
version = 2.0.4
description =
authors = Ronald Krist <[email protected]>
readme = README.md
Expand Down
Loading

0 comments on commit 24e008b

Please sign in to comment.