Spaces:
Sleeping
Sleeping
File size: 4,498 Bytes
b0c3a57 1f7c87f b0c3a57 6e640fe b0c3a57 6e640fe b0c3a57 1f7c87f b0c3a57 1f7c87f b0c3a57 1f7c87f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
"""OphthalmoCapture — Basic Authentication Service
Provides a simple login gate using streamlit-authenticator.
Doctors must authenticate before accessing the labeling interface.
Their name is automatically set in the session for audit trails.
If streamlit-authenticator is not installed, authentication is skipped
and the app works in "anonymous" mode.
"""
import streamlit as st
try:
import streamlit_authenticator as stauth
AUTH_AVAILABLE = True
except ImportError:
AUTH_AVAILABLE = False
from i18n import t
# ── Default credentials ──────────────────────────────────────────────────────
# In production, load these from a secure YAML/env. For now, hardcoded demo.
DEFAULT_CREDENTIALS = {
"usernames": {
"admin": {
"name": "Administrador",
"password": "$2b$12$dcvvIg0q/2hZ1pO9gBKqY./LfujFHvoJUvPDLx1qhLS0LtD2kzJoq",
# plain: "admin123" — generate new hashes with stauth.Hasher
},
"Saul": {
"name": "Dr. Saul",
"password": "$2b$12$dcvvIg0q/2hZ1pO9gBKqY./LfujFHvoJUvPDLx1qhLS0LtD2kzJoq",
# plain: "admin123"
},
"Marisse": {
"name": "Dra. Marisse",
"password": "$2b$12$dcvvIg0q/2hZ1pO9gBKqY./LfujFHvoJUvPDLx1qhLS0LtD2kzJoq",
# plain: "admin123"
},
"Angel": {
"name": "Dr. Angel",
"password": "$2b$12$dcvvIg0q/2hZ1pO9gBKqY./LfujFHvoJUvPDLx1qhLS0LtD2kzJoq",
# plain: "admin123"
},
"Enmanuel": {
"name": "Dr. Enmanuel",
"password": "$2b$12$dcvvIg0q/2hZ1pO9gBKqY./LfujFHvoJUvPDLx1qhLS0LtD2kzJoq",
# plain: "admin123"
},
"Micaela": {
"name": "Dra. Micaela",
"password": "$2b$12$dcvvIg0q/2hZ1pO9gBKqY./LfujFHvoJUvPDLx1qhLS0LtD2kzJoq",
# plain: "admin123"
},
"Miguel": {
"name": "Dr. Miguel",
"password": "$2b$12$dcvvIg0q/2hZ1pO9gBKqY./LfujFHvoJUvPDLx1qhLS0LtD2kzJoq",
# plain: "admin123"
},
}
}
COOKIE_NAME = "ophthalmocapture_auth"
COOKIE_KEY = "ophthalmocapture_secret_key"
COOKIE_EXPIRY_DAYS = 1
def _get_authenticator():
"""Return a single shared Authenticate instance per session."""
if "authenticator" not in st.session_state:
st.session_state["authenticator"] = stauth.Authenticate(
credentials=DEFAULT_CREDENTIALS,
cookie_name=COOKIE_NAME,
cookie_key=COOKIE_KEY,
cookie_expiry_days=COOKIE_EXPIRY_DAYS,
)
return st.session_state["authenticator"]
def require_auth() -> bool:
"""Show login form and return True if the user is authenticated.
If streamlit-authenticator is not installed, returns True immediately
(anonymous mode) and sets doctor_name to empty string.
"""
if not AUTH_AVAILABLE:
# Graceful degradation: no auth library → anonymous mode
return True
authenticator = _get_authenticator()
try:
authenticator.login(location="main")
except Exception:
pass
if st.session_state.get("authentication_status"):
# Set doctor name from authenticated user
username = st.session_state.get("username", "")
user_info = DEFAULT_CREDENTIALS["usernames"].get(username, {})
st.session_state.doctor_name = user_info.get("name", username)
return True
elif st.session_state.get("authentication_status") is False:
st.error(t("login_error"))
return False
else:
st.info(t("login_prompt"))
return False
def render_logout_button():
"""Show a logout button in the sidebar (only if auth is active)."""
if not AUTH_AVAILABLE:
return
if st.session_state.get("authentication_status"):
authenticator = _get_authenticator()
authenticator.logout(t("logout"), location="sidebar")
def do_logout():
"""Programmatically log out the current user."""
if not AUTH_AVAILABLE:
return
try:
authenticator = _get_authenticator()
authenticator.logout(location="unrendered")
except Exception:
# Fallback: clear auth keys manually
for key in ("authentication_status", "username", "name", "logout"):
st.session_state.pop(key, None)
st.session_state.pop("authenticator", None)
|