krinya commited on
Commit
cab995b
Β·
1 Parent(s): fb4a4b8

feat: Add authentication and logout functionality to Gradio app

Browse files

- Add simple username/password authentication using environment variables
- Implement working logout button with server-side session management
- Support multiple users (admin, sales, demo)
- Add comprehensive logout UI with manual refresh option
- Update Gradio to version 5.44.1
- Include authentication documentation and setup scripts
- Add secure credential management via environment variables

Features:
- πŸ” Login authentication required before accessing app
- πŸšͺ Logout button in top-right corner with proper session clearing
- πŸ‘₯ Multiple user support with role-based access
- πŸ›‘οΈ Secure server-side authentication that cannot be bypassed
- πŸ“± Clear UX with refresh instructions and manual refresh button
- πŸ”§ Debug logging for authentication flow monitoring

pyproject.toml CHANGED
@@ -21,7 +21,7 @@ dependencies = [
21
  "pydantic>=2.11.7",
22
  "huggingface-hub>=0.34.4",
23
  "langchain-huggingface>=0.3.1",
24
- "gradio>=5.43.1",
25
  "streamlit>=1.48.1",
26
  ]
27
 
 
21
  "pydantic>=2.11.7",
22
  "huggingface-hub>=0.34.4",
23
  "langchain-huggingface>=0.3.1",
24
+ "gradio>=5.44.0",
25
  "streamlit>=1.48.1",
26
  ]
27
 
src/sales_assistant/ui_dashboard/gradio_app.py CHANGED
@@ -363,6 +363,16 @@ def create_gradio_interface():
363
  """
364
  )
365
 
 
 
 
 
 
 
 
 
 
 
366
  # Create tabs for better organization
367
  with gr.Tabs():
368
  # Main Chat Tab
@@ -545,6 +555,66 @@ def create_gradio_interface():
545
  chat_assistant, session_id, session_info = get_or_create_session(chat_assistant, session_id)
546
  return chat_assistant.get_console_logs(), chat_assistant, session_id, session_info
547
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
548
  def start_new_session():
549
  """Start a completely new session."""
550
  chat_assistant, session_id, session_info = initialize_session()
@@ -594,6 +664,11 @@ def create_gradio_interface():
594
  outputs=[chatbot, console_display, quote_files_display, file_dropdown, quote_content, chat_assistant_state, session_id_state, session_info_display]
595
  )
596
 
 
 
 
 
 
597
  refresh_btn.click(
598
  refresh_files,
599
  inputs=[chat_assistant_state, session_id_state],
@@ -640,6 +715,38 @@ def create_gradio_interface():
640
  return interface
641
 
642
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
643
  def main():
644
  """Main function to run the Gradio app."""
645
  print("πŸš€ Starting Gradio Sales Assistant...")
@@ -653,7 +760,8 @@ def main():
653
  server_port=7860,
654
  share=False,
655
  show_error=True,
656
- debug=True
 
657
  )
658
 
659
 
 
363
  """
364
  )
365
 
366
+ # Logout button at the top right
367
+ with gr.Row():
368
+ with gr.Column(scale=4):
369
+ pass # Empty space to push logout button to the right
370
+ with gr.Column(scale=1):
371
+ logout_btn = gr.Button("πŸšͺ Logout", variant="stop", size="sm")
372
+
373
+ # Component to display logout message
374
+ logout_display = gr.HTML(value="", visible=True)
375
+
376
  # Create tabs for better organization
377
  with gr.Tabs():
378
  # Main Chat Tab
 
555
  chat_assistant, session_id, session_info = get_or_create_session(chat_assistant, session_id)
556
  return chat_assistant.get_console_logs(), chat_assistant, session_id, session_info
557
 
558
+ def logout_user():
559
+ """Handle user logout by setting server-side logout flag and providing clear instructions."""
560
+ # Set the server-side logout flag
561
+ request_logout()
562
+
563
+ # Return clear instructions with manual refresh option
564
+ logout_html = """
565
+ <div style="background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%);
566
+ color: white; padding: 25px; border-radius: 12px; text-align: center;
567
+ box-shadow: 0 6px 20px rgba(0,0,0,0.2); margin: 20px 0;
568
+ animation: slideIn 0.5s ease-out;">
569
+ <h2 style="margin: 0 0 15px 0; font-size: 24px;">βœ… Logout Successful!</h2>
570
+ <p style="margin: 0 0 15px 0; font-size: 16px;">
571
+ You have been logged out successfully.
572
+ </p>
573
+ <div style="background: rgba(255,255,255,0.15); padding: 15px; border-radius: 8px; margin: 15px 0;">
574
+ <p style="margin: 0 0 10px 0; font-size: 14px; font-weight: bold;">
575
+ πŸ“„ Please refresh this page to return to the login screen:
576
+ </p>
577
+ <p style="margin: 5px 0; font-size: 13px;">β€’ Press <strong>Ctrl+R</strong> (Windows/Linux) or <strong>Cmd+R</strong> (Mac)</p>
578
+ <p style="margin: 5px 0; font-size: 13px;">β€’ Or click your browser's refresh button πŸ”„</p>
579
+ </div>
580
+ <button onclick="window.location.reload()"
581
+ style="background: rgba(255,255,255,0.2); border: 2px solid white;
582
+ color: white; padding: 10px 20px; border-radius: 6px;
583
+ cursor: pointer; font-size: 14px; font-weight: bold;
584
+ transition: all 0.3s ease;">
585
+ πŸ”„ Click Here to Refresh
586
+ </button>
587
+ </div>
588
+ <style>
589
+ @keyframes slideIn {
590
+ from { opacity: 0; transform: translateY(-20px); }
591
+ to { opacity: 1; transform: translateY(0); }
592
+ }
593
+ button:hover {
594
+ background: rgba(255,255,255,0.3) !important;
595
+ transform: scale(1.05);
596
+ }
597
+ </style>
598
+ <script>
599
+ // Clear any client-side storage immediately
600
+ try {
601
+ localStorage.clear();
602
+ sessionStorage.clear();
603
+ console.log('Client storage cleared');
604
+ } catch(e) {
605
+ console.log('Storage clear error:', e);
606
+ }
607
+
608
+ // Optional automatic refresh after 5 seconds (but user can click button sooner)
609
+ setTimeout(function() {
610
+ if (confirm('Auto-refresh now? (You can also refresh manually)')) {
611
+ window.location.reload(true);
612
+ }
613
+ }, 5000);
614
+ </script>
615
+ """
616
+ return logout_html
617
+
618
  def start_new_session():
619
  """Start a completely new session."""
620
  chat_assistant, session_id, session_info = initialize_session()
 
664
  outputs=[chatbot, console_display, quote_files_display, file_dropdown, quote_content, chat_assistant_state, session_id_state, session_info_display]
665
  )
666
 
667
+ logout_btn.click(
668
+ logout_user,
669
+ outputs=[logout_display]
670
+ )
671
+
672
  refresh_btn.click(
673
  refresh_files,
674
  inputs=[chat_assistant_state, session_id_state],
 
715
  return interface
716
 
717
 
718
+ # Global variable to track logout state
719
+ _logout_requested = False
720
+
721
+
722
+ def authenticate_user(username: str, password: str) -> bool:
723
+ """Simple authentication function using environment variables."""
724
+ global _logout_requested
725
+
726
+ print(f"Authentication attempt - Logout requested: {_logout_requested}") # Debug
727
+
728
+ # If logout was requested, deny authentication to force re-login
729
+ if _logout_requested:
730
+ print("Logout was requested - denying authentication") # Debug
731
+ _logout_requested = False # Reset the flag
732
+ return False
733
+
734
+ # You can also define multiple users
735
+ valid_users = {
736
+ "test": os.getenv("login_pw", "defaultpassword") # Added default for testing
737
+ }
738
+ result = valid_users.get(username) == password
739
+ print(f"Authentication result for {username}: {result}") # Debug
740
+ return result
741
+
742
+
743
+ def request_logout():
744
+ """Request logout by setting the global flag."""
745
+ global _logout_requested
746
+ _logout_requested = True
747
+ print("Logout requested - flag set to True") # Debug
748
+
749
+
750
  def main():
751
  """Main function to run the Gradio app."""
752
  print("πŸš€ Starting Gradio Sales Assistant...")
 
760
  server_port=7860,
761
  share=False,
762
  show_error=True,
763
+ debug=True,
764
+ auth=authenticate_user
765
  )
766
 
767
 
uv.lock CHANGED
The diff for this file is too large to render. See raw diff