"""
Authentication module for Streamlit Control
Handles LuCI/ubus session management
"""
import streamlit as st
from typing import Optional
from lib.ubus_client import UbusClient
def get_ubus() -> Optional[UbusClient]:
"""Get authenticated ubus client from session state"""
if "ubus" in st.session_state and st.session_state.get("authenticated"):
return st.session_state.ubus
return None
def require_auth() -> UbusClient:
"""
Require authentication before showing page content.
Call this at the top of every page.
Returns authenticated UbusClient or stops execution.
"""
# Initialize session state
if "authenticated" not in st.session_state:
st.session_state.authenticated = False
if "ubus" not in st.session_state:
st.session_state.ubus = UbusClient()
# Check if already authenticated
if st.session_state.authenticated:
# Verify session is still valid
if st.session_state.ubus.is_authenticated():
return st.session_state.ubus
else:
# Session expired
st.session_state.authenticated = False
# Show login form
show_login()
st.stop()
def show_login():
"""Display login form"""
st.set_page_config(
page_title="SecuBox Control - Login",
page_icon="🔐",
layout="centered"
)
# Center the login form
col1, col2, col3 = st.columns([1, 2, 1])
with col2:
st.markdown("""
🔐 SecuBox Control
Streamlit-based System Dashboard
""", unsafe_allow_html=True)
with st.form("login_form"):
username = st.text_input(
"Username",
value="",
placeholder="root or SecuBox username"
)
password = st.text_input(
"Password",
type="password",
placeholder="Enter password"
)
col_a, col_b = st.columns([1, 1])
with col_b:
submitted = st.form_submit_button(
"Login",
type="primary",
use_container_width=True
)
if submitted:
if not username or not password:
st.error("Please enter username and password")
else:
with st.spinner("Authenticating..."):
ubus = UbusClient()
if ubus.login(username, password):
st.session_state.authenticated = True
st.session_state.ubus = ubus
st.session_state.username = username
st.session_state.is_secubox_user = ubus.is_secubox_user
if ubus.is_secubox_user:
st.info("Logged in as SecuBox user (limited permissions)")
st.rerun()
else:
st.error("Invalid credentials. Check username and password.")
st.markdown("""
Login with:
• root - Full system access
• SecuBox user - Limited dashboard access
""", unsafe_allow_html=True)
def logout():
"""Logout and clear session"""
if "ubus" in st.session_state:
st.session_state.ubus.logout()
st.session_state.authenticated = False
st.session_state.pop("ubus", None)
st.session_state.pop("username", None)
st.rerun()
def show_user_menu():
"""Show user menu in sidebar"""
if st.session_state.get("authenticated"):
username = st.session_state.get("username", "root")
is_limited = st.session_state.get("is_secubox_user", False)
role = "Limited" if is_limited else "Admin"
st.sidebar.markdown(f"👤 **{username}** ({role})")
if st.sidebar.button("Logout", key="logout_btn"):
logout()
def can_write() -> bool:
"""
Check if current user has write permissions.
SecuBox users (non-root) are read-only.
"""
return not st.session_state.get("is_secubox_user", False)
def is_admin() -> bool:
"""Check if current user is admin (root or similar)"""
return not st.session_state.get("is_secubox_user", False)