Code source de geonature.utils.config_schema

"""
    Description des options de configuration
"""

import os

from warnings import warn

from marshmallow import Schema, fields, validates_schema, ValidationError, post_load, pre_load
from marshmallow.validate import OneOf, Regexp, Email, Length

from geonature.core.gn_synthese.synthese_config import (
    DEFAULT_EXPORT_COLUMNS,
    DEFAULT_LIST_COLUMN,
)
from geonature.utils.env import GEONATURE_VERSION, BACKEND_DIR, ROOT_DIR
from geonature.utils.module import iter_modules_dist, get_module_config
from geonature.utils.utilsmails import clean_recipients
from geonature.utils.utilstoml import load_and_validate_toml


[docs] class EmailStrOrListOfEmailStrField(fields.Field):
[docs] def _deserialize(self, value, attr, data, **kwargs): if isinstance(value, str): value = list(map(lambda x: x.replace("\n", "").strip(), value.split(","))) if not isinstance(value, list) and all(isinstance(x, str) for x in value): raise ValidationError("Field should be str or list of str") self._check_email(value) return value
[docs] def _check_email(self, value): recipients = clean_recipients(value) for recipient in recipients: email = recipient[1] if isinstance(recipient, tuple) else recipient # Validate email with Marshmallow validator = Email() validator(email)
[docs] class CasUserSchemaConf(Schema):
[docs] URL = fields.Url(load_default="https://inpn.mnhn.fr/authentication/information")
[docs] BASE_URL = fields.Url(load_default="https://inpn.mnhn.fr/authentication/")
[docs] ID = fields.String(load_default="mon_id")
[docs] PASSWORD = fields.String(load_default="mon_pass")
[docs] class CasFrontend(Schema):
[docs] CAS_AUTHENTIFICATION = fields.Boolean(load_default=False)
[docs] CAS_URL_LOGIN = fields.Url(load_default="https://preprod-inpn.mnhn.fr/auth/login")
[docs] CAS_URL_LOGOUT = fields.Url(load_default="https://preprod-inpn.mnhn.fr/auth/logout")
[docs] class CasSchemaConf(Schema):
[docs] CAS_URL_VALIDATION = fields.String( load_default="https://preprod-inpn.mnhn.fr/auth/serviceValidate" )
[docs] CAS_USER_WS = fields.Nested(CasUserSchemaConf, load_default=CasUserSchemaConf().load({}))
[docs] USERS_CAN_SEE_ORGANISM_DATA = fields.Boolean(load_default=False)
# Quel modules seront associés au JDD récupérés depuis MTD
[docs] class MTDSchemaConf(Schema):
[docs] JDD_MODULE_CODE_ASSOCIATION = fields.List(fields.String, load_default=["OCCTAX", "OCCHAB"])
[docs] ID_INSTANCE_FILTER = fields.Integer(load_default=None)
[docs] SYNC_LOG_LEVEL = fields.String(load_default="INFO")
[docs] class BddConfig(Schema):
[docs] ID_USER_SOCLE_1 = fields.Integer(load_default=7)
[docs] ID_USER_SOCLE_2 = fields.Integer(load_default=6)
[docs] class RightsSchemaConf(Schema):
[docs] NOTHING = fields.Integer(load_default=0)
[docs] MY_DATA = fields.Integer(load_default=1)
[docs] MY_ORGANISM_DATA = fields.Integer(load_default=2)
[docs] ALL_DATA = fields.Integer(load_default=3)
[docs] class MailConfig(Schema):
[docs] MAIL_SERVER = fields.String(required=False)
[docs] MAIL_PORT = fields.Integer(required=False)
[docs] MAIL_USE_TLS = fields.Boolean(required=False)
[docs] MAIL_USE_SSL = fields.Boolean(required=False)
[docs] MAIL_USERNAME = fields.String(required=False)
[docs] MAIL_PASSWORD = fields.String(required=False)
[docs] MAIL_DEFAULT_SENDER = fields.String(required=False)
[docs] MAIL_MAX_EMAILS = fields.Integer(required=False)
[docs] MAIL_SUPPRESS_SEND = fields.Boolean(required=False)
[docs] MAIL_ASCII_ATTACHMENTS = fields.Boolean(required=False)
[docs] ERROR_MAIL_TO = EmailStrOrListOfEmailStrField(load_default=None)
[docs] class CeleryConfig(Schema):
[docs] broker_url = fields.String(load_default="redis://localhost:6379/0")
[docs] result_backend = fields.String(load_default="redis://localhost:6379/0")
[docs] enable_utc = fields.Boolean(load_default=False)
[docs] timezone = fields.String(load_default=None)
[docs] class AccountManagement(Schema): # Config for sign-up
[docs] ENABLE_SIGN_UP = fields.Boolean(load_default=False)
[docs] ENABLE_USER_MANAGEMENT = fields.Boolean(load_default=False)
[docs] AUTO_ACCOUNT_CREATION = fields.Boolean(load_default=True)
[docs] AUTO_DATASET_CREATION = fields.Boolean(load_default=True)
[docs] VALIDATOR_EMAIL = EmailStrOrListOfEmailStrField(load_default=None)
[docs] ACCOUNT_FORM = fields.List(fields.Dict(), load_default=[])
[docs] ADDON_USER_EMAIL = fields.String(load_default="")
[docs] DATASET_MODULES_ASSOCIATION = fields.List(fields.String(), load_default=["OCCTAX"])
[docs] class UsersHubConfig(Schema):
[docs] ADMIN_APPLICATION_LOGIN = fields.String()
[docs] ADMIN_APPLICATION_PASSWORD = fields.String()
[docs] URL_USERSHUB = fields.Url()
[docs] class ServerConfig(Schema):
[docs] LOG_LEVEL = fields.Integer(load_default=20)
[docs] class MediasConfig(Schema):
[docs] MEDIAS_SIZE_MAX = fields.Integer(load_default=50000)
[docs] THUMBNAIL_SIZES = fields.List(fields.Integer, load_default=[200, 50])
[docs] class AlembicConfig(Schema):
[docs] VERSION_LOCATIONS = fields.String()
[docs] class AdditionalFields(Schema):
[docs] IMPLEMENTED_MODULES = fields.List(fields.String(), load_default=["OCCTAX"])
[docs] IMPLEMENTED_OBJECTS = fields.List( fields.String(), load_default=["OCCTAX_RELEVE", "OCCTAX_OCCURENCE", "OCCTAX_DENOMBREMENT"] )
[docs] class HomeConfig(Schema):
[docs] TITLE = fields.String(load_default="Bienvenue dans GeoNature")
[docs] INTRODUCTION = fields.String( load_default="Texte d'introduction, configurable pour le modifier régulièrement ou le masquer" )
[docs] FOOTER = fields.String(load_default="")
[docs] class MetadataConfig(Schema):
[docs] NB_AF_DISPLAYED = fields.Integer(load_default=50, validate=OneOf([10, 25, 50, 100]))
[docs] ENABLE_CLOSE_AF = fields.Boolean(load_default=False)
[docs] CLOSED_AF_TITLE = fields.String(load_default="")
[docs] AF_PDF_TITLE = fields.String(load_default="Cadre d'acquisition: ")
[docs] DS_PDF_TITLE = fields.String(load_default="")
[docs] MAIL_SUBJECT_AF_CLOSED_BASE = fields.String(load_default="")
[docs] MAIL_CONTENT_AF_CLOSED_ADDITION = fields.String(load_default="")
[docs] MAIL_CONTENT_AF_CLOSED_PDF = fields.String(load_default="")
[docs] MAIL_CONTENT_AF_CLOSED_URL = fields.String(load_default="")
[docs] MAIL_CONTENT_AF_CLOSED_GREETINGS = fields.String(load_default="")
[docs] CLOSED_MODAL_LABEL = fields.String(load_default="Fermer un cadre d'acquisition")
[docs] CLOSED_MODAL_CONTENT = fields.String( load_default="""L'action de fermeture est irréversible. Il ne sera plus possible d'ajouter des jeux de données au cadre d'acquisition par la suite.""" )
[docs] CD_NOMENCLATURE_ROLE_TYPE_DS = fields.List(fields.Str(), load_default=[])
[docs] CD_NOMENCLATURE_ROLE_TYPE_AF = fields.List(fields.Str(), load_default=[])
[docs] METADATA_AREA_FILTERS = fields.List( fields.Dict, load_default=[ {"label": "Communes", "type_code": "COM"}, {"label": "Départements", "type_code": "DEP"}, {"label": "Régions", "type_code": "REG"}, ], )
# class a utiliser pour les paramètres que l'on ne veut pas passer au frontend
[docs] class GnPySchemaConf(Schema):
[docs] SQLALCHEMY_DATABASE_URI = fields.String( required=True, validate=Regexp( r"^(postgres(?:ql)?)((\+psycopg2)?):\/\/(?:([^@\s]+)@)?([^\/\s]+)(?:\/(\w+))?(?:\?(.+))?", error="PostgreSQL database URL is invalid. Check for authorized URL here : https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS", ), )
[docs] SQLALCHEMY_TRACK_MODIFICATIONS = fields.Boolean(load_default=True)
[docs] SESSION_TYPE = fields.String(load_default="filesystem")
[docs] SECRET_KEY = fields.String(required=True, validate=Length(min=20))
# le cookie expire toute les 7 jours par défaut
[docs] COOKIE_EXPIRATION = fields.Integer(load_default=3600 * 24 * 7)
[docs] COOKIE_AUTORENEW = fields.Boolean(load_default=True)
[docs] TRAP_ALL_EXCEPTIONS = fields.Boolean(load_default=False)
[docs] SENTRY_DSN = fields.String()
[docs] ROOT_PATH = fields.String(load_default=BACKEND_DIR)
[docs] STATIC_FOLDER = fields.String(load_default="static")
[docs] CUSTOM_STATIC_FOLDER = fields.String(load_default=ROOT_DIR / "custom")
[docs] MEDIA_FOLDER = fields.String(load_default="media")
[docs] CAS = fields.Nested(CasSchemaConf, load_default=CasSchemaConf().load({}))
[docs] MAIL_ON_ERROR = fields.Boolean(load_default=False)
[docs] MAIL_CONFIG = fields.Nested(MailConfig, load_default=MailConfig().load({}))
[docs] CELERY = fields.Nested(CeleryConfig, load_default=CeleryConfig().load({}))
[docs] METADATA = fields.Nested(MetadataConfig, load_default=MetadataConfig().load({}))
[docs] ADMIN_APPLICATION_LOGIN = fields.String()
[docs] ACCOUNT_MANAGEMENT = fields.Nested(AccountManagement, load_default=AccountManagement().load({}))
[docs] BAD_LOGIN_STATUS_CODE = fields.Integer(load_default=401)
[docs] USERSHUB = fields.Nested(UsersHubConfig, load_default=UsersHubConfig().load({}))
[docs] SERVER = fields.Nested(ServerConfig, load_default=ServerConfig().load({}))
[docs] MEDIAS = fields.Nested(MediasConfig, load_default=MediasConfig().load({}))
[docs] ALEMBIC = fields.Nested(AlembicConfig, load_default=AlembicConfig().load({}))
@post_load()
[docs] def folders(self, data, **kwargs): data["STATIC_FOLDER"] = os.path.join(data["ROOT_PATH"], data["STATIC_FOLDER"]) if "CUSTOM_STATIC_FOLDER" in data: data["CUSTOM_STATIC_FOLDER"] = os.path.join( data["ROOT_PATH"], data["CUSTOM_STATIC_FOLDER"] ) data["MEDIA_FOLDER"] = os.path.join(data["ROOT_PATH"], data["MEDIA_FOLDER"]) return data
@post_load()
[docs] def unwrap_usershub(self, data, **kwargs): """ On met la section [USERSHUB] à la racine de la conf pour compatibilité et simplicité ave le sous-module d'authentif """ for key, value in data["USERSHUB"].items(): data[key] = value data.pop("USERSHUB") return data
@validates_schema
[docs] def validate_enable_usershub_and_mail(self, data, **kwargs): # si account management = true, URL_USERSHUB et MAIL_CONFIG sont necessaire if data["ACCOUNT_MANAGEMENT"].get("ENABLE_SIGN_UP", False) or data[ "ACCOUNT_MANAGEMENT" ].get("ENABLE_USER_MANAGEMENT", False): if ( data["USERSHUB"].get("URL_USERSHUB", None) is None or data["USERSHUB"].get("ADMIN_APPLICATION_LOGIN", None) is None or data["USERSHUB"].get("ADMIN_APPLICATION_PASSWORD", None) is None ): raise ValidationError( ( "URL_USERSHUB, ADMIN_APPLICATION_LOGIN et ADMIN_APPLICATION_PASSWORD sont necessaires si ENABLE_SIGN_UP=True " "ou si ENABLE_USER_MANAGEMENT=True" ), "URL_USERSHUB", ) if data["MAIL_CONFIG"].get("MAIL_SERVER", None) is None: raise ValidationError( "Veuillez remplir la rubrique MAIL_CONFIG si ENABLE_SIGN_UP=True", "ENABLE_SIGN_UP", )
[docs] class GnFrontEndConf(Schema):
[docs] PROD_MOD = fields.Boolean(load_default=True)
[docs] DISPLAY_STAT_BLOC = fields.Boolean(load_default=True)
[docs] STAT_BLOC_TTL = fields.Integer(load_default=3600)
[docs] DISPLAY_MAP_LAST_OBS = fields.Boolean(load_default=True)
[docs] MULTILINGUAL = fields.Boolean(load_default=False)
[docs] ENABLE_PROFILES = fields.Boolean(load_default=True)
# show email on synthese and validation info obs modal
[docs] DISPLAY_EMAIL_INFO_OBS = fields.Boolean(load_default=True)
[docs] DISPLAY_EMAIL_DISPLAY_INFO = fields.List(fields.String(), load_default=["NOM_VERN"])
[docs] class ExportObservationSchema(Schema):
[docs] label = fields.String(required=True)
[docs] view_name = fields.String(required=True)
[docs] geojson_4326_field = fields.String(load_default="geojson_4326")
[docs] geojson_local_field = fields.String(load_default="geojson_local")
[docs] class Synthese(Schema): # -------------------------------------------------------------------- # SYNTHESE - SEARCH FORM
[docs] AREA_FILTERS = fields.List( fields.Dict, load_default=[{"label": "Communes", "type_code": "COM"}] )
# Nombre de résultat à afficher pour la rechercher autocompleté de taxon
[docs] TAXON_RESULT_NUMBER = fields.Integer(load_default=20)
# Afficher ou non l'arbre taxonomique
[docs] DISPLAY_TAXON_TREE = fields.Boolean(load_default=True)
# Switch the observer form input in free text input (true) or in select input (false)
[docs] SEARCH_OBSERVER_WITH_LIST = fields.Boolean(load_default=False)
# Id of the observer list -- utilisateurs.t_menus
[docs] ID_SEARCH_OBSERVER_LIST = fields.Integer(load_default=1)
# Regulatory or not status list of fields
[docs] STATUS_FILTERS = fields.List( fields.Dict, load_default=[ { "id": "protections", "show": True, "display_name": "Taxons protégés", "status_types": ["PN", "PR", "PD"], }, { "id": "regulations", "show": True, "display_name": "Taxons réglementés", "status_types": ["REGLII", "REGLLUTTE", "REGL", "REGLSO"], }, { "id": "znief", "show": True, "display_name": "Espèces déterminantes ZNIEFF", "status_types": ["ZDET"], }, ], )
# Red lists list of fields
[docs] RED_LISTS_FILTERS = fields.List( fields.Dict, load_default=[ { "id": "worldwide", "show": True, "display_name": "Liste rouge mondiale", "status_type": "LRM", }, { "id": "european", "show": True, "display_name": "Liste rouge européenne", "status_type": "LRE", }, { "id": "national", "show": True, "display_name": "Liste rouge nationale", "status_type": "LRN", }, { "id": "regional", "show": True, "display_name": "Liste rouge régionale", "status_type": "LRR", }, ], )
# Filtres par défaut pour la synthese
[docs] DEFAULT_FILTERS = fields.Dict(load_default={})
# -------------------------------------------------------------------- # SYNTHESE - OBSERVATIONS LIST # Colonnes affichées par défaut sur la liste des résultats de la synthese # Champs disponibles: tous ceux de la vue 'v_synthese_for_web_app
[docs] LIST_COLUMNS_FRONTEND = fields.List(fields.Dict, load_default=DEFAULT_LIST_COLUMN)
# Colonnes affichables sur la liste des résultats de la synthese via la modale de selection des colonnes
[docs] ADDITIONAL_COLUMNS_FRONTEND = fields.List(fields.Dict, load_default=[])
# -------------------------------------------------------------------- # SYNTHESE - DOWNLOADS (AKA EXPORTS)
[docs] EXPORT_COLUMNS = fields.List(fields.String(), load_default=DEFAULT_EXPORT_COLUMNS)
[docs] EXPORT_OBSERVATIONS_CUSTOM_VIEWS = fields.List( fields.Nested(ExportObservationSchema), load_default=[] )
# Certaines colonnes sont obligatoires pour effectuer les filtres CRUVED
[docs] EXPORT_ID_SYNTHESE_COL = fields.String(load_default="id_synthese")
[docs] EXPORT_ID_DATASET_COL = fields.String(load_default="jdd_id")
[docs] EXPORT_ID_DIGITISER_COL = fields.String(load_default="id_digitiser")
[docs] EXPORT_OBSERVERS_COL = fields.String(load_default="observateurs")
[docs] EXPORT_GEOJSON_4326_COL = fields.String(load_default="geojson_4326")
[docs] EXPORT_GEOJSON_LOCAL_COL = fields.String(load_default="geojson_local")
[docs] EXPORT_METADATA_ID_DATASET_COL = fields.String(load_default="jdd_id")
[docs] EXPORT_METADATA_ACTOR_COL = fields.String(load_default="acteurs")
# Formats d'export disponibles ["csv", "geojson", "shapefile", "gpkg"]
[docs] EXPORT_FORMAT = fields.List(fields.String(), load_default=["csv", "geojson", "shapefile"])
# Nombre max d'observation dans les exports
[docs] NB_MAX_OBS_EXPORT = fields.Integer(load_default=50000)
# -------------------------------------------------------------------- # SYNTHESE - OBSERVATION DETAILS # Liste des id attributs Taxhub à afficher sur la fiche détaile de la synthese # et sur les filtres taxonomiques avancés
[docs] ID_ATTRIBUT_TAXHUB = fields.List(fields.Integer(), load_default=[102, 103])
# Display email on synthese and validation info obs modal
[docs] DISPLAY_EMAIL = fields.Boolean(load_default=True)
# -------------------------------------------------------------------- # SYNTHESE - SHARED PARAMETERS # Nom des colonnes de la table gn_synthese.synthese que l'on veux retirer des filtres dynamiques # et de la modale d'information détaillée d'une observation example = "[non_digital_proof]"
[docs] EXCLUDED_COLUMNS = fields.List(fields.String(), load_default=[])
# Nombre max d'observation à afficher sur la carte
[docs] NB_MAX_OBS_MAP = fields.Integer(load_default=50000)
# Clusteriser les layers sur la carte
[docs] ENABLE_LEAFLET_CLUSTER = fields.Boolean(load_default=True)
# Nombre des "dernières observations" affichées à l'arrivée sur la synthese
[docs] NB_LAST_OBS = fields.Integer(load_default=100)
# Display email on synthese and validation info obs modal DISPLAY_EMAIL = fields.Boolean(load_default=True) # Limit comment max length for the discussion tab
[docs] DISCUSSION_MAX_LENGTH = fields.Integer(load_default=1500)
# Allow disable discussion tab for synthese or validation
[docs] DISCUSSION_MODULES = fields.List(fields.String(), load_default=["SYNTHESE", "VALIDATION"])
# Allow disable alert synthese module for synthese or validation or any
[docs] ALERT_MODULES = fields.List(fields.String(), load_default=["SYNTHESE", "VALIDATION"])
# Allow to activate pin tool for any, some or all VALIDATION, SYNTHESE
[docs] PIN_MODULES = fields.List(fields.String(), load_default=["SYNTHESE", "VALIDATION"])
# Enable areas vizualisation with toggle slide
[docs] AREA_AGGREGATION_ENABLED = fields.Boolean(load_default=True)
# Choose size of areas
[docs] AREA_AGGREGATION_TYPE = fields.String(load_default="M10")
# Activate areas mode by default
[docs] AREA_AGGREGATION_BY_DEFAULT = fields.Boolean(load_default=False)
# Areas legend classes to use
[docs] AREA_AGGREGATION_LEGEND_CLASSES = fields.List( fields.Dict(), load_default=[ {"min": 100, "color": "#800026"}, {"min": 50, "color": "#BD0026"}, {"min": 20, "color": "#E31A1C"}, {"min": 10, "color": "#FC4E2A"}, {"min": 5, "color": "#FD8D3C"}, {"min": 2, "color": "#FEB24C"}, {"min": 1, "color": "#FED976"}, {"min": 0, "color": "#FFEDA0"}, ], )
# Activate the blurring of sensitive observations. Otherwise, exclude them
[docs] BLUR_SENSITIVE_OBSERVATIONS = fields.Boolean(load_default=True)
@pre_load
[docs] def warn_deprecated(self, data, **kwargs): deprecated = { "EXPORT_ID_SYNTHESE_COL", "EXPORT_ID_DIGITISER_COL", "EXPORT_OBSERVERS_COL", "EXPORT_GEOJSON_4326_COL", "EXPORT_GEOJSON_LOCAL_COL", } for deprecated_field in deprecated & set(data.keys()): warn( f"{deprecated_field} is deprecated - " "Please use `EXPORT_OBSERVATIONS_CUSTOM_VIEWS` parameter to customize your synthese exports " ) return data
# Map configuration
[docs] BASEMAP = [ { "name": "OpenStreetMap", "url": "//{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png", "options": { "attribution": "<a href='https://www.openstreetmap.org/copyright' target='_blank'>© OpenStreetMap contributors</a>", }, }, { "name": "OpenTopoMap", "url": "//a.tile.opentopomap.org/{z}/{x}/{y}.png", "options": { "attribution": "Map data: © <a href='https://www.openstreetmap.org/copyright' target='_blank'>OpenStreetMap contributors</a>, SRTM | Map style: © <a href='https://opentopomap.org' target='_blank'>OpenTopoMap</a> (<a href='https://creativecommons.org/licenses/by-sa/3.0/' target='_blank'>CC-BY-SA</a>)", }, }, { "name": "GoogleSatellite", "layer": "//{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}", "options": { "subdomains": ["mt0", "mt1", "mt2", "mt3"], "attribution": "© Google Maps", }, }, ]
[docs] class MapConfig(Schema):
[docs] BASEMAP = fields.List(fields.Dict(), load_default=BASEMAP)
[docs] CENTER = fields.List(fields.Float, load_default=[46.52863469527167, 2.43896484375])
[docs] ZOOM_LEVEL = fields.Integer(load_default=6)
[docs] ZOOM_LEVEL_RELEVE = fields.Integer(load_default=15)
[docs] GEOLOCATION = fields.Boolean(load_default=False)
# zoom appliqué sur la carte lorsque l'on clique sur une liste # ne s'applique qu'aux points
[docs] ZOOM_ON_CLICK = fields.Integer(load_default=18)
# Restreindre la recherche OpenStreetMap (sur la carte dans l'encart "Rechercher un lieu") # à certains pays. Les pays doivent être au format ISO_3166-1 : # https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 et séparés par une virgule. # Exemple : OSM_RESTRICT_COUNTRY_CODES = "fr,es,be,ch" (Restreint à France, Espagne, Belgique # et Suisse) # Laisser à null pour n'avoir aucune restriction
[docs] OSM_RESTRICT_COUNTRY_CODES = fields.String(load_default=None)
[docs] REF_LAYERS = fields.List( fields.Dict(), load_default=[ { "code": "limitesadministratives", "label": "Limites administratives (IGN)", "type": "wms", "url": "https://data.geopf.fr/wms-r", "activate": False, "params": { "service": "wms", "version": "1.3.0", "request": "GetMap", "layers": "LIMITES_ADMINISTRATIVES_EXPRESS.LATEST", "styles": "normal", "format": "image/png", "crs": "CRS:84", "dpiMode": 7, }, }, { "code": "znieff1", "label": "ZNIEFF1 (INPN)", "type": "wms", "url": "https://ws.carmencarto.fr/WMS/119/fxx_inpn", "activate": False, "params": { "service": "wms", "version": "1.3.0", "request": "GetMap", "layers": "znieff1", "format": "image/png", "crs": "EPSG:4326", "opacity": 0.2, "transparent": True, }, }, ], )
[docs] REF_LAYERS_LEGEND = fields.Boolean(load_default=False)
[docs] class TaxHub(Schema):
[docs] ID_TYPE_MAIN_PHOTO = fields.Integer(load_default=1)
# class a utiliser pour les paramètres que l'on veut passer au frontend
[docs] class GnGeneralSchemaConf(Schema):
[docs] appName = fields.String(load_default="GeoNature2")
[docs] GEONATURE_VERSION = fields.String(load_default=GEONATURE_VERSION.strip())
[docs] DEFAULT_LANGUAGE = fields.String(load_default="fr")
[docs] PASS_METHOD = fields.String(load_default="hash", validate=OneOf(["hash", "md5"]))
[docs] DEBUG = fields.Boolean(load_default=False)
[docs] URL_APPLICATION = fields.Url(required=True)
[docs] API_ENDPOINT = fields.Url(required=True)
[docs] API_TAXHUB = fields.Url(required=True)
[docs] CODE_APPLICATION = fields.String(load_default="GN")
[docs] XML_NAMESPACE = fields.String(load_default="{http://inpn.mnhn.fr/mtd}")
[docs] MTD_API_ENDPOINT = fields.Url(load_default="https://preprod-inpn.mnhn.fr/mtd")
[docs] DISABLED_MODULES = fields.List(fields.String(), load_default=[])
[docs] CAS_PUBLIC = fields.Nested(CasFrontend, load_default=CasFrontend().load({}))
[docs] RIGHTS = fields.Nested(RightsSchemaConf, load_default=RightsSchemaConf().load({}))
[docs] FRONTEND = fields.Nested(GnFrontEndConf, load_default=GnFrontEndConf().load({}))
[docs] SYNTHESE = fields.Nested(Synthese, load_default=Synthese().load({}))
[docs] MAPCONFIG = fields.Nested(MapConfig, load_default=MapConfig().load({}))
# Ajoute la surchouche 'taxonomique' sur l'API nomenclature
[docs] ENABLE_NOMENCLATURE_TAXONOMIC_FILTERS = fields.Boolean(load_default=True)
[docs] BDD = fields.Nested(BddConfig, load_default=BddConfig().load({}))
[docs] URL_USERSHUB = fields.Url(required=False)
[docs] ACCOUNT_MANAGEMENT = fields.Nested(AccountManagement, load_default=AccountManagement().load({}))
[docs] MEDIAS = fields.Nested(MediasConfig, load_default=MediasConfig().load({}))
[docs] STATIC_URL = fields.String(load_default="/static")
[docs] MEDIA_URL = fields.String(load_default="/media")
[docs] METADATA = fields.Nested(MetadataConfig, load_default=MetadataConfig().load({}))
[docs] MTD = fields.Nested(MTDSchemaConf, load_default=MTDSchemaConf().load({}))
[docs] NB_MAX_DATA_SENSITIVITY_REPORT = fields.Integer(load_default=1000000)
[docs] ADDITIONAL_FIELDS = fields.Nested(AdditionalFields, load_default=AdditionalFields().load({}))
[docs] PUBLIC_ACCESS_USERNAME = fields.String(load_default="")
[docs] TAXHUB = fields.Nested(TaxHub, load_default=TaxHub().load({}))
[docs] HOME = fields.Nested(HomeConfig, load_default=HomeConfig().load({}))
[docs] NOTIFICATIONS_ENABLED = fields.Boolean(load_default=True)
[docs] PROFILES_REFRESH_CRONTAB = fields.String(load_default="0 3 * * *")
[docs] MEDIA_CLEAN_CRONTAB = fields.String(load_default="0 1 * * *")
@validates_schema
[docs] def validate_enable_sign_up(self, data, **kwargs): # si CAS_PUBLIC = true and ENABLE_SIGN_UP = true if data["CAS_PUBLIC"]["CAS_AUTHENTIFICATION"] and ( data["ACCOUNT_MANAGEMENT"]["ENABLE_SIGN_UP"] or data["ACCOUNT_MANAGEMENT"]["ENABLE_USER_MANAGEMENT"] ): raise ValidationError( "CAS_PUBLIC et ENABLE_SIGN_UP ou ENABLE_USER_MANAGEMENT ne peuvent être activés ensemble", "ENABLE_SIGN_UP, ENABLE_USER_MANAGEMENT", )
@validates_schema
[docs] def validate_account_autovalidation(self, data, **kwargs): account_config = data["ACCOUNT_MANAGEMENT"] if ( account_config["AUTO_ACCOUNT_CREATION"] is False and account_config["VALIDATOR_EMAIL"] is None ): raise ValidationError( "Si AUTO_ACCOUNT_CREATION = False, veuillez remplir le paramètre VALIDATOR_EMAIL", "AUTO_ACCOUNT_CREATION, VALIDATOR_EMAIL", )
@post_load
[docs] def insert_module_config(self, data, **kwargs): for dist in iter_modules_dist(): module_code = dist.entry_points["code"].load() if module_code in data["DISABLED_MODULES"]: continue data[module_code] = get_module_config(dist) return data