- Superadmin-only organization name setting displayed in dashboard header - Advanced Options tab with configurable scheduler refresh interval (0 = disabled) - Make system settings GET endpoint public for frontend reads - Scheduler reads refresh_seconds from DB dynamically each loop - Seed default system settings in init_defaults.py
330 lines
9.4 KiB
Python
330 lines
9.4 KiB
Python
"""
|
|
System Settings API endpoints.
|
|
Provides key-value storage for system-wide configuration.
|
|
"""
|
|
from flask import Blueprint, jsonify, request
|
|
from server.database import Session
|
|
from models.models import SystemSetting
|
|
from server.permissions import admin_or_higher, superadmin_only
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
|
|
system_settings_bp = Blueprint('system_settings', __name__, url_prefix='/api/system-settings')
|
|
|
|
|
|
@system_settings_bp.route('', methods=['GET'])
|
|
@admin_or_higher
|
|
def get_all_settings():
|
|
"""
|
|
Get all system settings.
|
|
Admin+ only.
|
|
"""
|
|
session = Session()
|
|
try:
|
|
settings = session.query(SystemSetting).all()
|
|
return jsonify({
|
|
'settings': [s.to_dict() for s in settings]
|
|
}), 200
|
|
except SQLAlchemyError as e:
|
|
return jsonify({'error': str(e)}), 500
|
|
finally:
|
|
session.close()
|
|
|
|
|
|
@system_settings_bp.route('/<key>', methods=['GET'])
|
|
def get_setting(key):
|
|
"""
|
|
Get a specific system setting by key.
|
|
Public endpoint - settings are read-only configuration.
|
|
"""
|
|
session = Session()
|
|
try:
|
|
setting = session.query(SystemSetting).filter_by(key=key).first()
|
|
if not setting:
|
|
return jsonify({'error': 'Setting not found'}), 404
|
|
return jsonify(setting.to_dict()), 200
|
|
except SQLAlchemyError as e:
|
|
return jsonify({'error': str(e)}), 500
|
|
finally:
|
|
session.close()
|
|
|
|
|
|
@system_settings_bp.route('/<key>', methods=['POST', 'PUT'])
|
|
@admin_or_higher
|
|
def update_setting(key):
|
|
"""
|
|
Create or update a system setting.
|
|
Admin+ only.
|
|
|
|
Request body:
|
|
{
|
|
"value": "string",
|
|
"description": "string" (optional)
|
|
}
|
|
"""
|
|
session = Session()
|
|
try:
|
|
data = request.get_json()
|
|
if not data:
|
|
return jsonify({'error': 'No data provided'}), 400
|
|
|
|
value = data.get('value')
|
|
description = data.get('description')
|
|
|
|
# Try to find existing setting
|
|
setting = session.query(SystemSetting).filter_by(key=key).first()
|
|
|
|
if setting:
|
|
# Update existing
|
|
setting.value = value
|
|
if description is not None:
|
|
setting.description = description
|
|
else:
|
|
# Create new
|
|
setting = SystemSetting(
|
|
key=key,
|
|
value=value,
|
|
description=description
|
|
)
|
|
session.add(setting)
|
|
|
|
session.commit()
|
|
return jsonify(setting.to_dict()), 200
|
|
except SQLAlchemyError as e:
|
|
session.rollback()
|
|
return jsonify({'error': str(e)}), 500
|
|
finally:
|
|
session.close()
|
|
|
|
|
|
@system_settings_bp.route('/<key>', methods=['DELETE'])
|
|
@admin_or_higher
|
|
def delete_setting(key):
|
|
"""
|
|
Delete a system setting.
|
|
Admin+ only.
|
|
"""
|
|
session = Session()
|
|
try:
|
|
setting = session.query(SystemSetting).filter_by(key=key).first()
|
|
if not setting:
|
|
return jsonify({'error': 'Setting not found'}), 404
|
|
|
|
session.delete(setting)
|
|
session.commit()
|
|
return jsonify({'message': 'Setting deleted successfully'}), 200
|
|
except SQLAlchemyError as e:
|
|
session.rollback()
|
|
return jsonify({'error': str(e)}), 500
|
|
finally:
|
|
session.close()
|
|
|
|
|
|
# Convenience endpoints for specific settings
|
|
@system_settings_bp.route('/supplement-table', methods=['GET'])
|
|
@admin_or_higher
|
|
def get_supplement_table_settings():
|
|
"""
|
|
Get supplement table URL and enabled status.
|
|
Admin+ only.
|
|
"""
|
|
session = Session()
|
|
try:
|
|
url_setting = session.query(SystemSetting).filter_by(key='supplement_table_url').first()
|
|
enabled_setting = session.query(SystemSetting).filter_by(key='supplement_table_enabled').first()
|
|
|
|
return jsonify({
|
|
'url': url_setting.value if url_setting else '',
|
|
'enabled': enabled_setting.value == 'true' if enabled_setting else False,
|
|
}), 200
|
|
except SQLAlchemyError as e:
|
|
return jsonify({'error': str(e)}), 500
|
|
finally:
|
|
session.close()
|
|
|
|
|
|
@system_settings_bp.route('/supplement-table', methods=['POST'])
|
|
@admin_or_higher
|
|
def update_supplement_table_settings():
|
|
"""
|
|
Update supplement table URL and enabled status.
|
|
Admin+ only.
|
|
|
|
Request body:
|
|
{
|
|
"url": "https://...",
|
|
"enabled": true/false
|
|
}
|
|
"""
|
|
session = Session()
|
|
try:
|
|
data = request.get_json()
|
|
if not data:
|
|
return jsonify({'error': 'No data provided'}), 400
|
|
|
|
url = data.get('url', '')
|
|
enabled = data.get('enabled', False)
|
|
|
|
# Update or create URL setting
|
|
url_setting = session.query(SystemSetting).filter_by(key='supplement_table_url').first()
|
|
if url_setting:
|
|
url_setting.value = url
|
|
else:
|
|
url_setting = SystemSetting(
|
|
key='supplement_table_url',
|
|
value=url,
|
|
description='URL für Vertretungsplan / WebUntis (Stundenplan-Änderungstabelle)'
|
|
)
|
|
session.add(url_setting)
|
|
|
|
# Update or create enabled setting
|
|
enabled_setting = session.query(SystemSetting).filter_by(key='supplement_table_enabled').first()
|
|
if enabled_setting:
|
|
enabled_setting.value = 'true' if enabled else 'false'
|
|
else:
|
|
enabled_setting = SystemSetting(
|
|
key='supplement_table_enabled',
|
|
value='true' if enabled else 'false',
|
|
description='Ob Vertretungsplan aktiviert ist'
|
|
)
|
|
session.add(enabled_setting)
|
|
|
|
session.commit()
|
|
|
|
return jsonify({
|
|
'url': url,
|
|
'enabled': enabled,
|
|
'message': 'Supplement table settings updated successfully'
|
|
}), 200
|
|
except SQLAlchemyError as e:
|
|
session.rollback()
|
|
return jsonify({'error': str(e)}), 500
|
|
finally:
|
|
session.close()
|
|
|
|
|
|
@system_settings_bp.route('/holiday-banner', methods=['GET'])
|
|
def get_holiday_banner_setting():
|
|
"""
|
|
Get holiday banner enabled status.
|
|
Public endpoint - dashboard needs this.
|
|
"""
|
|
session = Session()
|
|
try:
|
|
setting = session.query(SystemSetting).filter_by(key='holiday_banner_enabled').first()
|
|
enabled = setting.value == 'true' if setting else True
|
|
|
|
return jsonify({'enabled': enabled}), 200
|
|
except SQLAlchemyError as e:
|
|
return jsonify({'error': str(e)}), 500
|
|
finally:
|
|
session.close()
|
|
|
|
|
|
@system_settings_bp.route('/holiday-banner', methods=['POST'])
|
|
@admin_or_higher
|
|
def update_holiday_banner_setting():
|
|
"""
|
|
Update holiday banner enabled status.
|
|
Admin+ only.
|
|
|
|
Request body:
|
|
{
|
|
"enabled": true/false
|
|
}
|
|
"""
|
|
session = Session()
|
|
try:
|
|
data = request.get_json()
|
|
if not data:
|
|
return jsonify({'error': 'No data provided'}), 400
|
|
|
|
enabled = data.get('enabled', True)
|
|
|
|
# Update or create setting
|
|
setting = session.query(SystemSetting).filter_by(key='holiday_banner_enabled').first()
|
|
if setting:
|
|
setting.value = 'true' if enabled else 'false'
|
|
else:
|
|
setting = SystemSetting(
|
|
key='holiday_banner_enabled',
|
|
value='true' if enabled else 'false',
|
|
description='Ferienstatus-Banner auf Dashboard anzeigen'
|
|
)
|
|
session.add(setting)
|
|
|
|
session.commit()
|
|
|
|
return jsonify({
|
|
'enabled': enabled,
|
|
'message': 'Holiday banner setting updated successfully'
|
|
}), 200
|
|
except SQLAlchemyError as e:
|
|
session.rollback()
|
|
return jsonify({'error': str(e)}), 500
|
|
finally:
|
|
session.close()
|
|
|
|
|
|
@system_settings_bp.route('/organization-name', methods=['GET'])
|
|
def get_organization_name():
|
|
"""
|
|
Get organization name.
|
|
Public endpoint - header needs this.
|
|
"""
|
|
session = Session()
|
|
try:
|
|
setting = session.query(SystemSetting).filter_by(key='organization_name').first()
|
|
name = setting.value if setting and setting.value else ''
|
|
|
|
return jsonify({'name': name}), 200
|
|
except SQLAlchemyError as e:
|
|
return jsonify({'error': str(e)}), 500
|
|
finally:
|
|
session.close()
|
|
|
|
|
|
@system_settings_bp.route('/organization-name', methods=['POST'])
|
|
@superadmin_only
|
|
def update_organization_name():
|
|
"""
|
|
Update organization name.
|
|
Superadmin only.
|
|
|
|
Request body:
|
|
{
|
|
"name": "Meine Organisation"
|
|
}
|
|
"""
|
|
session = Session()
|
|
try:
|
|
data = request.get_json()
|
|
if not data:
|
|
return jsonify({'error': 'No data provided'}), 400
|
|
|
|
name = data.get('name', '')
|
|
|
|
# Update or create setting
|
|
setting = session.query(SystemSetting).filter_by(key='organization_name').first()
|
|
if setting:
|
|
setting.value = name
|
|
else:
|
|
setting = SystemSetting(
|
|
key='organization_name',
|
|
value=name,
|
|
description='Name der Organisation (wird im Header angezeigt)'
|
|
)
|
|
session.add(setting)
|
|
|
|
session.commit()
|
|
|
|
return jsonify({
|
|
'name': name,
|
|
'message': 'Organization name updated successfully'
|
|
}), 200
|
|
except SQLAlchemyError as e:
|
|
session.rollback()
|
|
return jsonify({'error': str(e)}), 500
|
|
finally:
|
|
session.close()
|
|
|