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 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
|
import logging
|
||||||
from datetime import datetime, time, timedelta
|
from datetime import datetime, time, timedelta
|
||||||
import os
|
import os
|
||||||
@@ -42,6 +42,23 @@ mail = Mail(app)
|
|||||||
# Initialize the database with the app
|
# Initialize the database with the app
|
||||||
db.init_app(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
|
# Authentication decorator
|
||||||
def login_required(f):
|
def login_required(f):
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
@@ -123,6 +140,14 @@ def logout():
|
|||||||
|
|
||||||
@app.route('/register', methods=['GET', 'POST'])
|
@app.route('/register', methods=['GET', 'POST'])
|
||||||
def register():
|
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':
|
if request.method == 'POST':
|
||||||
username = request.form.get('username')
|
username = request.form.get('username')
|
||||||
email = request.form.get('email')
|
email = request.form.get('email')
|
||||||
@@ -681,5 +706,27 @@ def toggle_user_status(user_id):
|
|||||||
|
|
||||||
return redirect(url_for('admin_users'))
|
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__':
|
if __name__ == '__main__':
|
||||||
app.run(debug=True)
|
app.run(debug=True)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
from app import app, db
|
from app import app, db
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import os
|
import os
|
||||||
from models import User, TimeEntry, WorkConfig
|
from models import User, TimeEntry, WorkConfig, SystemSettings
|
||||||
from werkzeug.security import generate_password_hash
|
from werkzeug.security import generate_password_hash
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
@@ -13,6 +13,9 @@ def migrate_database():
|
|||||||
print("Database doesn't exist. Creating new database.")
|
print("Database doesn't exist. Creating new database.")
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
db.create_all()
|
db.create_all()
|
||||||
|
|
||||||
|
# Initialize system settings
|
||||||
|
init_system_settings()
|
||||||
return
|
return
|
||||||
|
|
||||||
print("Migrating existing database...")
|
print("Migrating existing database...")
|
||||||
@@ -104,6 +107,20 @@ def migrate_database():
|
|||||||
print("Adding is_blocked column to user table...")
|
print("Adding is_blocked column to user table...")
|
||||||
cursor.execute("ALTER TABLE user ADD COLUMN is_blocked BOOLEAN DEFAULT 0")
|
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
|
# Commit changes and close connection
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
@@ -112,6 +129,9 @@ def migrate_database():
|
|||||||
# Create tables if they don't exist
|
# Create tables if they don't exist
|
||||||
db.create_all()
|
db.create_all()
|
||||||
|
|
||||||
|
# Initialize system settings
|
||||||
|
init_system_settings()
|
||||||
|
|
||||||
# Check if admin user exists
|
# Check if admin user exists
|
||||||
admin = User.query.filter_by(username='admin').first()
|
admin = User.query.filter_by(username='admin').first()
|
||||||
if not admin:
|
if not admin:
|
||||||
@@ -154,6 +174,21 @@ def migrate_database():
|
|||||||
print(f"Associated {len(orphan_configs)} existing work configs with admin user")
|
print(f"Associated {len(orphan_configs)} existing work configs with admin user")
|
||||||
print(f"Marked {len(existing_users)} existing users as verified")
|
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__":
|
if __name__ == "__main__":
|
||||||
migrate_database()
|
migrate_database()
|
||||||
print("Database migration completed")
|
print("Database migration completed")
|
||||||
10
models.py
10
models.py
@@ -49,6 +49,16 @@ class User(db.Model):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'<User {self.username}>'
|
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):
|
class TimeEntry(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
arrival_time = db.Column(db.DateTime, nullable=False)
|
arrival_time = db.Column(db.DateTime, nullable=False)
|
||||||
|
|||||||
@@ -523,3 +523,77 @@ input[type="time"]::-webkit-datetime-edit {
|
|||||||
background-color: #f8d7da;
|
background-color: #f8d7da;
|
||||||
color: #721c24;
|
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>
|
<a href="{{ url_for('admin_users') }}" class="btn btn-primary">Manage Users</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- You can add more admin cards here in the future -->
|
|
||||||
<!-- For example:
|
|
||||||
<div class="admin-card">
|
<div class="admin-card">
|
||||||
<h2>System Settings</h2>
|
<h2>System Settings</h2>
|
||||||
<p>Configure application-wide settings.</p>
|
<p>Configure application-wide settings like registration and more.</p>
|
||||||
<a href="#" class="btn btn-primary">Configure</a>
|
<a href="{{ url_for('admin_settings') }}" class="btn btn-primary">Configure</a>
|
||||||
</div>
|
</div>
|
||||||
-->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% 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