Alfred Ang
Upload folder using huggingface_hub
532ffe7 verified
Raw
History Blame Contribute Delete
5.88 kB
"""
Admin Authentication Module
Simple authentication for protecting Settings pages.
Admin credentials are stored in SQLite database.
Initial setup requires ADMIN_USERNAME and ADMIN_PASSWORD in .streamlit/secrets.toml or environment variables.
Author: Wong Xin Ping
Date: 26 January 2026
"""
import streamlit as st
import hashlib
import os
from settings.api_database import (
verify_admin_password,
admin_credentials_exist,
set_admin_credentials,
get_admin_credentials_from_db,
)
def hash_password(password: str) -> str:
"""Hash password using SHA-256"""
return hashlib.sha256(password.encode()).hexdigest()
def is_authenticated() -> bool:
"""Check if user is authenticated"""
return st.session_state.get('admin_authenticated', False)
def logout():
"""Log out the admin user"""
st.session_state['admin_authenticated'] = False
st.session_state['admin_username'] = None
def _get_initial_credentials():
"""Get initial credentials from environment variables or Streamlit secrets."""
username = os.environ.get("ADMIN_USERNAME") or st.secrets.get("ADMIN_USERNAME", "admin")
password = os.environ.get("ADMIN_PASSWORD") or st.secrets.get("ADMIN_PASSWORD", "")
return username, password
def login_page():
"""Display login page and handle authentication"""
# Check if admin credentials exist in database
if not admin_credentials_exist():
# First-time setup - try to get from secrets/env
username, password = _get_initial_credentials()
if username and password:
set_admin_credentials(username, password)
else:
# Show setup form
st.markdown("### Initial Admin Setup")
st.warning("No admin credentials found. Please set up admin account.")
st.caption("You can also set ADMIN_USERNAME and ADMIN_PASSWORD in .streamlit/secrets.toml or environment variables.")
with st.form("admin_setup_form"):
new_username = st.text_input("Username", placeholder="Enter admin username")
new_password = st.text_input("Password", type="password", placeholder="Enter admin password")
confirm_password = st.text_input("Confirm Password", type="password", placeholder="Confirm password")
submitted = st.form_submit_button("Create Admin Account", type="primary")
if submitted:
if not new_username or not new_password:
st.error("Username and password are required")
elif new_password != confirm_password:
st.error("Passwords do not match")
elif len(new_password) < 8:
st.error("Password must be at least 8 characters")
else:
if set_admin_credentials(new_username, new_password):
st.success("Admin account created successfully!")
st.rerun()
else:
st.error("Failed to create admin account")
return
# Normal login flow
st.markdown("### Admin Login")
st.caption("Enter admin credentials to access settings")
with st.form("admin_login_form"):
username = st.text_input("Username", value="admin", placeholder="Enter username")
password = st.text_input("Password", type="password", placeholder="Enter password")
col1, col2 = st.columns([1, 3])
with col1:
submitted = st.form_submit_button("Login", type="primary", use_container_width=True)
if submitted:
if verify_admin_password(username, password):
st.session_state['admin_authenticated'] = True
st.session_state['admin_username'] = username
st.success("Login successful!")
st.rerun()
else:
st.error("Invalid username or password")
def require_auth(page_function):
"""Decorator/wrapper to require authentication for a page"""
def wrapper(*args, **kwargs):
if not is_authenticated():
login_page()
return None
return page_function(*args, **kwargs)
return wrapper
def show_logout_button():
"""Show logout button in sidebar or page"""
if is_authenticated():
username = st.session_state.get('admin_username', 'Admin')
col1, col2 = st.columns([3, 1])
with col1:
st.caption(f"Logged in as: **{username}**")
with col2:
if st.button("Logout", key="logout_btn", use_container_width=True):
logout()
st.rerun()
def change_password_form():
"""Display form to change admin password"""
if not is_authenticated():
return
st.markdown("### Change Password")
with st.form("change_password_form"):
current_password = st.text_input("Current Password", type="password")
new_password = st.text_input("New Password", type="password")
confirm_password = st.text_input("Confirm New Password", type="password")
submitted = st.form_submit_button("Change Password", type="primary")
if submitted:
username = st.session_state.get('admin_username', '')
if not verify_admin_password(username, current_password):
st.error("Current password is incorrect")
elif new_password != confirm_password:
st.error("New passwords do not match")
elif len(new_password) < 8:
st.error("Password must be at least 8 characters")
else:
if set_admin_credentials(username, new_password):
st.success("Password changed successfully!")
else:
st.error("Failed to change password")