""" 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 = ["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": [ "*", ], }, "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 } # Invenio-S3 # ========== S3_ACCESS_KEY_ID = "CHANGE_ME" S3_SECRET_ACCESS_KEY = "CHANGE_ME" S3_REGION_NAME = "eu-west-1" S3_DEFAULT_BLOCK_SIZE = 525 * 1024**2 # 525 MB S3_SIGNATURE_VERSION = "s3v4" S3_ARGS = {"ACL": "private", "ServerSideEncryption": "AES256"} # 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", "mostviewed", ], "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", "mostviewed", ], } """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."""