Update app.py
Browse files
app.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
import os
|
|
|
|
| 3 |
import streamlit as st
|
| 4 |
from dotenv import load_dotenv
|
| 5 |
from datetime import date, datetime, time
|
|
@@ -80,6 +81,49 @@ except Exception:
|
|
| 80 |
def bank_label(choice: str) -> str:
|
| 81 |
return "🟢 Produção" if choice == "prod" else "🔴 Teste"
|
| 82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
# ===============================
|
| 84 |
# RERUN por querystring (atalho ?rr=1)
|
| 85 |
# ===============================
|
|
@@ -537,7 +581,6 @@ def _show_birthday_banner_if_needed():
|
|
| 537 |
unsafe_allow_html=True
|
| 538 |
)
|
| 539 |
|
| 540 |
-
|
| 541 |
# ===============================
|
| 542 |
# 🔎 Painel de Diagnóstico de Autenticação (Admin)
|
| 543 |
# ===============================
|
|
@@ -576,7 +619,6 @@ def _render_auth_diag_panel():
|
|
| 576 |
except Exception as e:
|
| 577 |
st.sidebar.error(f"Falha ao importar login.py: {e}")
|
| 578 |
|
| 579 |
-
|
| 580 |
# ===============================
|
| 581 |
# MAIN
|
| 582 |
# ===============================
|
|
@@ -682,7 +724,6 @@ def main():
|
|
| 682 |
|
| 683 |
# 6) Amostra de usuários (sem senhas)
|
| 684 |
try:
|
| 685 |
-
# tenta nomes comuns de colunas
|
| 686 |
sel_cols = [c for c in ["usuario", "email", "perfil", "nome"] if c in cols]
|
| 687 |
sel_expr = ", ".join(sel_cols) if sel_cols else "*"
|
| 688 |
amostra = db.execute(text(f"SELECT {sel_expr} FROM {target_table} LIMIT 5"))
|
|
@@ -700,7 +741,6 @@ def main():
|
|
| 700 |
|
| 701 |
if st.button("Testar bcrypt com este usuário", key="__btn_bcrypt_test__"):
|
| 702 |
try:
|
| 703 |
-
# detectar nome da coluna de senha
|
| 704 |
pass_cols = [c for c in ["senha_hash", "password_hash", "senha", "hash"] if c in cols]
|
| 705 |
user_cols = [c for c in ["usuario", "username", "login"] if c in cols]
|
| 706 |
if not pass_cols or not user_cols:
|
|
@@ -735,6 +775,41 @@ def main():
|
|
| 735 |
except Exception:
|
| 736 |
pass
|
| 737 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 738 |
# 🔄 Botão de Recarregar (mantém a sessão ativa) + ⏱️ Controle do intervalo
|
| 739 |
st.sidebar.markdown("---")
|
| 740 |
col_reload, col_interval = st.sidebar.columns([1, 1])
|
|
@@ -974,7 +1049,7 @@ def main():
|
|
| 974 |
usuario=st.session_state.get("usuario"),
|
| 975 |
ambiente=ambiente_atual
|
| 976 |
)
|
| 977 |
-
ja_nas_opcoes_r = any(mid == "repositorio_load" for mid, _ in (opcoes
|
| 978 |
passa_busca_r = (not termo_busca) or (termo_busca in mod_repo.get("label", "").strip().lower())
|
| 979 |
if mesmo_grupo_r and perfil_ok_r and not ja_nas_opcoes_r and passa_busca_r:
|
| 980 |
opcoes = (opcoes or []) + [("repositorio_load", mod_repo.get("label", "Repositório Load"))]
|
|
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
import os
|
| 3 |
+
import io
|
| 4 |
import streamlit as st
|
| 5 |
from dotenv import load_dotenv
|
| 6 |
from datetime import date, datetime, time
|
|
|
|
| 81 |
def bank_label(choice: str) -> str:
|
| 82 |
return "🟢 Produção" if choice == "prod" else "🔴 Teste"
|
| 83 |
|
| 84 |
+
# =========================================
|
| 85 |
+
# 🔧 STARTUP HOOKS (1x por container / process)
|
| 86 |
+
# =========================================
|
| 87 |
+
# - CLEAR_CACHE_ON_START=1 → limpa caches do Streamlit
|
| 88 |
+
# - INIT_DB_ON_START=1 → tenta rodar init_db.run() e grava ~/.ioirun/.init_done
|
| 89 |
+
_MARKER_DIR = os.path.join(os.path.expanduser("~"), ".ioirun")
|
| 90 |
+
os.makedirs(_MARKER_DIR, exist_ok=True)
|
| 91 |
+
_INIT_MARK = os.path.join(_MARKER_DIR, ".init_done")
|
| 92 |
+
|
| 93 |
+
# Limpa cache no start (não depende de marker; roda a cada start quando flag=1)
|
| 94 |
+
if os.getenv("CLEAR_CACHE_ON_START", "0") == "1":
|
| 95 |
+
try:
|
| 96 |
+
st.cache_data.clear()
|
| 97 |
+
except Exception:
|
| 98 |
+
pass
|
| 99 |
+
try:
|
| 100 |
+
st.cache_resource.clear()
|
| 101 |
+
except Exception:
|
| 102 |
+
pass
|
| 103 |
+
|
| 104 |
+
# Rodar init_db.run() uma única vez por start de container
|
| 105 |
+
try:
|
| 106 |
+
import init_db as _init_db
|
| 107 |
+
_HAS_INIT_DB = hasattr(_init_db, "run")
|
| 108 |
+
except Exception:
|
| 109 |
+
_HAS_INIT_DB = False
|
| 110 |
+
|
| 111 |
+
if os.getenv("INIT_DB_ON_START", "0") == "1" and _HAS_INIT_DB:
|
| 112 |
+
# Só roda se marker não existir OU se variável forçada estiver setada
|
| 113 |
+
force = os.getenv("FORCE_INIT_DB_EVERY_START", "0") == "1"
|
| 114 |
+
should_run = (not os.path.exists(_INIT_MARK)) or force
|
| 115 |
+
if should_run:
|
| 116 |
+
try:
|
| 117 |
+
_init_db.run()
|
| 118 |
+
with open(_INIT_MARK, "w", encoding="utf-8") as f:
|
| 119 |
+
f.write(f"init at {datetime.now().isoformat()}\n")
|
| 120 |
+
except Exception as e:
|
| 121 |
+
# no start, se falhar, apenas registra visualmente
|
| 122 |
+
try:
|
| 123 |
+
st.sidebar.warning(f"INIT_DB_ON_START falhou: {e}")
|
| 124 |
+
except Exception:
|
| 125 |
+
pass
|
| 126 |
+
|
| 127 |
# ===============================
|
| 128 |
# RERUN por querystring (atalho ?rr=1)
|
| 129 |
# ===============================
|
|
|
|
| 581 |
unsafe_allow_html=True
|
| 582 |
)
|
| 583 |
|
|
|
|
| 584 |
# ===============================
|
| 585 |
# 🔎 Painel de Diagnóstico de Autenticação (Admin)
|
| 586 |
# ===============================
|
|
|
|
| 619 |
except Exception as e:
|
| 620 |
st.sidebar.error(f"Falha ao importar login.py: {e}")
|
| 621 |
|
|
|
|
| 622 |
# ===============================
|
| 623 |
# MAIN
|
| 624 |
# ===============================
|
|
|
|
| 724 |
|
| 725 |
# 6) Amostra de usuários (sem senhas)
|
| 726 |
try:
|
|
|
|
| 727 |
sel_cols = [c for c in ["usuario", "email", "perfil", "nome"] if c in cols]
|
| 728 |
sel_expr = ", ".join(sel_cols) if sel_cols else "*"
|
| 729 |
amostra = db.execute(text(f"SELECT {sel_expr} FROM {target_table} LIMIT 5"))
|
|
|
|
| 741 |
|
| 742 |
if st.button("Testar bcrypt com este usuário", key="__btn_bcrypt_test__"):
|
| 743 |
try:
|
|
|
|
| 744 |
pass_cols = [c for c in ["senha_hash", "password_hash", "senha", "hash"] if c in cols]
|
| 745 |
user_cols = [c for c in ["usuario", "username", "login"] if c in cols]
|
| 746 |
if not pass_cols or not user_cols:
|
|
|
|
| 775 |
except Exception:
|
| 776 |
pass
|
| 777 |
|
| 778 |
+
# ============================
|
| 779 |
+
# 🧰 Ações de manutenção (somente Admin)
|
| 780 |
+
# ============================
|
| 781 |
+
with st.sidebar.expander("🧰 Manutenção (Admin)", expanded=False):
|
| 782 |
+
col_m1, col_m2 = st.columns(2)
|
| 783 |
+
if col_m1.button("🧹 Limpar cache agora", use_container_width=True):
|
| 784 |
+
try:
|
| 785 |
+
st.cache_data.clear()
|
| 786 |
+
except Exception:
|
| 787 |
+
pass
|
| 788 |
+
try:
|
| 789 |
+
st.cache_resource.clear()
|
| 790 |
+
except Exception:
|
| 791 |
+
pass
|
| 792 |
+
st.sidebar.success("Caches limpos.")
|
| 793 |
+
st.rerun()
|
| 794 |
+
|
| 795 |
+
# Rodar init_db.run() com dupla confirmação
|
| 796 |
+
if _HAS_INIT_DB:
|
| 797 |
+
c1, c2 = st.columns(2)
|
| 798 |
+
sure1 = c1.checkbox("Confirmo")
|
| 799 |
+
sure2 = c2.checkbox("Estou ciente")
|
| 800 |
+
if st.button("🧬 Rodar init_db.run()", use_container_width=True):
|
| 801 |
+
if not (sure1 and sure2):
|
| 802 |
+
st.warning("Marque as duas confirmações para executar.")
|
| 803 |
+
else:
|
| 804 |
+
try:
|
| 805 |
+
_init_db.run()
|
| 806 |
+
# Atualiza marker
|
| 807 |
+
with open(_INIT_MARK, "w", encoding="utf-8") as f:
|
| 808 |
+
f.write(f"init manual at {datetime.now().isoformat()}\n")
|
| 809 |
+
st.success("init_db.run() executado com sucesso.")
|
| 810 |
+
except Exception as e:
|
| 811 |
+
st.error(f"Falha no init_db.run(): {e}")
|
| 812 |
+
|
| 813 |
# 🔄 Botão de Recarregar (mantém a sessão ativa) + ⏱️ Controle do intervalo
|
| 814 |
st.sidebar.markdown("---")
|
| 815 |
col_reload, col_interval = st.sidebar.columns([1, 1])
|
|
|
|
| 1049 |
usuario=st.session_state.get("usuario"),
|
| 1050 |
ambiente=ambiente_atual
|
| 1051 |
)
|
| 1052 |
+
ja_nas_opcoes_r = any(mid == "repositorio_load" for mid, _ in (opcoes ou []))
|
| 1053 |
passa_busca_r = (not termo_busca) or (termo_busca in mod_repo.get("label", "").strip().lower())
|
| 1054 |
if mesmo_grupo_r and perfil_ok_r and not ja_nas_opcoes_r and passa_busca_r:
|
| 1055 |
opcoes = (opcoes or []) + [("repositorio_load", mod_repo.get("label", "Repositório Load"))]
|