diff --git a/docker-compose.yaml b/docker-compose.yaml index 73a8fdb..7d264ae 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -35,6 +35,7 @@ services: - uploaded_data:/opt/invenio/var/instance/data - archived_data:/opt/invenio/var/instance/archive - ./invenio_assets:/opt/invenio/var/instance/static/custom_assets # Add static assets for theming + - ./invenio.cfg:/opt/invenio/var/instance/invenio.cfg # Override the config with our custom one environment: # Flask - INVENIO_APP_ALLOWED_HOSTS=${INVENIO_APP_ALLOWED_HOSTS:-['0.0.0.0', 'localhost', '127.0.0.1']} @@ -117,7 +118,6 @@ services: # Custom invenio settings - INVENIO_SECURITY_REGISTERABLE=False # Disable manual user registration - INVENIO_MAIL_SUPPRESS_SEND=False # Allow server to send emails - - INVENIO_OAUTHCLIENT_REMOTE_APPS="{}" # Disable OAuth clients depends_on: search: condition: service_started diff --git a/invenio.cfg b/invenio.cfg new file mode 100644 index 0000000..bfcbdb8 --- /dev/null +++ b/invenio.cfg @@ -0,0 +1,820 @@ +""" +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 re +from flask import request, url_for +import idutils +from marshmallow import validate +from invenio_rdm_records.services.pids import providers +from invenio_rdm_records.services import facets +from invenio_rdm_records.contrib.journal import ( + JOURNAL_CUSTOM_FIELDS, + JOURNAL_CUSTOM_FIELDS_UI, + JOURNAL_NAMESPACE, +) +from invenio_records_resources.services.custom_fields import TextCF +from invenio_records_resources.services.records.queryparser import ( + FieldValueMapper, + QueryParser, + SearchFieldTransformer, +) + +# from invenio_records_resources.services.records.facets import TermsFacet +from invenio_communities.communities.records.models import CommunityMetadata +from invenio_db import db +from luqum.tree import Phrase + +from invenio_access import action_factory +from invenio_records.dictutils import dict_lookup +from invenio_records_permissions.generators import ( + ConditionalGenerator, + Generator, +) +from invenio_administration.generators import Administration +from invenio_communities.permissions import CommunityPermissionPolicy +from invenio_rdm_records.services.generators import ( + AccessGrant, + CommunityInclusionReviewers, + IfDeleted, + IfExternalDOIRecord, + IfFileIsLocal, + IfNewRecord, + IfRecordDeleted, + IfRestricted, + RecordCommunitiesAction, + RecordOwners, + ResourceAccessToken, + SecretLinks, + SubmissionReviewer, +) +from invenio_rdm_records.services.permissions import RDMRecordPermissionPolicy +from invenio_records_permissions.generators import ( + Disable, + IfConfig, + SystemProcess, +) + + +def _(x): # needed to avoid start time failure with lazy strings + return x + + +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. +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= + + +# 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 + # 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 = True + +# 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-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 +# ================== +FILES_REST_STORAGE_FACTORY = "invenio_s3.s3fs_storage_factory" + +# Invenio-S3 +# ========== +S3_ENDPOINT_URL = "http://localhost:9000/" +S3_ACCESS_KEY_ID = "CHANGE_ME" +S3_SECRET_ACCESS_KEY = "CHANGE_ME" +S3_REGION_NAME = "us-east-1" + +# 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")}, +# ) + +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", + }, + }, +} + + +# 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", "subject"], + # 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", + # 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", + # Specific to InveniRDM Starter + "content": "custom_fields.rs\:content_text", + }, + 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", "subject"], + "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 = [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_review + # Allow uploading, updating and deleting files in drafts + can_draft_create_files = can_review + can_draft_set_content_files = [SystemProcess()] + can_draft_get_content_files = [SystemProcess()] + can_draft_commit_files = [SystemProcess()] + can_draft_update_files = can_review + can_draft_delete_files = can_review + can_manage_record_access = can_review + + # + # 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 = [SystemProcess()] + # Allow deleting/discarding a draft and all associated files + can_delete_draft = [SystemProcess()] + # Allow creating a new version of an existing published record. + can_new_version = [SystemProcess()] + # Allow publishing a new record or changes to an existing record. + can_publish = [SystemProcess()] + # Allow lifting a record or draft. + can_lift_embargo = [SystemProcess()] + + # + # Record communities + # + # Who can add record to a community + can_add_community = can_review + + # Media files + can_draft_media_create_files = [MediaFilesManager(), SystemProcess()] + can_draft_media_read_files = can_draft_media_create_files + can_draft_media_set_content_files = [SystemProcess()] + can_draft_media_commit_files = [SystemProcess()] + can_draft_media_update_files = can_draft_media_create_files + can_draft_media_delete_files = can_draft_media_create_files + can_moderate = [SystemProcess()] + can_media_create_files = [SystemProcess()] + can_media_set_content_files = [SystemProcess()] + can_media_commit_files = [SystemProcess()] + can_media_update_files = [SystemProcess()] + can_media_delete_files = [SystemProcess()] + can_modify_locked_files = [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."""