Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Config in toml file #517

Merged
merged 5 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ on:
- master
- hotfixes
- develop
- flask-admin

jobs:
build:
Expand Down Expand Up @@ -89,17 +90,17 @@ jobs:
flask db autoupgrade
flask db status
env:
TAXHUB_SETTINGS: test_config.py
TAXHUB_CONFIG_FILE: config/test_config.toml
- name: Install taxref
run: |
flask taxref import-v17
env:
TAXHUB_SETTINGS: test_config.py
TAXHUB_CONFIG_FILE: config/test_config.toml
- name: Test with pytest
run: |
pytest -v --cov --cov-report xml
env:
TAXHUB_SETTINGS: test_config.py
TAXHUB_CONFIG_FILE: config/test_config.toml
- name: Upload coverage to Codecov
if: ${{ matrix.name == '11' && matrix.sqlalchemy-version == '1.4' }}
uses: codecov/codecov-action@v3
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,4 @@ target/

/docs/changelog.html

/apptax/*_config.py
config/*_config.toml
15 changes: 7 additions & 8 deletions apptax/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
taxhub_routes = [
("apptax.taxonomie.routesbibnoms:adresses", "/api/bibnoms"),
("apptax.taxonomie.routestaxref:adresses", "/api/taxref"),
("apptax.taxonomie.routesbibattributs:adresses", "/api/bibattributs"),
("apptax.taxonomie.routesbiblistes:adresses", "/api/biblistes"),
("apptax.taxonomie.routestmedias:adresses", "/api/tmedias"),
("apptax.taxonomie.routesbdcstatuts:adresses", "/api/bdc_statuts"),
("apptax.admin.admin:adresses", "/"),
taxhub_api_routes = [
("apptax.taxonomie.routesbibnoms:adresses", "/bibnoms"),
("apptax.taxonomie.routestaxref:adresses", "/taxref"),
("apptax.taxonomie.routesbibattributs:adresses", "/bibattributs"),
("apptax.taxonomie.routesbiblistes:adresses", "/biblistes"),
("apptax.taxonomie.routestmedias:adresses", "/tmedias"),
("apptax.taxonomie.routesbdcstatuts:adresses", "/bdc_statuts"),
]
22 changes: 15 additions & 7 deletions apptax/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from pypnusershub.login_manager import login_manager

from apptax.admin.admin import taxhub_admin, taxhub_admin_addview
from apptax.utils.config.utilstoml import load_and_validate_toml
from apptax.utils.config.config_schema import TaxhubSchemaConf

migrate = Migrate()

Expand Down Expand Up @@ -43,7 +45,10 @@ def configure_alembic(alembic_config):
def create_app():
app = Flask(__name__, static_folder=os.environ.get("TAXHUB_STATIC_FOLDER", "static"))

app.config.from_pyfile(os.environ.get("TAXHUB_SETTINGS", "config.py"))
DEFAULT_CONFIG_FILE = Path(__file__).absolute().parent.parent / "config/taxhub_config.toml"
CONFIG_FILE = os.environ.get("TAXHUB_CONFIG_FILE", DEFAULT_CONFIG_FILE)
config = load_and_validate_toml(CONFIG_FILE, TaxhubSchemaConf)
app.config.update(config)
app.config.from_prefixed_env(prefix="TAXHUB")

media_path = Path(app.config["MEDIA_FOLDER"], "taxhub").absolute()
Expand All @@ -66,9 +71,6 @@ def create_app():

app.config["DB"] = db

if "CODE_APPLICATION" not in app.config:
app.config["CODE_APPLICATION"] = "TH"

@app.before_request
def load_current_user():
g.current_user = current_user if current_user.is_authenticated else None
Expand All @@ -83,20 +85,26 @@ def favicon():
mimetype="image/vnd.microsoft.icon",
)

# UserHub
from pypnusershub import routes

app.register_blueprint(routes.routes, url_prefix="/api/auth")

# Flask admin
taxhub_admin.init_app(app)
taxhub_admin_addview(app, taxhub_admin)
from apptax.admin.admin import adresses

app.register_blueprint(adresses, url_prefix="/")

# API
from apptax import taxhub_routes
from apptax import taxhub_api_routes

base_api_prefix = app.config["API"].get("API_PREFIX")

for blueprint_path, url_prefix in taxhub_routes:
for blueprint_path, url_prefix in taxhub_api_routes:
module_name, blueprint_name = blueprint_path.split(":")
blueprint = getattr(import_module(module_name), blueprint_name)
app.register_blueprint(blueprint, url_prefix=url_prefix)
app.register_blueprint(blueprint, url_prefix=base_api_prefix + url_prefix)

return app
Empty file added apptax/utils/config/__init__.py
Empty file.
40 changes: 40 additions & 0 deletions apptax/utils/config/config_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""
Description des options de configuration
"""

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


class TaxhubApiConf(Schema):
API_PREFIX = fields.String(
load_default="",
validate=Regexp(
r"(^\/(.+)$)|(^\s*$)",
error="API_PREFIX must start with a slash.",
),
)


class TaxhubSchemaConf(Schema):
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",
),
)
SQLALCHEMY_TRACK_MODIFICATIONS = fields.Boolean(load_default=True)
SESSION_TYPE = fields.String(load_default="filesystem")
SECRET_KEY = fields.String(required=True, validate=Length(min=20))
CODE_APPLICATION = fields.String(load_default="TH")
# le cookie expire toute les 7 jours par défaut
COOKIE_EXPIRATION = fields.Integer(load_default=3600 * 24 * 7)
COOKIE_AUTORENEW = fields.Boolean(load_default=True)
TRAP_ALL_EXCEPTIONS = fields.Boolean(load_default=False)
APPLICATION_ROOT = fields.String(load_default="/")
MEDIA_FOLDER = fields.String(load_default="media")
PASS_METHOD = fields.String(load_default="hash")
FLASK_ADMIN_SWATCH = fields.String(load_default="cerulean")
FLASK_ADMIN_FLUID_LAYOUT = fields.Boolean(load_default=True)
API = fields.Nested(TaxhubApiConf, load_default=TaxhubApiConf().load({}))
48 changes: 48 additions & 0 deletions apptax/utils/config/utilstoml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from pathlib import Path

import toml
from marshmallow import EXCLUDE
from marshmallow.exceptions import ValidationError


class ConfigError(Exception):
"""
Configuration error class
Quand un fichier de configuration n'est pas conforme aux attentes
"""

def __init__(self, file, value):
self.value = value
self.file = file

def __str__(self):
msg = "Error in the config file '{}'. Fix the following:\n"
msg = msg.format(self.file)
for key, errors in self.value.items():
msg += "\n\t{}:\n\t\t- {}".format(key, errors)
return msg


def load_and_validate_toml(toml_file, config_schema, partial=None):
"""
Fonction qui charge un fichier toml
et le valide avec un Schema marshmallow
"""
if toml_file:
toml_config = load_toml(toml_file)
else:
toml_config = {}
try:
configs_py = config_schema().load(toml_config, unknown=EXCLUDE, partial=partial)
except ValidationError as e:
raise ConfigError(toml_file, e.messages)
return configs_py


def load_toml(toml_file):
"""
Fonction qui charge un fichier toml
"""
if not Path(toml_file).is_file():
raise Exception("Missing file {}".format(toml_file))
return toml.load(str(toml_file))
14 changes: 14 additions & 0 deletions config/taxhub_config.toml.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

#############################################
# Taxhub backend global configuration file
#############################################

# Database
SQLALCHEMY_DATABASE_URI = "postgresql://monuser:monpassachanger@localhost:5432/mabase"

# Remplacer par une clé alétoire complexe
SECRET_KEY = 'super secret key'

# Configuration liée à l'api de taxhub
[API]
API_PREFIX = "/api"
3 changes: 0 additions & 3 deletions apptax/test_config.py → config/test_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,3 @@

SECRET_KEY = 'a7e0a755dd3f2c382bac5b5cea6c9329802aeedf39e3f10d0462ffb52c3f5e99'

COOKIE_EXPIRATION = 3600

MEDIA_FOLDER = 'medias'
2 changes: 1 addition & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- Changement dans les permissions : seuls les profils 2 et 6 sont utilisés. Il faut un profil 2 pour ajouter des attributs / medias et ajouter des taxons à des listes. Il faut un profil 6 pour pouvoir créer des listes / thêmes / type d'attributs.
- Le paramètre `UPLOAD_FOLDER` devient `MEDIA_FOLDER`. Veillez à le remplacer dans le fichier `config.py`. Si vous utilisez TaxHub avec GeoNature, ce paramètre existe déjà et est par défaut à `<GEONATURE_DIR>/backend/medias`.


- La configuration est maintenant gérée dans le fichier `config/taxhub_config.toml` (#517)

1.14.1 (2024-05-23)
===================
Expand Down
3 changes: 2 additions & 1 deletion requirements-common.in
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ psycopg2
python-dotenv
Pillow<10.0.0
urllib3
click>=8.1.3
click>=8.1.3
toml
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ werkzeug==3.0.3
zipp==3.18.2
# via importlib-metadata



Flask-Admin==1.6.0
WTForms==3.0.1
# via flask-admin

toml==0.10.2
Loading