From e744afbe26c66f5878ee2e630db6789e0f55a556 Mon Sep 17 00:00:00 2001
From: Matt Hills
Date: Thu, 19 Jun 2025 16:03:50 -0400
Subject: [PATCH] adding server settings
---
src/app.py | 23 ++++++++--
src/database.py | 70 +++++++++++++++++++++++++++--
src/templates/settings.html | 52 +++++++++++++++++++++
src/templates/tenant_selection.html | 2 +
4 files changed, 140 insertions(+), 7 deletions(-)
create mode 100644 src/templates/settings.html
diff --git a/src/app.py b/src/app.py
index 1ab0ce9..f94377d 100644
--- a/src/app.py
+++ b/src/app.py
@@ -28,7 +28,8 @@ def load_products(tenant_id=None):
def index():
# Show a tenant selection page or redirect to default
tenants = database.get_all_tenants()
- return render_template('tenant_selection.html', tenants=tenants)
+ server_url = database.get_server_url()
+ return render_template('tenant_selection.html', tenants=tenants, server_url=server_url)
@app.route('/tenant//delete', methods=['POST'])
def delete_tenant(tenant_id):
@@ -37,6 +38,22 @@ def delete_tenant(tenant_id):
flash(f'Tenant "{tenant_id}" has been deleted successfully.', 'success')
return redirect('/')
+@app.route('/settings', methods=['GET', 'POST'])
+def settings():
+ if request.method == 'POST':
+ server_url = request.form.get('server_url', '').strip()
+ if server_url:
+ # Remove trailing slash for consistency
+ server_url = server_url.rstrip('/')
+ database.set_setting('server_url', server_url)
+ flash('Server settings updated successfully.', 'success')
+ else:
+ flash('Please provide a valid server URL.', 'error')
+ return redirect('/settings')
+
+ server_url = database.get_server_url()
+ return render_template('settings.html', server_url=server_url)
+
@app.route('//')
def tenant_index(tenant_id):
# Auto-create tenant if it doesn't exist
@@ -56,8 +73,8 @@ def check_basic_auth(auth_header, tenant_id):
credentials = base64.b64decode(auth_header[6:]).decode('utf-8')
username, password = credentials.split(':', 1)
- # Get tenant credentials from database
- tenant = database.get_or_create_tenant(tenant_id)
+ # Get tenant credentials from database (without creating)
+ tenant = database.get_tenant(tenant_id)
if tenant and username == tenant['username'] and password == tenant['password']:
return True
except Exception:
diff --git a/src/database.py b/src/database.py
index d8692ec..836f9a6 100644
--- a/src/database.py
+++ b/src/database.py
@@ -107,6 +107,16 @@ def init_database():
)
''')
+ # Create settings table for server configuration
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS settings (
+ key TEXT PRIMARY KEY,
+ value TEXT NOT NULL,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+ )
+ ''')
+
conn.commit()
def migrate_from_json():
@@ -342,10 +352,34 @@ def get_product_image(product_id: str, tenant_id: str) -> Optional[tuple[bytes,
return row['image_data'], row['image_mime_type']
return None
+def get_tenant(tenant_id: str) -> Optional[Dict[str, Any]]:
+ """Get a tenant without creating it"""
+ # Normalize tenant_id to lowercase
+ tenant_id = tenant_id.lower()
+
+ with get_db() as conn:
+ cursor = conn.cursor()
+
+ # Check if tenant exists
+ cursor.execute('SELECT id, name, username, password FROM tenants WHERE id = ?', (tenant_id,))
+ row = cursor.fetchone()
+
+ if row:
+ return {
+ 'id': row['id'],
+ 'name': row['name'],
+ 'username': row['username'],
+ 'password': row['password']
+ }
+ return None
+
def get_or_create_tenant(tenant_id: str, username: str = None, password: str = None) -> Optional[Dict[str, Any]]:
"""Get or create a tenant"""
+ # Normalize tenant_id to lowercase
+ tenant_id = tenant_id.lower()
+
# Check if tenant_id is reserved
- if tenant_id.lower() in RESERVED_TENANT_IDS:
+ if tenant_id in RESERVED_TENANT_IDS:
return None
with get_db() as conn:
@@ -366,10 +400,12 @@ def get_or_create_tenant(tenant_id: str, username: str = None, password: str = N
# Create new tenant with default credentials
default_username = username or 'admin'
default_password = password or 'admin'
+ # Preserve original casing for display name
+ display_name = tenant_id.replace('-', ' ').replace('_', ' ').title()
cursor.execute('''
INSERT INTO tenants (id, name, username, password)
VALUES (?, ?, ?, ?)
- ''', (tenant_id, tenant_id.title(), default_username, default_password))
+ ''', (tenant_id, display_name, default_username, default_password))
conn.commit()
# Initialize default AR fields for the new tenant
@@ -377,7 +413,7 @@ def get_or_create_tenant(tenant_id: str, username: str = None, password: str = N
return {
'id': tenant_id,
- 'name': tenant_id.title(),
+ 'name': display_name,
'username': default_username,
'password': default_password
}
@@ -554,4 +590,30 @@ def get_product_image_by_field(product_id: str, tenant_id: str, field_name: str)
row = cursor.fetchone()
if row and row['image_data']:
return row['image_data'], row['image_mime_type']
- return None
\ No newline at end of file
+ return None
+
+def get_setting(key: str, default_value: str = None) -> Optional[str]:
+ """Get a setting value by key"""
+ with get_db() as conn:
+ cursor = conn.cursor()
+ cursor.execute('SELECT value FROM settings WHERE key = ?', (key,))
+ row = cursor.fetchone()
+
+ if row:
+ return row['value']
+ return default_value
+
+def set_setting(key: str, value: str):
+ """Set a setting value"""
+ with get_db() as conn:
+ cursor = conn.cursor()
+ cursor.execute('''
+ INSERT INTO settings (key, value)
+ VALUES (?, ?)
+ ON CONFLICT(key) DO UPDATE SET value = ?, updated_at = CURRENT_TIMESTAMP
+ ''', (key, value, value))
+ conn.commit()
+
+def get_server_url() -> str:
+ """Get the configured server URL or return a default"""
+ return get_setting('server_url', 'http://localhost:5000')
\ No newline at end of file
diff --git a/src/templates/settings.html b/src/templates/settings.html
new file mode 100644
index 0000000..0cc6697
--- /dev/null
+++ b/src/templates/settings.html
@@ -0,0 +1,52 @@
+
+
+
+
+
+ Server Settings - KCAP Demo Server
+
+
+
+
+
Server Settings
+
+ {% with messages = get_flashed_messages(with_categories=true) %}
+ {% if messages %}
+ {% for category, message in messages %}
+
+ {{ message }}
+
+
+ {% endfor %}
+ {% endif %}
+ {% endwith %}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/templates/tenant_selection.html b/src/templates/tenant_selection.html
index 427672a..4dd29ed 100644
--- a/src/templates/tenant_selection.html
+++ b/src/templates/tenant_selection.html
@@ -38,6 +38,7 @@
{{ tenant.created_at }}
Username: {{ tenant.username }}
+ Knox Capture AR Template URL: {{ server_url }}/{{ tenant.id }}/
ID: {{ tenant.id }}
+ Server Settings