Initial commit

This commit is contained in:
Kristof committed 2026-10-14 12:29:29 +02:00
commit 536ff43ce4
158 files changed
+30355

No files matched your search

+107
View File
@@ -0,0 +1,107 @@
"""
Instellingen.
config.ini bevat enkel nog wat voor ALLE scholen geldt (database-server, centrale
database, gedeelde Google-login, superbeheerders). Alles wat per school verschilt
staat in de centrale database (zie tenancy.py) en wordt beheerd via /scholen.
`Config.SS_API_PW`, `Config.SCHOOL_DOMAIN`, ... geven de waarde van de school
waarvoor de huidige request (of achtergrondtaak) loopt.
Geheimen kunnen ook via omgevingsvariabelen gezet worden (handig voor Docker):
PIVOT_DB_PASSWORD, FLASK_SECRET_KEY, PIVOT_SLEUTEL, PIVOT_SSO_CLIENT_SECRET
"""
import os
import configparser
base_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.environ.get('PIVOT_CONFIG', os.path.join(base_dir, 'config.ini'))
config_file = configparser.ConfigParser()
config_file.read(config_path, encoding='utf-8')
def _get(section, key, fallback='', env=None):
if env and os.environ.get(env):
return os.environ[env]
return config_file.get(section, key, fallback=fallback)
def _secret_key():
"""FLASK_SECRET_KEY, config.ini, of anders een willekeurige sleutel die bewaard wordt in geheimen/flask.key.
(Nooit een vaste standaardsleutel: daarmee kan iemand een sessie voor eender welke school vervalsen.)"""
sleutel = os.environ.get("FLASK_SECRET_KEY") or _get('algemeen', 'secret_key')
if sleutel:
return sleutel
import secrets
pad = os.path.join(os.environ.get('PIVOT_GEHEIMEN', os.path.join(base_dir, 'geheimen')), 'flask.key')
if os.path.exists(pad):
with open(pad) as f:
return f.read().strip()
os.makedirs(os.path.dirname(pad), exist_ok=True)
sleutel = secrets.token_hex(32)
with open(pad, 'w') as f:
f.write(sleutel)
return sleutel
class _SchoolConfigMeta(type):
"""Onbekende attributen op de klasse → instelling van de huidige school."""
def __getattr__(cls, naam):
if naam.startswith('__'):
raise AttributeError(naam)
if naam == 'GOOGLE_API_LOCATION':
raise AttributeError("GOOGLE_API_LOCATION bestaat niet meer: gebruik tenancy.google_credentials()")
from tenancy import huidige_school, VELD, AFGELEID
if naam not in VELD and naam not in AFGELEID:
raise AttributeError(naam)
return huidige_school().get(naam)
class Config(metaclass=_SchoolConfigMeta):
"""Algemene instellingen (klasse-attributen) + per-school instellingen (via de metaclass)."""
# Flask
SECRET_KEY = _secret_key()
DEBUG = _get('algemeen', 'debug', 'nee').strip().lower() in ('ja', 'yes', 'true', '1', 'on')
SESSION_COOKIE_PATH = '/'
SESSION_PERMANENT = True
# Database-server: standaard voor alle schooldatabases + de centrale database
DB_HOST = _get('database', 'host', 'localhost', env='PIVOT_DB_HOST')
DB_PORT = int(_get('database', 'port', '3306', env='PIVOT_DB_PORT'))
DB_USER = _get('database', 'user', '', env='PIVOT_DB_USER')
DB_PASSWORD = _get('database', 'password', '', env='PIVOT_DB_PASSWORD')
DB_CENTRAAL = _get('database', 'centrale_database', 'pivot_centraal', env='PIVOT_DB_CENTRAAL')
# Verbindingen per database in de pool. Elke pool opent die meteen allemaal: aantal scholen x pool_size
# (+ centraal) moet onder max_connections van MySQL blijven (standaard 151).
DB_POOL_SIZE = max(1, min(32, int(_get('database', 'pool_size', '3', env='PIVOT_DB_POOL_SIZE') or 3)))
# Gedeelde Google-login (één OAuth-client voor alle scholen; per school te overschrijven)
SSO_CLIENT_ID = _get('google_sso', 'client_id', env='PIVOT_SSO_CLIENT_ID')
SSO_CLIENT_SECRET = _get('google_sso', 'client_secret', env='PIVOT_SSO_CLIENT_SECRET')
# Superbeheerders: mogen scholen beheren en tussen scholen wisselen (Google-login)
SUPERBEHEERDERS = [x.strip().lower() for x in
_get('algemeen', 'superbeheerders', env='PIVOT_SUPERBEHEERDERS').replace(';', ',').split(',')
if x.strip()]
APP_VERSION = _get('algemeen', 'app_version', '1.1.0')
# Elke bezochte pagina bewaren in de tabel Logs (centrale database)
LOGBOEK = _get('algemeen', 'logboek', 'ja').strip().lower() in ('ja', 'yes', 'true', '1', 'on')
# Aantal reverse proxies (nginx, IIS, firewall met https, ...) vóór PIVOT. 0 = PIVOT staat rechtstreeks op het net.
# Nodig om het echte IP-adres van de bezoeker te kennen (IP-blokkades, logboek, inlogbeveiliging).
try:
PROXY_AANTAL = max(0, int(_get('algemeen', 'proxy_aantal', '0') or 0))
except ValueError:
PROXY_AANTAL = 0
def __getattr__(self, naam):
# Config().SS_API_PW werkt ook (zoals in de bestaande services)
return getattr(type(self), naam)
@property
def DB_CONFIG(self):
from tenancy import huidige_school
return huidige_school().db_config()