Merge pull request #17997 from davelopez/23.2_invenio_plugin_fixes

[23.2] Invenio plugin fixes
This commit is contained in:
David López
2024-04-16 17:49:27 +02:00
committed by GitHub
3 changed files with 43 additions and 38 deletions
@@ -199,10 +199,14 @@
doc: Make sure to define this generic drs file source if you have defined any other drs file sources, or stock drs download capability will be disabled.
- type: inveniordm
id: invenio
doc: Invenio RDM turn-key research data management repository
label: Invenio RDM Demo Repository
id: invenio_sandbox
doc: This is the Sandbox instance of Invenio. It is used for testing purposes only, content is NOT preserved. DOIs created in this instance are not real and will not resolve.
label: Invenio RDM Sandbox Repository (TESTING ONLY)
url: https://inveniordm.web.cern.ch/
token: ${user.user_vault.read_secret('preferences/invenio_sandbox/token')}
# token: ${user.preferences['invenio_sandbox|token']} # Alternatively use this for retrieving the token from user preferences instead of the Vault
public_name: ${user.preferences['invenio_sandbox|public_name']}
writable: true
- type: onedata
id: onedata1
+18 -23
View File
@@ -1,6 +1,5 @@
import logging
from typing import (
cast,
List,
NamedTuple,
Optional,
@@ -26,6 +25,7 @@ OptionalUserContext = Optional[ProvidesUserFileSourcesUserContext]
class RDMFilesSourceProperties(FilesSourceProperties):
url: str
token: str
public_name: str
class RecordFilename(NamedTuple):
@@ -80,7 +80,9 @@ class RDMRepositoryInteractor:
"""
raise NotImplementedError()
def create_draft_record(self, title: str, user_context: OptionalUserContext = None):
def create_draft_record(
self, title: str, public_name: Optional[str] = None, user_context: OptionalUserContext = None
):
"""Creates a draft record (directory) in the repository with basic metadata.
The metadata is usually just the title of the record and the user that created it.
@@ -138,11 +140,10 @@ class RDMFilesSource(BaseFilesSource):
def __init__(self, **kwd: Unpack[FilesSourceProperties]):
props = self._parse_common_config_opts(kwd)
base_url = props.get("url", None)
base_url = props.get("url")
if not base_url:
raise Exception("URL for RDM repository must be provided in configuration")
self._repository_url = base_url
self._token = props.get("token", None)
self._props = props
self._repository_interactor = self.get_repository_interactor(base_url)
@@ -150,10 +151,6 @@ class RDMFilesSource(BaseFilesSource):
def repository(self) -> RDMRepositoryInteractor:
return self._repository_interactor
@property
def token(self) -> Optional[str]:
return self._token if self._token and not self._token.startswith("$") else None
def get_repository_interactor(self, repository_url: str) -> RDMRepositoryInteractor:
"""Returns an interactor compatible with the given repository URL.
@@ -190,25 +187,23 @@ class RDMFilesSource(BaseFilesSource):
def get_record_id_from_path(self, source_path: str) -> str:
return self.parse_path(source_path, record_id_only=True).record_id
def _serialization_props(self, user_context: OptionalUserContext = None) -> RDMFilesSourceProperties:
def _serialization_props(self, user_context: OptionalUserContext = None):
effective_props = {}
for key, val in self._props.items():
effective_props[key] = self._evaluate_prop(val, user_context=user_context)
effective_props["url"] = self._repository_url
effective_props["token"] = self.safe_get_authorization_token(user_context)
return cast(RDMFilesSourceProperties, effective_props)
return effective_props
def get_authorization_token(self, user_context: OptionalUserContext) -> str:
token = self.token
if not token and user_context:
vault = user_context.user_vault if user_context else None
token = vault.read_secret(f"preferences/{self.id}/token") if vault else None
if token is None:
raise AuthenticationRequired(f"No authorization token provided in user's settings for '{self.label}'")
token = None
if user_context:
effective_props = self._serialization_props(user_context)
token = effective_props.get("token")
if not token:
raise AuthenticationRequired(
f"Please provide a personal access token in your user's preferences for '{self.label}'"
)
return token
def safe_get_authorization_token(self, user_context: OptionalUserContext) -> Optional[str]:
try:
return self.get_authorization_token(user_context)
except AuthenticationRequired:
return None
def get_public_name(self, user_context: OptionalUserContext) -> Optional[str]:
effective_props = self._serialization_props(user_context)
return effective_props.get("public_name")
+18 -12
View File
@@ -135,7 +135,8 @@ class InvenioRDMFilesSource(RDMFilesSource):
user_context: OptionalUserContext = None,
opts: Optional[FilesSourceOptions] = None,
) -> Entry:
record = self.repository.create_draft_record(entry_data["name"], user_context=user_context)
public_name = self.get_public_name(user_context)
record = self.repository.create_draft_record(entry_data["name"], public_name, user_context=user_context)
return {
"uri": self.repository.to_plugin_uri(record["id"]),
"name": record["metadata"]["title"],
@@ -198,9 +199,11 @@ class InvenioRepositoryInteractor(RDMRepositoryInteractor):
response_data = self._get_response(user_context, request_url)
return self._get_record_files_from_response(record_id, response_data)
def create_draft_record(self, title: str, user_context: OptionalUserContext = None) -> RemoteDirectory:
def create_draft_record(
self, title: str, public_name: Optional[str] = None, user_context: OptionalUserContext = None
) -> RemoteDirectory:
today = datetime.date.today().isoformat()
creator = self._get_creator_from_user_context(user_context)
creator = self._get_creator_from_public_name(public_name)
create_record_request = {
"files": {"enabled": True},
"metadata": {
@@ -360,10 +363,9 @@ class InvenioRepositoryInteractor(RDMRepositoryInteractor):
)
return rval
def _get_creator_from_user_context(self, user_context: OptionalUserContext):
public_name = self.get_user_preference_by_key("public_name", user_context)
family_name = "Galaxy User"
def _get_creator_from_public_name(self, public_name: Optional[str] = None) -> Creator:
given_name = "Anonymous"
family_name = "Galaxy User"
if public_name:
tokens = public_name.split(", ")
if len(tokens) == 2:
@@ -371,12 +373,16 @@ class InvenioRepositoryInteractor(RDMRepositoryInteractor):
given_name = tokens[1]
else:
given_name = public_name
return {"person_or_org": {"family_name": family_name, "given_name": given_name, "type": "personal"}}
def get_user_preference_by_key(self, key: str, user_context: OptionalUserContext):
preferences = user_context.preferences if user_context else None
value = preferences.get(f"{self.plugin.id}|{key}", None) if preferences else None
return value
return {
"person_or_org": {
"name": f"{given_name} {family_name}",
"family_name": family_name,
"given_name": given_name,
"type": "personal",
"identifiers": [],
},
"affiliations": [],
}
def _get_response(
self, user_context: OptionalUserContext, request_url: str, params: Optional[Dict[str, Any]] = None