-
Notifications
You must be signed in to change notification settings - Fork 34
Add admin functionality to save workspaces as demo templates #324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Adds a new "Save as Demo" option in the sidebar (online mode only) that allows password-protected saving of the current workspace as a demo. The admin password is stored in .streamlit/secrets.toml which is gitignored. - Add src/common/admin.py with admin utilities (password verification, demo saving with symlink handling) - Add .streamlit/secrets.toml.example as a template - Modify sidebar to show Save as Demo expander in online mode - Warn and require confirmation when overwriting existing demos https://claude.ai/code/session_01JzDsFmXBRSFdvGV4TgqXwk
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughAdds admin authentication and demo workspace management: new admin utilities for password verification and demo saving (symlink-aware), a sidebar UI to "Save as Demo" with password flow, a secrets template, and Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as Streamlit UI
participant Admin as Admin Module
participant FS as File System
User->>UI: Enter demo name & click "Save as Demo"
UI->>Admin: is_admin_configured()
Admin-->>UI: configured?
alt not configured
UI->>User: Show error (admin not configured)
else configured
User->>UI: Enter admin password
UI->>Admin: verify_admin_password(password)
Admin-->>UI: verification result
alt verified
UI->>Admin: save_workspace_as_demo(workspace_path, demo_name)
Admin->>FS: validate source & target, prepare dirs
Admin->>FS: remove existing demo (handle symlinks)
Admin->>FS: copytree (follow symlinks)
FS-->>Admin: success / error
Admin-->>UI: return success or error message
UI->>User: Display result (and rerun on success)
else rejected
UI->>User: Show password incorrect
end
end
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@src/common/admin.py`:
- Line 13: The top-level import of is_safe_workspace_name in src/common/admin.py
creates a circular import with src/common/common.py; to fix, remove the
module-level import and either move is_safe_workspace_name into a new utility
module (e.g., src/common/utils.py) and import it from there, or defer the import
inside the save_workspace_as_demo function so the import happens at runtime;
update references in save_workspace_as_demo to use the deferred or relocated
symbol and ensure tests/imports still resolve.
In `@src/common/common.py`:
- Around line 664-693: The admin password stored under the streamlit session key
"admin-password-input" is never removed; update the confirm and cancel flows in
the block that checks st.session_state.get("show_admin_password_dialog") so the
key is deleted after use: when verify_admin_password(admin_password) succeeds
(before hiding the dialog and rerun) remove the "admin-password-input" entry
from st.session_state; when the password is invalid (the else branch under
verify_admin_password) delete the key before showing the error; and when the
Cancel button handler runs delete the key before hiding the dialog and calling
st.rerun(); reference the UI elements and functions in this block (st.text_input
key "admin-password-input", verify_admin_password, save_workspace_as_demo) to
locate where to add the cleanup.
| if st.session_state.get("show_admin_password_dialog", False): | ||
| admin_password = st.text_input( | ||
| "Admin password", | ||
| type="password", | ||
| key="admin-password-input", | ||
| help="Enter the admin password to save this workspace as a demo" | ||
| ) | ||
|
|
||
| col1, col2 = st.columns(2) | ||
| with col1: | ||
| if st.button("Confirm", key="confirm-save-demo"): | ||
| if verify_admin_password(admin_password): | ||
| success, message = save_workspace_as_demo( | ||
| st.session_state.workspace, | ||
| demo_name_clean | ||
| ) | ||
| if success: | ||
| st.success(message) | ||
| st.session_state["show_admin_password_dialog"] = False | ||
| time.sleep(1) | ||
| st.rerun() | ||
| else: | ||
| st.error(message) | ||
| else: | ||
| st.error("Invalid admin password.") | ||
|
|
||
| with col2: | ||
| if st.button("Cancel", key="cancel-save-demo"): | ||
| st.session_state["show_admin_password_dialog"] = False | ||
| st.rerun() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
rg -n "admin-password-input" src/common/common.pyRepository: OpenMS/streamlit-template
Length of output: 128
🏁 Script executed:
sed -n '660,700p' src/common/common.pyRepository: OpenMS/streamlit-template
Length of output: 2180
🏁 Script executed:
rg -n "session_state.*pop|session_state.*del|session_state.*clear" src/Repository: OpenMS/streamlit-template
Length of output: 148
🏁 Script executed:
sed -n '280,290p' src/view.pyRepository: OpenMS/streamlit-template
Length of output: 392
🏁 Script executed:
sed -n '664,695p' src/common/common.py | cat -nRepository: OpenMS/streamlit-template
Length of output: 2000
Clear the admin password from session state after use.
The password input is stored in st.session_state and never cleared. The password persists in memory across all exit paths—success, invalid password attempt, and cancel—even after the dialog is hidden. Remove the key on success, cancel, and invalid password to avoid retaining secrets longer than needed.
🔧 Suggested cleanup
if st.button("Confirm", key="confirm-save-demo"):
if verify_admin_password(admin_password):
success, message = save_workspace_as_demo(
st.session_state.workspace,
demo_name_clean
)
if success:
st.success(message)
st.session_state["show_admin_password_dialog"] = False
+ st.session_state.pop("admin-password-input", None)
time.sleep(1)
st.rerun()
else:
st.error(message)
else:
st.error("Invalid admin password.")
+ st.session_state.pop("admin-password-input", None)
with col2:
if st.button("Cancel", key="cancel-save-demo"):
st.session_state["show_admin_password_dialog"] = False
+ st.session_state.pop("admin-password-input", None)
st.rerun()🤖 Prompt for AI Agents
In `@src/common/common.py` around lines 664 - 693, The admin password stored under
the streamlit session key "admin-password-input" is never removed; update the
confirm and cancel flows in the block that checks
st.session_state.get("show_admin_password_dialog") so the key is deleted after
use: when verify_admin_password(admin_password) succeeds (before hiding the
dialog and rerun) remove the "admin-password-input" entry from st.session_state;
when the password is invalid (the else branch under verify_admin_password)
delete the key before showing the error; and when the Cancel button handler runs
delete the key before hiding the dialog and calling st.rerun(); reference the UI
elements and functions in this block (st.text_input key "admin-password-input",
verify_admin_password, save_workspace_as_demo) to locate where to add the
cleanup.
Defer the import of is_safe_workspace_name inside save_workspace_as_demo to avoid circular dependency between admin.py and common.py. https://claude.ai/code/session_01JzDsFmXBRSFdvGV4TgqXwk
Summary
This PR adds admin-only functionality to save current workspaces as reusable demo templates. It includes password-protected access to prevent unauthorized demo creation, proper secret management, and safe file handling for symlinks.
Key Changes
New admin module (
src/common/admin.py): Provides admin utilities including:Secrets management:
.streamlit/secrets.tomlto.gitignoreto prevent accidental credential commits.streamlit/secrets.toml.exampleas a template for configurationUI integration (
src/common/common.py):Implementation Details
hmac.compare_digest()for secure password comparison to mitigate timing attacksis_safe_workspace_name()utility to prevent path traversal attacksexample-data/workspaces/directoryhttps://claude.ai/code/session_01JzDsFmXBRSFdvGV4TgqXwk
Summary by CodeRabbit
New Features
Documentation
Chores
✏️ Tip: You can customize this high-level summary in your review settings.