Files
testing123/streamlit_dashboard/page_classes/authentication_page_wrapper.py
2026-05-21 08:40:24 -04:00

68 lines
3.2 KiB
Python

import logging
import streamlit as st
from streamlit_authenticator import Authenticate
# Imports from this module
from page_classes.funding_milestones_page_class import NetworkFundingMilestonesReportPage
from utility_classes.base_report_page import BaseReportPage
from page_classes.page_class_constants import REPORT_CONFIGS
from utility_classes.dashboard_config_parser import DashboardConfig
from streamlit_constants import DASHBOARD_CONFIG_OBJECT_KEY
class AuthenticationPageWrapper:
"""
Wraps a report page to enforce user authentication before rendering.
This class acts as a security gateway. It isolates the authentication state logic
from the underlying report rendering, ensuring that unauthenticated users
cannot instantiate or view protected components, while handling page-level configurations.
:param inner_report_page: The uninstantiated class of the report to display.
:type inner_report_page: type[BaseReportPage]
:param report_config: Keyword arguments required to instantiate the report.
:type report_config: dict
"""
def __init__(self, inner_report_page:type[BaseReportPage], report_config:dict):
self.inner_report_page = inner_report_page
self.report_config = report_config
self.app_config:DashboardConfig = st.session_state[DASHBOARD_CONFIG_OBJECT_KEY]
self.logger = logging.getLogger(__name__)
def run(self):
"""
Executes the authentication check and manages the encapsulated report lifecycle.
Checks the Streamlit session state for valid credentials. If authenticated,
it safely constructs and renders the underlying report page, catching and logging
any initialization or rendering exceptions to prevent application crashes.
"""
authenticator: Authenticate = st.session_state.get('authenticator')
st.set_page_config(layout='wide')
if st.session_state.get('authentication_status'):
st.sidebar.write(f'Welcome *{st.session_state.get("name")}*')
authenticator.logout(location="sidebar")
# Unpack the arguments and construct the page object
try:
page_class = self.inner_report_page(**self.report_config)
except Exception as e:
self.logger.exception(f"Failed to construct the report page. Got {e}")
st.error(f"Construction of page failed. A detailed error has been added to the logs. {self.app_config.get_errors_contact_string()}")
st.stop()
# Display it
try:
page_class.render(st.container())
except Exception as e:
self.logger.exception(f"Failed to render the page. Got {e}")
st.error(f"Rendering of page failed. A detailed error has been added to the logs. {self.app_config.get_errors_contact_string()}")
st.stop()
elif st.session_state.get('authentication_status') is False:
st.error(f'Username/password is incorrect. {self.app_config.get_errors_contact_string()}')
elif st.session_state.get('authentication_status') is None:
st.warning('Please enter your username and password')