Add System Settings. Enable/Disable User registration.
This commit is contained in:
49
app.py
49
app.py
@@ -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)
|
||||
@@ -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")
|
||||
10
models.py
10
models.py
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 %}
|
||||
31
templates/admin_settings.html
Normal file
31
templates/admin_settings.html
Normal 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 %}
|
||||
Reference in New Issue
Block a user