diff --git a/invenio_rdm_records/records/jsonschemas/records/parent-v3.0.0.json b/invenio_rdm_records/records/jsonschemas/records/parent-v3.0.0.json index a548b4008b..dd44681f5b 100644 --- a/invenio_rdm_records/records/jsonschemas/records/parent-v3.0.0.json +++ b/invenio_rdm_records/records/jsonschemas/records/parent-v3.0.0.json @@ -72,6 +72,26 @@ } } } + }, + + "settings": { + "description": "Access settings for the record.", + "type": "object", + "additionalProperties": false, + "properties": { + "allow_user_requests": { + "description": "Whether or not access requests are enabled for authenticated users.", + "type": "boolean" + }, + "allow_guest_requests": { + "description": "Whether or not access requests are enabled for unauthenticated guests.", + "type": "boolean" + }, + "accept_conditions_text": { + "description": "Custom description for access conditions to be displayed rather than the default text.", + "type": ["string", "null"] + } + } } } }, diff --git a/invenio_rdm_records/records/mappings/os-v1/rdmrecords/drafts/draft-v6.0.0.json b/invenio_rdm_records/records/mappings/os-v1/rdmrecords/drafts/draft-v6.0.0.json index 7c9ec05470..57a361b9a0 100644 --- a/invenio_rdm_records/records/mappings/os-v1/rdmrecords/drafts/draft-v6.0.0.json +++ b/invenio_rdm_records/records/mappings/os-v1/rdmrecords/drafts/draft-v6.0.0.json @@ -180,6 +180,19 @@ "type": "keyword" } } + }, + "settings": { + "properties": { + "allow_user_requests": { + "type": "boolean" + }, + "allow_guest_requests": { + "type": "boolean" + }, + "accept_conditions_text": { + "type": "text" + } + } } } }, diff --git a/invenio_rdm_records/records/mappings/os-v1/rdmrecords/records/record-v6.0.0.json b/invenio_rdm_records/records/mappings/os-v1/rdmrecords/records/record-v6.0.0.json index d19eda2689..2d82a7a3d0 100644 --- a/invenio_rdm_records/records/mappings/os-v1/rdmrecords/records/record-v6.0.0.json +++ b/invenio_rdm_records/records/mappings/os-v1/rdmrecords/records/record-v6.0.0.json @@ -180,6 +180,19 @@ "type": "keyword" } } + }, + "settings": { + "properties": { + "allow_user_requests": { + "type": "boolean" + }, + "allow_guest_requests": { + "type": "boolean" + }, + "accept_conditions_text": { + "type": "text" + } + } } } }, diff --git a/invenio_rdm_records/records/mappings/os-v2/rdmrecords/drafts/draft-v6.0.0.json b/invenio_rdm_records/records/mappings/os-v2/rdmrecords/drafts/draft-v6.0.0.json index 7c9ec05470..57a361b9a0 100644 --- a/invenio_rdm_records/records/mappings/os-v2/rdmrecords/drafts/draft-v6.0.0.json +++ b/invenio_rdm_records/records/mappings/os-v2/rdmrecords/drafts/draft-v6.0.0.json @@ -180,6 +180,19 @@ "type": "keyword" } } + }, + "settings": { + "properties": { + "allow_user_requests": { + "type": "boolean" + }, + "allow_guest_requests": { + "type": "boolean" + }, + "accept_conditions_text": { + "type": "text" + } + } } } }, diff --git a/invenio_rdm_records/records/mappings/os-v2/rdmrecords/records/record-v6.0.0.json b/invenio_rdm_records/records/mappings/os-v2/rdmrecords/records/record-v6.0.0.json index d19eda2689..2d82a7a3d0 100644 --- a/invenio_rdm_records/records/mappings/os-v2/rdmrecords/records/record-v6.0.0.json +++ b/invenio_rdm_records/records/mappings/os-v2/rdmrecords/records/record-v6.0.0.json @@ -180,6 +180,19 @@ "type": "keyword" } } + }, + "settings": { + "properties": { + "allow_user_requests": { + "type": "boolean" + }, + "allow_guest_requests": { + "type": "boolean" + }, + "accept_conditions_text": { + "type": "text" + } + } } } }, diff --git a/invenio_rdm_records/records/mappings/v7/rdmrecords/drafts/draft-v6.0.0.json b/invenio_rdm_records/records/mappings/v7/rdmrecords/drafts/draft-v6.0.0.json index 7c9ec05470..57a361b9a0 100644 --- a/invenio_rdm_records/records/mappings/v7/rdmrecords/drafts/draft-v6.0.0.json +++ b/invenio_rdm_records/records/mappings/v7/rdmrecords/drafts/draft-v6.0.0.json @@ -180,6 +180,19 @@ "type": "keyword" } } + }, + "settings": { + "properties": { + "allow_user_requests": { + "type": "boolean" + }, + "allow_guest_requests": { + "type": "boolean" + }, + "accept_conditions_text": { + "type": "text" + } + } } } }, diff --git a/invenio_rdm_records/records/mappings/v7/rdmrecords/records/record-v6.0.0.json b/invenio_rdm_records/records/mappings/v7/rdmrecords/records/record-v6.0.0.json index d19eda2689..2d82a7a3d0 100644 --- a/invenio_rdm_records/records/mappings/v7/rdmrecords/records/record-v6.0.0.json +++ b/invenio_rdm_records/records/mappings/v7/rdmrecords/records/record-v6.0.0.json @@ -180,6 +180,19 @@ "type": "keyword" } } + }, + "settings": { + "properties": { + "allow_user_requests": { + "type": "boolean" + }, + "allow_guest_requests": { + "type": "boolean" + }, + "accept_conditions_text": { + "type": "text" + } + } } } }, diff --git a/invenio_rdm_records/records/systemfields/access/field/parent.py b/invenio_rdm_records/records/systemfields/access/field/parent.py index 109d0d129c..4674698baa 100644 --- a/invenio_rdm_records/records/systemfields/access/field/parent.py +++ b/invenio_rdm_records/records/systemfields/access/field/parent.py @@ -8,6 +8,7 @@ """Access system field.""" +from flask import current_app from invenio_records.systemfields import SystemField from ..grants import Grants @@ -15,12 +16,40 @@ from ..owners import Owner +class AccessSettings: + """Access settings for a parent record.""" + + def __init__(self, settings_dict): + """Constructor.""" + self.allow_user_requests = settings_dict.get("allow_user_requests", False) + self.allow_guest_requests = settings_dict.get("allow_guest_requests", False) + self.accept_conditions_text = settings_dict.get("accept_conditions_text", None) + + def dump(self): + """Dump the record as dictionary.""" + return { + "allow_user_requests": self.allow_user_requests, + "allow_guest_requests": self.allow_guest_requests, + "accept_conditions_text": self.accept_conditions_text, + } + + def __repr__(self): + """Return repr(self).""" + return "<{} requests: {}/{}, text: {}>".format( + type(self).__name__, + self.allow_guest_requests, + self.allow_user_requests, + bool(self.accept_conditions_text), + ) + + class ParentRecordAccess: """Access management for all versions of a record.""" grant_cls = Grants links_cls = Links owner_cls = Owner + settings_cls = AccessSettings def __init__( self, @@ -28,8 +57,10 @@ def __init__( grants=None, links=None, owner_cls=None, + settings=None, grants_cls=None, links_cls=None, + settings_cls=None, ): """Create a new Access object for a record. @@ -45,6 +76,7 @@ def __init__( owner_cls = owner_cls or ParentRecordAccess.owner_cls grants_cls = grants_cls or ParentRecordAccess.grant_cls links_cls = links_cls or ParentRecordAccess.links_cls + settings_cls = settings_cls or ParentRecordAccess.settings_cls # since owned_by and grants are basically sets and empty sets # evaluate to False, assigning 'self.x = x or x_cls()' could lead to @@ -52,6 +84,7 @@ def __init__( self._owned_by = owned_by if owned_by else owner_cls(None) self.grants = grants if grants else grants_cls() self.links = links if links else links_cls() + self.settings = settings if settings else settings_cls({}) self.errors = [] @property @@ -80,6 +113,7 @@ def dump(self): "owned_by": self._owned_by.dump(), "links": self.links.dump(), "grants": self.grants.dump(), + "settings": self.settings.dump(), } return access @@ -91,6 +125,7 @@ def refresh_from_dict(self, access_dict): self._owned_by = new_access.owned_by self.grants = new_access.grants self.links = new_access.links + self.settings = new_access.settings @classmethod def from_dict( @@ -99,23 +134,27 @@ def from_dict( owner_cls=None, grants_cls=None, links_cls=None, + settings_cls=None, ): """Create a new Access object from the specified 'access' property. The new ``ParentRecordAccess`` object will be populated with new instances from the configured classes. If ``access_dict`` is empty, the ``ParentRecordAccess`` object will - be populated with new instances of ``grants_cls``, and ``links_cls``. + be populated with new instances of ``grants_cls``, ``links_cls``, and + ``settings_cls``. """ grants_cls = grants_cls or cls.grant_cls links_cls = links_cls or cls.links_cls owner_cls = owner_cls or cls.owner_cls + settings_cls = settings_cls or cls.settings_cls errors = [] # provide defaults in case there is no 'access' property owner = owner_cls(None) grants = grants_cls() links = links_cls() + settings = settings_cls({}) if access_dict: try: @@ -135,21 +174,28 @@ def from_dict( except Exception as e: errors.append(e) + try: + settings = settings_cls(access_dict.get("settings", {})) + except Exception as e: + errors.append(e) + access = cls( owned_by=owner, grants=grants, links=links, + settings=settings, ) access.errors = errors return access def __repr__(self): """Return repr(self).""" - return ("<{} (owner: {}, grants: {}, links: {})>").format( + return "<{} (owner: {}, grants: {}, links: {}, settings: {})>".format( type(self).__name__, self.owner, len(self.grants or []), len(self.links or []), + self.settings, ) diff --git a/invenio_rdm_records/services/schemas/parent/access.py b/invenio_rdm_records/services/schemas/parent/access.py index 03c9fa1c5f..6cdaf496f3 100644 --- a/invenio_rdm_records/services/schemas/parent/access.py +++ b/invenio_rdm_records/services/schemas/parent/access.py @@ -57,9 +57,21 @@ class Agent(Schema): user = fields.Integer(required=True) +class AccessSettingsSchema(Schema): + """Schema for a record's access settings.""" + + # enabling/disabling guests or users to send access requests + user_requests_enabled = fields.Boolean() + guest_requests_enabled = fields.Boolean() + + # accept conditions text + accept_conditions_text = fields.String() + + class ParentAccessSchema(Schema): """Access schema.""" grants = fields.List(fields.Nested(Grant)) owned_by = fields.Nested(Agent) links = fields.List(fields.Nested(SecretLink)) + settings = fields.Nested(AccessSettingsSchema)