Skip to content

Commit

Permalink
Merge pull request #17997 from davelopez/23.2_invenio_plugin_fixes
Browse files Browse the repository at this point in the history
[23.2] Invenio plugin fixes
  • Loading branch information
davelopez authored Apr 16, 2024
2 parents c36005b + 133730c commit 6a28080
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 38 deletions.
10 changes: 7 additions & 3 deletions lib/galaxy/config/sample/file_sources_conf.yml.sample
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
41 changes: 18 additions & 23 deletions lib/galaxy/files/sources/_rdm.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import logging
from typing import (
cast,
List,
NamedTuple,
Optional,
Expand All @@ -26,6 +25,7 @@
class RDMFilesSourceProperties(FilesSourceProperties):
url: str
token: str
public_name: str


class RecordFilename(NamedTuple):
Expand Down Expand Up @@ -80,7 +80,9 @@ def get_files_in_record(
"""
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.
Expand Down Expand Up @@ -138,22 +140,17 @@ 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)

@property
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.
Expand Down Expand Up @@ -190,25 +187,23 @@ def get_error_msg(details: str) -> str:
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")
30 changes: 18 additions & 12 deletions lib/galaxy/files/sources/invenio.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ def _create_entry(
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"],
Expand Down Expand Up @@ -198,9 +199,11 @@ def get_files_in_record(
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": {
Expand Down Expand Up @@ -360,23 +363,26 @@ def _get_record_files_from_response(self, record_id: str, response: dict) -> Lis
)
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:
family_name = tokens[0]
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
Expand Down

0 comments on commit 6a28080

Please sign in to comment.