Files
am-d-model.eu/invenio/invenio.cfg
2025-09-04 13:53:06 +01:00

1008 lines
30 KiB
INI

"""
InvenioRDM settings for InvenioRDM Starter project, modified
for the AM-D-Model repository.
This file was automatically generated by 'invenio-cli init'
and manually modified to configure.
For the full list of settings and their values, see
https://inveniordm.docs.cern.ch/reference/configuration/.
"""
from copy import deepcopy
from datetime import datetime
import idutils
from invenio_access import action_factory
from invenio_communities.communities.records.models import CommunityMetadata
from invenio_communities.permissions import CommunityPermissionPolicy
from invenio_db import db
from invenio_rdm_records.contrib.journal import (
JOURNAL_CUSTOM_FIELDS,
JOURNAL_CUSTOM_FIELDS_UI,
JOURNAL_NAMESPACE,
)
from invenio_rdm_records.services import facets
from invenio_rdm_records.services.generators import (
AccessGrant,
IfRestricted,
RecordOwners,
)
from invenio_rdm_records.services.permissions import RDMRecordPermissionPolicy
from invenio_rdm_records.services.pids import providers
from invenio_records.dictutils import dict_lookup
from invenio_records_permissions.generators import (
AuthenticatedUser,
ConditionalGenerator,
Generator,
SystemProcess,
)
from invenio_records_resources.services.custom_fields import TextCF
from invenio_records_resources.services.records.facets.facets import (
LabelledFacetMixin,
TermsFacet,
)
from invenio_records_resources.services.records.queryparser import (
FieldValueMapper,
QueryParser,
SearchFieldTransformer,
)
from invenio_search.engine import dsl
from invenio_vocabularies.contrib.affiliations.facets import AffiliationsLabels
from invenio_vocabularies.contrib.funders.facets import FundersLabels
from invenio_vocabularies.services.facets import VocabularyLabels
from luqum.tree import Phrase
from marshmallow import validate
def _(x): # needed to avoid start time failure with lazy strings
return x
EXTENSIONS = ["custom_invenio_plugin"]
RATELIMIT_ENABLED = True
RATELIMIT_AUTHENTICATED_USER = "50000 per hour;900 per minute"
RATELIMIT_GUEST_USER = "30000 per hour;500 per minute"
# Flask
# =====
# See https://flask.palletsprojects.com/en/1.1.x/config/
# Define the value of the cache control header `max-age` returned by the server when serving
# public files. Files will be cached by the browser for the provided number of seconds.
# See flask documentation for more information:
# https://flask.palletsprojects.com/en/2.1.x/config/#SEND_FILE_MAX_AGE_DEFAULT
SEND_FILE_MAX_AGE_DEFAULT = 300
# Set via env variable
# SECRET_KEY=
# Since HAProxy and Nginx route all requests no matter the host header
# provided, the allowed hosts variable is set to localhost. In production it
# should be set to the correct host and it is strongly recommended to only
# route correct hosts to the application.
TRUSTED_HOSTS = ["invenio.am-d-model.eu"]
APP_ALLOWED_HOSTS = ["localhost", "127.0.0.1"]
# Flask-SQLAlchemy
# ================
# See https://flask-sqlalchemy.palletsprojects.com/en/2.x/config/
# Set via env variable
# SQLALCHEMY_DATABASE_URI=
SQLALCHEMY_ENGINE_OPTIONS = {
"pool_size": 5,
"max_overflow": 5,
"pool_recycle": 3600,
}
# Invenio-App
# ===========
# See https://invenio-app.readthedocs.io/en/latest/configuration.html
APP_DEFAULT_SECURE_HEADERS = {
"content_security_policy": {
"default-src": [
"'self'",
"data:", # for fonts
"'unsafe-inline'", # for inline scripts and styles
"blob:", # for pdf preview
"fly.storage.tigris.dev", # for S3 object storage
"s3.us-east-1.amazonaws.com", # for S3 object storage
"s3.eu-central-1.amazonaws.com", # for S3 object storage
"s3.eu-west-1.amazonaws.com", # for S3 object storage
# Add your own policies here (e.g. analytics)
],
"img-src": [
"*",
],
"script-src": ["'self'", "blob:", "'wasm-unsafe-eval'"],
},
"force_https": True,
"force_https_permanent": False,
"force_file_save": False,
"frame_options": "sameorigin",
"frame_options_allow_from": None,
"strict_transport_security": True,
"strict_transport_security_preload": False,
"strict_transport_security_max_age": 31556926, # One year in seconds
"strict_transport_security_include_subdomains": True,
"content_security_policy_report_uri": None,
"content_security_policy_report_only": False,
"session_cookie_secure": True,
"session_cookie_http_only": True,
}
# Flask-Babel
# ===========
# See https://python-babel.github.io/flask-babel/#configuration
# Default locale (language)
BABEL_DEFAULT_LOCALE = "en"
# Default time zone
BABEL_DEFAULT_TIMEZONE = "UTC"
# Invenio-I18N
# ============
# See https://invenio-i18n.readthedocs.io/en/latest/configuration.html
# Other supported languages (do not include BABEL_DEFAULT_LOCALE in list).
I18N_LANGUAGES = [
("de", _("German")),
("es", _("Spanish")),
("fr", _("French")),
("it", _("Italian")),
("pt", _("Portuguese")),
("tr", _("Turkish")),
]
# Invenio-Mail
# ===========
# See https://invenio-mail.readthedocs.io/en/latest/configuration.html
# Set this to False when enable email sending.
MAIL_SUPPRESS_SEND = False
# Invenio-Theme
# =============
# See https://invenio-theme.readthedocs.io/en/latest/configuration.html
# The name of the site to be used on the header and as a title.
THEME_SITENAME = "InvenioRDM Starter"
# Frontpage title
THEME_FRONTPAGE_TITLE = "InvenioRDM Starter"
# Frontpage subtitle
THEME_FRONTPAGE_SUBTITLE = (
"A starter project for the turn-key research data management repository."
)
# Header logo
THEME_LOGO = "images/starter.svg"
# Invenio-logging Sentry
# ----------------------
LOGGING_SENTRY_INIT_KWARGS = {
# Add Sentry SDK configuration options here, e.g.:
# Instruct Sentry to send user data attached to the event
"send_default_pii": True,
}
LOGGING_SENTRY_LEVEL = "ERROR"
# Invenio-App-RDM
# ===============
# See https://invenio-app-rdm.readthedocs.io/en/latest/configuration.html
# Instance's theme entrypoint file. Path relative to the ``assets/`` folder.
INSTANCE_THEME_FILE = "./less/theme.less"
# Invenio-Files-Rest
# ==================
DATADIR = "/opt/invenio/var/instance/data"
FILES_REST_STORAGE_FACTORY = "invenio_s3.s3fs_storage_factory"
FILES_REST_MAX_CONTENT_LENGTH = 5 * 1024**4 # 5 TB
FILES_REST_MULTIPART_CHUNKSIZE_MIN = 5 * 1024**2 # 5 MB
FILES_REST_MULTIPART_CHUNKSIZE_MAX = 5 * 1024**3 # 5 GB
FILES_REST_MULTIPART_MAX_PARTS = 10000
FILES_REST_MULTIPART_UPLOAD_THRESHOLD = 100 * 1024**2 # 100 MB
FILES_REST_MULTIPART_EXPIRES = 7 * 24 * 60 * 60 # 7 days
RDM_FILES_DEFAULT_MAX_FILE_SIZE = 5 * 1024**4 # 5 TB
RDM_FILES_DEFAULT_QUOTA_SIZE = 10 * 1024**4 # 10 TB
APP_RDM_DEPOSIT_FORM_QUOTA = {
"maxFiles": 500,
"maxStorage": 10 * 1024**4, # 10 TB
}
APP_RDM_DEPOSIT_NG_FILES_UI_ENABLED = True
# Invenio-S3
# ==========
S3_ACCESS_KEY_ID = "CHANGE_ME"
S3_SECRET_ACCESS_KEY = "CHANGE_ME"
S3_REGION_NAME = "eu-west-1"
S3_SIGNATURE_VERSION = "s3v4"
S3_URL_EXPIRATION = 60 * 60 * 24 # 1 Day
# Invenio-Assets
# ==============
# Use rspack instead of webpack
WEBPACKEXT_PROJECT = "invenio_assets.webpack:rspack_project"
# Invenio-Records-Resources
# =========================
# See https://github.com/inveniosoftware/invenio-records-resources/blob/master/invenio_records_resources/config.py
SITE_UI_URL = "https://localhost"
SITE_API_URL = "https://localhost/api"
APP_RDM_DEPOSIT_FORM_DEFAULTS = {
"publication_date": lambda: datetime.now().strftime("%Y-%m-%d"),
"rights": [
{
"id": "cc-by-4.0",
"title": "Creative Commons Attribution 4.0 International",
"description": (
"The Creative Commons Attribution license allows "
"re-distribution and re-use of a licensed work "
"on the condition that the creator is "
"appropriately credited."
),
"link": "https://creativecommons.org/licenses/by/4.0/legalcode",
}
],
"resource_type": {
"id": "publication-preprint",
},
}
# See https://github.com/inveniosoftware/invenio-app-rdm/blob/master/invenio_app_rdm/config.py
APP_RDM_DEPOSIT_FORM_AUTOCOMPLETE_NAMES = "search" # "search_only" or "off"
# Invenio-RDM-Records
# ===================
# See https://inveniordm.docs.cern.ch/customize/dois/
DATACITE_ENABLED = False
DATACITE_PREFIX = "10.1234"
#
# Persistent identifiers configuration
#
RDM_PERSISTENT_IDENTIFIER_PROVIDERS = [
# DOI provider for externally managed DOIs
providers.ExternalPIDProvider(
"external",
"doi",
validators=[providers.BlockedPrefixes(config_names=["DATACITE_PREFIX"])],
label=_("DOI"),
),
# OAI identifier
providers.OAIPIDProvider(
"oai",
label=_("OAI ID"),
),
]
"""A list of configured persistent identifier providers."""
RDM_PERSISTENT_IDENTIFIERS = {
"doi": {
"providers": ["external"],
"required": False,
"label": _("DOI"),
"validator": idutils.is_doi,
"normalizer": idutils.normalize_doi,
"is_enabled": providers.ExternalPIDProvider.is_enabled,
},
"oai": {
"providers": ["oai"],
"required": True,
"label": _("OAI"),
"is_enabled": providers.OAIPIDProvider.is_enabled,
},
}
"""The configured persistent identifiers for records."""
RDM_PARENT_PERSISTENT_IDENTIFIERS = {}
def always_valid(identifier):
"""Gives every identifier as valid."""
return True
RDM_RECORDS_IDENTIFIERS_SCHEMES = {
"ark": {"label": _("ARK"), "validator": idutils.is_ark, "datacite": "ARK"},
"arxiv": {"label": _("arXiv"), "validator": idutils.is_arxiv, "datacite": "arXiv"},
"ads": {
"label": _("Bibcode"),
"validator": idutils.is_ads,
"datacite": "bibcode",
},
"crossreffunderid": {
"label": _("Crossref Funder ID"),
"validator": always_valid,
"datacite": "Crossref Funder ID",
},
"doi": {"label": _("DOI"), "validator": idutils.is_doi, "datacite": "DOI"},
"ean13": {"label": _("EAN13"), "validator": idutils.is_ean13, "datacite": "EAN13"},
"eissn": {"label": _("EISSN"), "validator": idutils.is_issn, "datacite": "EISSN"},
"grid": {"label": _("GRID"), "validator": always_valid, "datacite": "GRID"},
"handle": {
"label": _("Handle"),
"validator": idutils.is_handle,
"datacite": "Handle",
},
"igsn": {"label": _("IGSN"), "validator": always_valid, "datacite": "IGSN"},
"isbn": {"label": _("ISBN"), "validator": idutils.is_isbn, "datacite": "ISBN"},
"isni": {"label": _("ISNI"), "validator": idutils.is_isni, "datacite": "ISNI"},
"issn": {"label": _("ISSN"), "validator": idutils.is_issn, "datacite": "ISSN"},
"istc": {"label": _("ISTC"), "validator": idutils.is_istc, "datacite": "ISTC"},
"lissn": {"label": _("LISSN"), "validator": idutils.is_issn, "datacite": "LISSN"},
"lsid": {"label": _("LSID"), "validator": idutils.is_lsid, "datacite": "LSID"},
"pmid": {"label": _("PMID"), "validator": idutils.is_pmid, "datacite": "PMID"},
"purl": {"label": _("PURL"), "validator": idutils.is_purl, "datacite": "PURL"},
"upc": {"label": _("UPC"), "validator": always_valid, "datacite": "UPC"},
"url": {"label": _("URL"), "validator": idutils.is_url, "datacite": "URL"},
"urn": {"label": _("URN"), "validator": idutils.is_urn, "datacite": "URN"},
"w3id": {"label": _("W3ID"), "validator": always_valid, "datacite": "w3id"},
# Custom identifiers added for InvenioRDM Starter
"uuid": {"label": _("UUID"), "validator": always_valid, "datacite": "UUID"},
"guid": {"label": _("GUID"), "validator": always_valid, "datacite": "GUID"},
"other": {"label": _("Other"), "validator": always_valid, "datacite": "Other"},
}
"""These are used for references, main, alternate and related identifiers."""
# Authentication - Invenio-Accounts and Invenio-OAuthclient
# =========================================================
# See: https://inveniordm.docs.cern.ch/customize/authentication/
# Invenio-Accounts
# ----------------
# See https://github.com/inveniosoftware/invenio-accounts/blob/master/invenio_accounts/config.py
ACCOUNTS_LOCAL_LOGIN_ENABLED = True # enable local login
ACCOUNTS_DEFAULT_USER_VISIBILITY = "public"
SECURITY_REGISTERABLE = True # local login: allow users to register
SECURITY_RECOVERABLE = True # local login: allow users to reset the password
SECURITY_CHANGEABLE = True # local login: allow users to change psw
SECURITY_CONFIRMABLE = True # local login: users can confirm e-mail address
SECURITY_LOGIN_WITHOUT_CONFIRMATION = (
False # require users to confirm email before being able to login
)
# Enable optional custom fields
RDM_NAMESPACES = {
**JOURNAL_NAMESPACE,
"rs": None,
}
RDM_CUSTOM_FIELDS = [
*JOURNAL_CUSTOM_FIELDS,
TextCF( # content in markdown format
name="rs:content_text",
),
TextCF( # feature image url
name="rs:image",
field_args={
"validate": validate.URL(),
},
multiple=False,
),
]
RDM_CUSTOM_FIELDS_UI = [
{
"section": _("Publishing information"),
"hide_from_landing_page": True,
"fields": [
# journal
*JOURNAL_CUSTOM_FIELDS_UI["fields"],
],
},
{
"section": _("Images"),
"hide_from_landing_page": True,
"fields": [
dict(
field="rs:image",
ui_widget="Input",
props=dict(
label="Feature Image URL",
icon="image",
required=False,
),
),
],
},
]
RDM_SORT_OPTIONS = {
"bestmatch": dict(
title=_("Best match"),
fields=["_score"],
),
"newest": dict(
title=_("Newest"),
fields=["-metadata.publication_date", "-metadata.dates.date"],
),
"oldest": dict(
title=_("Oldest"),
fields=["metadata.publication_date", "metadata.dates.date"],
),
"version": dict(
title=_("Version"),
fields=["-versions.index"],
),
"updated-desc": dict(
title=_("Recently updated"),
fields=["-updated"],
),
"updated-asc": dict(
title=_("Least recently updated"),
fields=["updated"],
),
"created-desc": dict(
title=_("Recently added"),
fields=["-created"],
),
"created-asc": dict(
title=_("Least recently added"),
fields=["created"],
),
}
# def orcid = TermsFacet(
# field="is_published",
# label=_("ORCID"),
# value_labels={"true": _("Yes"), "false": _("No")},
# )
class DateHistogramFacet(LabelledFacetMixin, dsl.DateHistogramFacet):
"""Date Range Facet
facets = {
'publication_date': DateRangeFacet(
field='dates',
interval='year',
format='yyyy'
)
}
"""
def __init__(self, *args, **kwargs):
"""Show only years with at least 1 document."""
kwargs.setdefault("min_doc_count", 1)
super().__init__(*args, **kwargs)
def get_value_filter(self, filter_value):
"""Overriding this function to cast string dates to datetime"""
for interval_type in ("calendar_interval", "fixed_interval"):
if interval_type in self._params:
break
else:
interval_type = "interval"
# dealing with a range
try:
if "--" in filter_value:
start, end = [
datetime.strptime(year, "%Y") for year in filter_value.split("--")
]
end = self.DATE_INTERVALS[self._params[interval_type]](end)
else:
start = datetime.strptime(filter_value, "%Y")
end = self.DATE_INTERVALS[self._params[interval_type]](start)
except ValueError:
start = 0
end = 1
# swap them
if start > end:
start, end = end, start
return dsl.query.Range(
_expand__to_dot=False,
**{
self._params["field"]: {
"gte": start,
"lt": end,
}
},
)
RDM_FACETS = {
"access_status": {
"facet": facets.access_status,
"ui": {
"field": "access.status",
},
},
"is_published": {
"facet": facets.is_published,
"ui": {
"field": "is_published",
},
},
"file_type": {
"facet": facets.filetype,
"ui": {
"field": "files.types",
},
},
"language": {
"facet": facets.language,
"ui": {
"field": "languages",
},
},
"resource_type": {
"facet": facets.resource_type,
"ui": {
"field": "resource_type.type",
"childAgg": {
"field": "resource_type.subtype",
},
},
},
"subject": {
"facet": facets.subject,
"ui": {
"field": "subjects.subject",
},
},
"publication_date": {
"facet": DateHistogramFacet(
field="metadata.publication_date_range",
label=_("Publication year"),
interval="year",
format="yyyy",
),
"ui": {"field": "publication_date"},
},
"affiliations": {
"facet": TermsFacet(
field="metadata.creators.affiliations.id",
label=_("Author affiliations"),
value_labels=AffiliationsLabels("affiliations"),
),
"ui": {
"field": "metadata.creators.affiliations",
},
},
"funders": {
"facet": TermsFacet(
field="metadata.funding.funder.id",
label=_("Funders"),
value_labels=FundersLabels("funders"),
),
"ui": {
"field": "metadata.funding.funder",
},
},
"author_identifiers": {
"facet": TermsFacet(
field="metadata.creators.person_or_org.identifiers.scheme",
label=_("Author identifiers"),
value_labels={"orcid": _("ORCID")},
),
"ui": {
"field": "metadata.creators.person_or_org.identifiers.scheme",
},
},
"rights": {
"facet": TermsFacet(
field="metadata.rights.id",
label=_("Licenses"),
value_labels=VocabularyLabels("licenses"),
),
"ui": {
"field": "rights",
},
},
"relations": {
"facet": TermsFacet(
field="metadata.related_identifiers.relation_type.id",
label=_("Related works"),
value_labels=VocabularyLabels("relationtypes"),
),
"ui": {
"field": "related_identifiers.relation_type",
},
},
"references": {
"facet": TermsFacet(
field="metadata.references.scheme",
label=_("References"),
value_labels={
"doi": _("DOI"),
"url": _("URL"),
"": _("No identifier"),
},
),
"ui": {
"field": "metadata.references.scheme",
},
},
}
# from https://github.com/zenodo/zenodo-rdm/blob/master/site/zenodo_rdm/queryparser.py
def word_doi(node):
"""Quote DOIs."""
if not node.value.startswith("10."):
return node
return Phrase(f'"{node.value}"')
def word_communities(node):
"""Resolve community slugs to IDs."""
slug = node.value
uuid = (
db.session.query(CommunityMetadata.id)
.filter(CommunityMetadata.slug == slug)
.scalar()
)
return Phrase(f'"{uuid}"')
RDM_SEARCH = {
# Supported values from RDM_FACETS
"facets": [
"language",
"resource_type",
"publication_date",
"subject",
"funders",
"affiliations",
"author_identifiers",
"rights",
"relations",
"references",
],
# Supported values from RDM_SORT_OPTIONS
"sort": [
"bestmatch",
"newest",
"oldest",
"updated-desc",
"updated-asc",
"created-desc",
"created-asc",
],
"query_parser_cls": QueryParser.factory(
mapping={
# shortcuts
"title": "metadata.title",
"subject": "metadata.subjects.subject",
"contributor": "metadata.creators.person_or_org.name",
"affiliation": "metadata.creators.affiliations.name",
"funder": "metadata.funding.funder.name",
"references": FieldValueMapper(
"metadata.references.identifier", word=word_doi
),
# taken from Zenodo
"doi": FieldValueMapper("pids.doi.identifier", word=word_doi),
"communities": FieldValueMapper(
"parent.communities.ids", word=word_communities
),
# Persistent identifiers
"orcid": "metadata.creators.person_or_org.identifiers.identifier",
"ror": "metadata.creators.affiliations.id",
"issn": "custom_fields.journal\:journal.issn",
},
tree_transformer_cls=SearchFieldTransformer,
),
}
COMMUNITIES_RECORDS_SEARCH = deepcopy(RDM_SEARCH)
"""Communities record search config is the same as the main record search."""
RDM_SEARCH_DRAFTS = {
"facets": [
"is_published",
"language",
"resource_type",
"publication_date",
"subject",
"funders",
"affiliations",
"author_identifiers",
"rights",
"relations",
"references",
],
"sort": [
"bestmatch",
"newest",
"oldest",
"updated-desc",
"updated-asc",
"created-desc",
"created-asc",
],
}
"""User records search configuration (i.e. list of uploads)."""
# Toggle to show or hide the 'Browse' menu entry for communities.
COMMUNITIES_SHOW_BROWSE_MENU_ENTRY = True
# Enable featured communities
COMMUNITIES_ADMINISTRATION_DISABLED = False
# Invenio-OAuthclient
# -------------------
# See https://github.com/inveniosoftware/invenio-oauthclient/blob/master/invenio_oauthclient/config.py
# from invenio_oauthclient.contrib.orcid import ORCIDOAuthSettingsHelper
# from invenio_github.oauth.remote_app import github_app as github_remote_app
#
# _orcid_app = ORCIDOAuthSettingsHelper(
# title="ORCID",
# description="ORCID - Connecting Research and Researchers.",
# base_url="https://pub.orcid.org/",
# access_token_url="https://orcid.org/oauth/token",
# authorize_url="https://orcid.org/oauth/authorize#show_login",
# )
#
# OAUTHCLIENT_REMOTE_APPS = {
# "orcid": _orcid_app.remote_app,
# "github": github_remote_app,
# }
#
# # Set via env variable
# ORCID_APP_CREDENTIALS = {
# "consumer_key": "CHANGE ME",
# "consumer_secret": "CHANGE ME",
# }
# GITHUB_APP_CREDENTIALS = {
# "consumer_key": "CHANGE ME",
# "consumer_secret": "CHANGE",
# }
#
# from invenio_oauthclient.views.client import auto_redirect_login
# ACCOUNTS_LOGIN_VIEW_FUNCTION = auto_redirect_login # autoredirect to external login if enabled
# OAUTHCLIENT_AUTO_REDIRECT_TO_EXTERNAL_LOGIN = False # autoredirect to external login
#
# # Invenio-UserProfiles
# # --------------------
# USERPROFILES_READ_ONLY = False # allow users to change profile info (name, email, etc...)
# OAI-PMH
# =======
# See https://github.com/inveniosoftware/invenio-oaiserver/blob/master/invenio_oaiserver/config.py
OAISERVER_ID_PREFIX = "invenio-rdm"
"""The prefix that will be applied to the generated OAI-PMH ids."""
# Invenio-Search
# --------------
SEARCH_INDEX_PREFIX = "invenio-rdm-"
# See https://inveniordm.docs.cern.ch/reference/configuration/
RDM_CITATION_STYLES = [
("apa", _("APA")),
("harvard-cite-them-right", _("Harvard")),
("ieee", _("IEEE")),
("modern-language-association", _("MLA")),
("vancouver", _("Vancouver")),
("chicago-author-date", _("Chicago")),
("american-chemical-society", _("ACS")),
]
RDM_DEFAULT_CITATION_STYLE = "apa"
# Redirection of legacy URLs
# --------------------------
REDIRECTOR_RULES = {
# "redirect_name": {
# "source": "/blogs",
# "target": redirect_function,
# },
}
"""InvenioRDMStarter permissions."""
# these are defined here as there is a circular dependency otherwise with the
# permissions.py file
media_files_management_action = action_factory("manage-media-files")
manage_external_doi_files_action = action_factory("manage-external-doi-files")
class IfFilesRestrictedForCommunity(IfRestricted):
"""Conditional generator for files restriction for community."""
def __init__(self, then_, else_):
"""Constructor."""
super().__init__("files", then_, else_)
def _condition(self, record, **kwargs):
"""Check if community can access restricted files of the migrated record."""
try:
can_community_read_files = dict_lookup(
record.parent, "permission_flags.can_community_read_files"
)
except KeyError:
can_community_read_files = True
is_restricted = super()._condition(record, **kwargs)
if is_restricted:
return not can_community_read_files
else:
return False
class MediaFilesManager(Generator):
"""Allows media files management."""
def __init__(self):
"""Constructor."""
super(MediaFilesManager, self).__init__()
def needs(self, **kwargs):
"""Enabling Needs."""
return [media_files_management_action]
class ExternalDOIFilesManager(Generator):
"""Allows to manage files for exteranl DOI records."""
def __init__(self):
"""Initialize generator."""
super(ExternalDOIFilesManager, self).__init__()
def needs(self, **kwargs):
"""Enable Needs."""
return [manage_external_doi_files_action]
class IfRecordManagementAllowedForCommunity(ConditionalGenerator):
"""Conditional generator for community access to record management."""
def _condition(self, record, **kwargs):
"""Check if community can manage the migrated record."""
if record is None:
return False
try:
can_community_manage_record = dict_lookup(
record.parent, "permission_flags.can_community_manage_record"
)
except KeyError:
can_community_manage_record = True
return can_community_manage_record
def query_filter(self, **kwargs):
"""Filters for current identity as super user."""
then_query = self._make_query(self.then_, **kwargs)
else_query = self._make_query(self.else_, **kwargs)
return then_query if then_query else else_query
class InvenioRDMStarterRecordPermissionPolicy(RDMRecordPermissionPolicy):
"""Access control configuration for records."""
#
# High-level permissions (used by low-level)
#
can_manage = [
IfRecordManagementAllowedForCommunity(
then_=RDMRecordPermissionPolicy.can_manage,
else_=[
RecordOwners(),
AccessGrant("manage"),
SystemProcess(),
],
)
]
can_curate = can_manage + [SystemProcess()]
can_review = can_curate + [SystemProcess()]
can_preview = can_curate + [SystemProcess()]
#
# Records
#
# Used for search filtering of deleted records
# cannot be implemented inside can_read - otherwise permission will
# kick in before tombstone renders
can_create = [AuthenticatedUser(), SystemProcess()]
can_read_deleted = [SystemProcess()]
can_read_deleted_files = can_read_deleted
can_media_read_deleted_files = can_read_deleted_files
#
# Drafts
#
# Allow reading metadata of a draft
can_read_draft = can_preview
# Allow reading files of a draft
can_draft_read_files = can_preview + [SystemProcess()]
# Allow updating metadata of a draft
can_update_draft = can_manage
# Allow uploading, updating and deleting files in drafts
can_draft_create_files = can_manage
can_draft_set_content_files = can_manage + [SystemProcess()]
can_draft_get_content_files = can_manage + [SystemProcess()]
can_draft_commit_files = can_manage + [SystemProcess()]
can_draft_update_files = can_manage
can_draft_delete_files = can_manage
can_manage_record_access = can_manage
#
# PIDs
#
can_pid_create = can_review
can_pid_register = can_review
can_pid_update = can_review
can_pid_discard = can_review
can_pid_delete = can_review
#
# Actions
#
# Allow to put a record in edit mode (create a draft from record)
can_edit = can_manage + [SystemProcess()]
# Allow deleting/discarding a draft and all associated files
can_delete_draft = can_manage + [SystemProcess()]
# Allow creating a new version of an existing published record.
can_new_version = can_manage + [SystemProcess()]
# Allow publishing a new record or changes to an existing record.
can_publish = can_manage + [SystemProcess()]
# Allow lifting a record or draft.
can_lift_embargo = can_manage + [SystemProcess()]
#
# Record communities
#
# Who can add record to a community
can_add_community = can_review
# Media files
can_draft_media_create_files = can_manage + [MediaFilesManager(), SystemProcess()]
can_draft_media_read_files = can_draft_media_create_files
can_draft_media_set_content_files = can_manage + [SystemProcess()]
can_draft_media_commit_files = can_manage + [SystemProcess()]
can_draft_media_update_files = can_draft_media_create_files
can_draft_media_delete_files = can_draft_media_create_files
can_moderate = can_manage + [SystemProcess()]
can_media_create_files = can_manage + [SystemProcess()]
can_media_set_content_files = can_manage + [SystemProcess()]
can_media_commit_files = can_manage + [SystemProcess()]
can_media_update_files = can_manage + [SystemProcess()]
can_media_delete_files = can_manage + [SystemProcess()]
can_modify_locked_files = can_manage + [SystemProcess()]
class InvenioRDMStarterCommunityPermissionPolicy(CommunityPermissionPolicy):
"""Permissions for Community CRUD operations.
We start with limited permissions for community creation and moderation.
"""
can_create = [SystemProcess()]
can_moderate = [SystemProcess()]
can_rename = [SystemProcess()]
can_submit_record = [SystemProcess()]
can_include_directly = [SystemProcess()]
RDM_PERMISSION_POLICY = InvenioRDMStarterRecordPermissionPolicy
"""InvenioRDMStarter record permission policy."""
COMMUNITIES_ALLOW_RESTRICTED = False
"""Don't allow restricted records in communities."""
COMMUNITIES_PERMISSION_POLICY = InvenioRDMStarterCommunityPermissionPolicy
"""InvenioRDMStarter community permission policy."""