mike boone commited on
Commit
090128c
Β·
1 Parent(s): ece9b51

fix: force password change before app access

Browse files
Files changed (1) hide show
  1. chat_interface.py +98 -1
chat_interface.py CHANGED
@@ -4868,8 +4868,34 @@ def create_chat_interface():
4868
  population_code_state = gr.State("")
4869
  live_progress_state = gr.State("")
4870
  demo_pack_state = gr.State("")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4871
 
4872
- with gr.Tabs():
4873
  with gr.Tab("πŸ“± App"):
4874
  chat_components = create_chat_tab(
4875
  chat_controller_state, default_settings, current_stage, current_model,
@@ -5442,6 +5468,56 @@ def create_chat_interface():
5442
  inputs=[],
5443
  outputs=admin_outputs
5444
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5445
 
5446
  # Create update function for tabs
5447
  _spotter_waiting = "Story will be generated after liveboard creation."
@@ -5885,6 +5961,8 @@ def create_chat_tab(chat_controller_state, settings, current_stage, current_mode
5885
  controller.settings['thoughtspot_url'] = _url
5886
  if _key_value:
5887
  controller.settings['thoughtspot_trusted_auth_key'] = _key_value
 
 
5888
  # Always use the current UI values β€” take priority over DB-loaded defaults
5889
  if liveboard_name_ui is not None:
5890
  controller.settings['liveboard_name'] = liveboard_name_ui
@@ -5957,6 +6035,8 @@ def create_chat_tab(chat_controller_state, settings, current_stage, current_mode
5957
  controller.settings['thoughtspot_url'] = _url
5958
  if _key_value:
5959
  controller.settings['thoughtspot_trusted_auth_key'] = _key_value
 
 
5960
  if lb_name is not None:
5961
  controller.settings['liveboard_name'] = lb_name
5962
  if model:
@@ -5988,6 +6068,23 @@ def create_chat_tab(chat_controller_state, settings, current_stage, current_mode
5988
 
5989
  is_custom = (vertical == "* CUSTOM *")
5990
  hide_welcome = gr.update(visible=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5991
 
5992
  if is_custom:
5993
  # Custom: context field drives the use case
 
4868
  population_code_state = gr.State("")
4869
  live_progress_state = gr.State("")
4870
  demo_pack_state = gr.State("")
4871
+
4872
+ with gr.Group(visible=False) as password_gate:
4873
+ gr.Markdown("""
4874
+ ## Change Password Required
4875
+
4876
+ You are signed in with a temporary password. Set a new password before using DemoPrep.
4877
+ """)
4878
+ with gr.Row():
4879
+ with gr.Column(scale=1):
4880
+ gate_current_password = gr.Textbox(
4881
+ label="Temporary Password",
4882
+ type="password",
4883
+ placeholder="Enter the password you just used to sign in",
4884
+ )
4885
+ gate_new_password = gr.Textbox(
4886
+ label="New Password",
4887
+ type="password",
4888
+ placeholder="At least 8 characters",
4889
+ )
4890
+ gate_confirm_password = gr.Textbox(
4891
+ label="Confirm New Password",
4892
+ type="password",
4893
+ placeholder="Repeat new password",
4894
+ )
4895
+ gate_change_password_btn = gr.Button("Change Password", variant="primary")
4896
+ gate_password_status = gr.Markdown("")
4897
 
4898
+ with gr.Tabs(visible=False) as main_tabs:
4899
  with gr.Tab("πŸ“± App"):
4900
  chat_components = create_chat_tab(
4901
  chat_controller_state, default_settings, current_stage, current_model,
 
5468
  inputs=[],
5469
  outputs=admin_outputs
5470
  )
5471
+
5472
+ def check_password_gate(request: gr.Request = None):
5473
+ """Show only the forced password-change panel for temp-password users."""
5474
+ try:
5475
+ user_email = require_authenticated_email(request)
5476
+ from supabase_client import UserManager
5477
+ um = UserManager()
5478
+ must_change = um.enabled and um.must_change_password(user_email)
5479
+ return gr.update(visible=must_change), gr.update(visible=not must_change)
5480
+ except Exception as e:
5481
+ print(f"[LOAD] password gate check skipped: {e}")
5482
+ return gr.update(visible=False), gr.update(visible=True)
5483
+
5484
+ def complete_required_password_change(current, new_pw, confirm, request: gr.Request = None):
5485
+ if not current or not new_pw or not confirm:
5486
+ return "❌ All fields are required.", gr.update(), gr.update()
5487
+ if new_pw != confirm:
5488
+ return "❌ New passwords don't match.", gr.update(), gr.update()
5489
+ if len(new_pw) < 8:
5490
+ return "❌ New password must be at least 8 characters.", gr.update(), gr.update()
5491
+ try:
5492
+ user_email = require_authenticated_email(request)
5493
+ from supabase_client import UserManager
5494
+ um = UserManager()
5495
+ if not um.enabled:
5496
+ return "⚠️ Supabase not configured β€” password change unavailable.", gr.update(), gr.update()
5497
+ if not um.authenticate(user_email, current):
5498
+ return "❌ Temporary password is incorrect.", gr.update(), gr.update()
5499
+ if not um.reset_password(user_email, new_pw, must_change_password=False):
5500
+ return "❌ Password change failed. Please try again or ask an admin to reset it.", gr.update(), gr.update()
5501
+ um.clear_must_change_password(user_email)
5502
+ return (
5503
+ "βœ… Password changed. DemoPrep is ready.",
5504
+ gr.update(visible=False),
5505
+ gr.update(visible=True),
5506
+ )
5507
+ except Exception as e:
5508
+ return f"❌ Error: {e}", gr.update(), gr.update()
5509
+
5510
+ interface.load(
5511
+ fn=check_password_gate,
5512
+ inputs=[],
5513
+ outputs=[password_gate, main_tabs],
5514
+ )
5515
+
5516
+ gate_change_password_btn.click(
5517
+ fn=complete_required_password_change,
5518
+ inputs=[gate_current_password, gate_new_password, gate_confirm_password],
5519
+ outputs=[gate_password_status, password_gate, main_tabs],
5520
+ )
5521
 
5522
  # Create update function for tabs
5523
  _spotter_waiting = "Story will be generated after liveboard creation."
 
5961
  controller.settings['thoughtspot_url'] = _url
5962
  if _key_value:
5963
  controller.settings['thoughtspot_trusted_auth_key'] = _key_value
5964
+ elif username:
5965
+ controller.user_email = username
5966
  # Always use the current UI values β€” take priority over DB-loaded defaults
5967
  if liveboard_name_ui is not None:
5968
  controller.settings['liveboard_name'] = liveboard_name_ui
 
6035
  controller.settings['thoughtspot_url'] = _url
6036
  if _key_value:
6037
  controller.settings['thoughtspot_trusted_auth_key'] = _key_value
6038
+ elif username:
6039
+ controller.user_email = username
6040
  if lb_name is not None:
6041
  controller.settings['liveboard_name'] = lb_name
6042
  if model:
 
6068
 
6069
  is_custom = (vertical == "* CUSTOM *")
6070
  hide_welcome = gr.update(visible=False)
6071
+ password_block = controller._temporary_password_block_message()
6072
+ if password_block:
6073
+ history = history or []
6074
+ history.append(("GO", password_block))
6075
+ controller.phase_log = ["Password change required before starting pipeline."]
6076
+ yield (
6077
+ controller,
6078
+ gr.update(value=history, visible=True),
6079
+ stage,
6080
+ model,
6081
+ company,
6082
+ usecase,
6083
+ get_progress_html(stage),
6084
+ hide_welcome,
6085
+ gr.update(open=False),
6086
+ )
6087
+ return
6088
 
6089
  if is_custom:
6090
  # Custom: context field drives the use case