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')