Add System Settings. Enable/Disable User registration.

This commit is contained in:
Jens Luedicke
2025-06-28 11:30:34 +02:00
parent ff80964956
commit e7593dc840
6 changed files with 201 additions and 7 deletions

49
app.py
View File

@@ -1,5 +1,5 @@
from flask import Flask, render_template, request, redirect, url_for, jsonify, flash, session, g
from models import db, TimeEntry, WorkConfig, User
from models import db, TimeEntry, WorkConfig, User, SystemSettings
import logging
from datetime import datetime, time, timedelta
import os
@@ -42,6 +42,23 @@ mail = Mail(app)
# Initialize the database with the app
db.init_app(app)
# Add this function to initialize system settings
def init_system_settings():
# Check if registration_enabled setting exists, if not create it
if not SystemSettings.query.filter_by(key='registration_enabled').first():
registration_setting = SystemSettings(
key='registration_enabled',
value='true',
description='Controls whether new user registration is allowed'
)
db.session.add(registration_setting)
db.session.commit()
# Call this function during app initialization (add it where you initialize the app)
@app.before_first_request
def initialize_app():
init_system_settings()
# Authentication decorator
def login_required(f):
@wraps(f)
@@ -123,6 +140,14 @@ def logout():
@app.route('/register', methods=['GET', 'POST'])
def register():
# Check if registration is enabled
reg_setting = SystemSettings.query.filter_by(key='registration_enabled').first()
registration_enabled = reg_setting and reg_setting.value == 'true'
if not registration_enabled:
flash('Registration is currently disabled by the administrator.', 'error')
return redirect(url_for('login'))
if request.method == 'POST':
username = request.form.get('username')
email = request.form.get('email')
@@ -681,5 +706,27 @@ def toggle_user_status(user_id):
return redirect(url_for('admin_users'))
# Add this route to manage system settings
@app.route('/admin/settings', methods=['GET', 'POST'])
@admin_required
def admin_settings():
if request.method == 'POST':
# Update registration setting
registration_enabled = 'registration_enabled' in request.form
reg_setting = SystemSettings.query.filter_by(key='registration_enabled').first()
if reg_setting:
reg_setting.value = 'true' if registration_enabled else 'false'
db.session.commit()
flash('System settings updated successfully!', 'success')
# Get current settings
settings = {}
for setting in SystemSettings.query.all():
if setting.key == 'registration_enabled':
settings['registration_enabled'] = setting.value == 'true'
return render_template('admin_settings.html', title='System Settings', settings=settings)
if __name__ == '__main__':
app.run(debug=True)

View File

@@ -1,7 +1,7 @@
from app import app, db
import sqlite3
import os
from models import User, TimeEntry, WorkConfig
from models import User, TimeEntry, WorkConfig, SystemSettings
from werkzeug.security import generate_password_hash
from datetime import datetime
@@ -13,6 +13,9 @@ def migrate_database():
print("Database doesn't exist. Creating new database.")
with app.app_context():
db.create_all()
# Initialize system settings
init_system_settings()
return
print("Migrating existing database...")
@@ -104,6 +107,20 @@ def migrate_database():
print("Adding is_blocked column to user table...")
cursor.execute("ALTER TABLE user ADD COLUMN is_blocked BOOLEAN DEFAULT 0")
# Check if the system_settings table exists
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='system_settings'")
if not cursor.fetchone():
print("Creating system_settings table...")
cursor.execute("""
CREATE TABLE system_settings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key VARCHAR(50) UNIQUE NOT NULL,
value VARCHAR(255) NOT NULL,
description VARCHAR(255),
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
# Commit changes and close connection
conn.commit()
conn.close()
@@ -112,6 +129,9 @@ def migrate_database():
# Create tables if they don't exist
db.create_all()
# Initialize system settings
init_system_settings()
# Check if admin user exists
admin = User.query.filter_by(username='admin').first()
if not admin:
@@ -154,6 +174,21 @@ def migrate_database():
print(f"Associated {len(orphan_configs)} existing work configs with admin user")
print(f"Marked {len(existing_users)} existing users as verified")
def init_system_settings():
"""Initialize system settings with default values if they don't exist"""
# Check if registration_enabled setting exists
reg_setting = SystemSettings.query.filter_by(key='registration_enabled').first()
if not reg_setting:
print("Adding registration_enabled system setting...")
reg_setting = SystemSettings(
key='registration_enabled',
value='true', # Default to enabled
description='Controls whether new user registration is allowed'
)
db.session.add(reg_setting)
db.session.commit()
print("Registration setting initialized to enabled")
if __name__ == "__main__":
migrate_database()
print("Database migration completed")

View File

@@ -49,6 +49,16 @@ class User(db.Model):
def __repr__(self):
return f'<User {self.username}>'
class SystemSettings(db.Model):
id = db.Column(db.Integer, primary_key=True)
key = db.Column(db.String(50), unique=True, nullable=False)
value = db.Column(db.String(255), nullable=False)
description = db.Column(db.String(255))
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
def __repr__(self):
return f'<SystemSettings {self.key}={self.value}>'
class TimeEntry(db.Model):
id = db.Column(db.Integer, primary_key=True)
arrival_time = db.Column(db.DateTime, nullable=False)

View File

@@ -523,3 +523,77 @@ input[type="time"]::-webkit-datetime-edit {
background-color: #f8d7da;
color: #721c24;
}
.settings-card {
background-color: #f8f9fa;
border-radius: 5px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
}
.setting-description {
color: #6c757d;
font-size: 0.9em;
margin-top: 5px;
}
.checkbox-container {
display: block;
position: relative;
padding-left: 35px;
margin-bottom: 12px;
cursor: pointer;
font-size: 16px;
user-select: none;
}
.checkbox-container input {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}
.checkmark {
position: absolute;
top: 0;
left: 0;
height: 25px;
width: 25px;
background-color: #eee;
border-radius: 4px;
}
.checkbox-container:hover input ~ .checkmark {
background-color: #ccc;
}
.checkbox-container input:checked ~ .checkmark {
background-color: #2196F3;
}
.checkmark:after {
content: "";
position: absolute;
display: none;
}
.checkbox-container input:checked ~ .checkmark:after {
display: block;
}
.checkbox-container .checkmark:after {
left: 9px;
top: 5px;
width: 5px;
height: 10px;
border: solid white;
border-width: 0 3px 3px 0;
transform: rotate(45deg);
}
.form-actions {
margin-top: 20px;
}

View File

@@ -11,14 +11,11 @@
<a href="{{ url_for('admin_users') }}" class="btn btn-primary">Manage Users</a>
</div>
<!-- You can add more admin cards here in the future -->
<!-- For example:
<div class="admin-card">
<h2>System Settings</h2>
<p>Configure application-wide settings.</p>
<a href="#" class="btn btn-primary">Configure</a>
<p>Configure application-wide settings like registration and more.</p>
<a href="{{ url_for('admin_settings') }}" class="btn btn-primary">Configure</a>
</div>
-->
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,31 @@
{% extends "layout.html" %}
{% block content %}
<div class="admin-container">
<h1>System Settings</h1>
<form method="POST" action="{{ url_for('admin_settings') }}">
<div class="settings-card">
<h2>Registration Settings</h2>
<div class="form-group">
<label class="checkbox-container">
<input type="checkbox" name="registration_enabled"
{% if settings.registration_enabled %}checked{% endif %}>
<span class="checkmark"></span>
Enable User Registration
</label>
<p class="setting-description">
When enabled, new users can register accounts. When disabled, only administrators can create new accounts.
</p>
</div>
<!-- You can add more settings here in the future -->
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Save Settings</button>
</div>
</form>
</div>
{% endblock %}