Update app.py
Browse files
app.py
CHANGED
|
@@ -774,6 +774,91 @@ def _db_choice_ui():
|
|
| 774 |
except Exception as e:
|
| 775 |
st.sidebar.caption(f"⚙️ DEBUG router fail: {e}")
|
| 776 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 777 |
# ===============================
|
| 778 |
# MAIN
|
| 779 |
# ===============================
|
|
@@ -798,11 +883,11 @@ def main():
|
|
| 798 |
# ===== Seleção de banco (sempre visível na sidebar) =====
|
| 799 |
_db_choice_ui()
|
| 800 |
|
| 801 |
-
# 🔧 Manutenção do banco atual: Schema + init_db.run()
|
| 802 |
try:
|
| 803 |
from banco import init_schema
|
| 804 |
with st.sidebar.expander("⚙️ Manutenção do banco atual", expanded=False):
|
| 805 |
-
if st.button("Criar/atualizar schema neste banco", key="__btn_init_schema__"):
|
| 806 |
try:
|
| 807 |
init_schema()
|
| 808 |
st.sidebar.success("Schema criado/atualizado no banco selecionado com sucesso.")
|
|
@@ -823,6 +908,47 @@ def main():
|
|
| 823 |
st.success("init_db.run() executado com sucesso no banco selecionado.")
|
| 824 |
except Exception as e:
|
| 825 |
st.error(f"Falha ao rodar init_db.run(): {e}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 826 |
except Exception:
|
| 827 |
pass
|
| 828 |
|
|
|
|
| 774 |
except Exception as e:
|
| 775 |
st.sidebar.caption(f"⚙️ DEBUG router fail: {e}")
|
| 776 |
|
| 777 |
+
# ===============================
|
| 778 |
+
# 🔴 Zerar banco (somente Admin, e apenas test/treinamento)
|
| 779 |
+
# ===============================
|
| 780 |
+
def _wipe_current_database_safely():
|
| 781 |
+
"""
|
| 782 |
+
Zera totalmente o banco ATUAL selecionado no router (apenas test/treinamento).
|
| 783 |
+
- SQLite: remove o arquivo físico e recria o schema.
|
| 784 |
+
- Postgres/MySQL: drop_all + recreate.
|
| 785 |
+
"""
|
| 786 |
+
try:
|
| 787 |
+
from db_router import current_db_choice
|
| 788 |
+
except Exception:
|
| 789 |
+
st.error("Router indisponível. Não é possível determinar o banco atual.")
|
| 790 |
+
return
|
| 791 |
+
|
| 792 |
+
from sqlalchemy.engine.url import make_url
|
| 793 |
+
from banco import get_engine, init_schema, Base
|
| 794 |
+
|
| 795 |
+
choice = (current_db_choice() or "").strip().lower()
|
| 796 |
+
if choice not in ("test", "treinamento", "train"):
|
| 797 |
+
st.error("Operação bloqueada: só é permitido zerar **Teste** ou **Treinamento**.")
|
| 798 |
+
return
|
| 799 |
+
|
| 800 |
+
eng = get_engine()
|
| 801 |
+
url = str(eng.url)
|
| 802 |
+
url_obj = make_url(url)
|
| 803 |
+
|
| 804 |
+
try:
|
| 805 |
+
if url_obj.drivername.startswith("sqlite"):
|
| 806 |
+
# Caminho do arquivo
|
| 807 |
+
path = url.replace("sqlite:///", "", 1)
|
| 808 |
+
if path.startswith("//"):
|
| 809 |
+
path = path[1:]
|
| 810 |
+
file_path = os.path.abspath(path)
|
| 811 |
+
|
| 812 |
+
# Fecha conexões e apaga arquivo
|
| 813 |
+
try:
|
| 814 |
+
eng.dispose()
|
| 815 |
+
except Exception:
|
| 816 |
+
pass
|
| 817 |
+
|
| 818 |
+
try:
|
| 819 |
+
if os.path.exists(file_path):
|
| 820 |
+
os.remove(file_path)
|
| 821 |
+
else:
|
| 822 |
+
# Pode estar no ~/.ioirun/<arquivo>
|
| 823 |
+
home_alt = os.path.join(os.path.expanduser("~"), ".ioirun", os.path.basename(file_path))
|
| 824 |
+
if os.path.exists(home_alt):
|
| 825 |
+
os.remove(home_alt)
|
| 826 |
+
except Exception as e_rm:
|
| 827 |
+
st.error(f"Falha ao remover arquivo SQLite: {e_rm}")
|
| 828 |
+
return
|
| 829 |
+
|
| 830 |
+
# Recria o schema do zero no arquivo recém criado
|
| 831 |
+
try:
|
| 832 |
+
init_schema()
|
| 833 |
+
except Exception as e_schema:
|
| 834 |
+
st.error(f"Falha ao recriar schema após remoção do arquivo: {e_schema}")
|
| 835 |
+
return
|
| 836 |
+
|
| 837 |
+
else:
|
| 838 |
+
# Postgres/MySQL: drop_all + create_all
|
| 839 |
+
try:
|
| 840 |
+
Base.metadata.drop_all(bind=eng)
|
| 841 |
+
except Exception as e_drop:
|
| 842 |
+
st.error(f"Falha no drop de tabelas: {e_drop}")
|
| 843 |
+
return
|
| 844 |
+
try:
|
| 845 |
+
init_schema()
|
| 846 |
+
except Exception as e_create:
|
| 847 |
+
st.error(f"Falha ao recriar schema: {e_create}")
|
| 848 |
+
return
|
| 849 |
+
|
| 850 |
+
st.success("✅ Banco zerado e schema recriado com sucesso.")
|
| 851 |
+
try:
|
| 852 |
+
st.toast("Banco zerado com sucesso.", icon="🗑️")
|
| 853 |
+
except Exception:
|
| 854 |
+
pass
|
| 855 |
+
|
| 856 |
+
# Rerun para refletir o novo estado
|
| 857 |
+
st.rerun()
|
| 858 |
+
|
| 859 |
+
except Exception as e:
|
| 860 |
+
st.error(f"Erro ao zerar o banco: {e}")
|
| 861 |
+
|
| 862 |
# ===============================
|
| 863 |
# MAIN
|
| 864 |
# ===============================
|
|
|
|
| 883 |
# ===== Seleção de banco (sempre visível na sidebar) =====
|
| 884 |
_db_choice_ui()
|
| 885 |
|
| 886 |
+
# 🔧 Manutenção do banco atual: Schema + init_db.run() + Zerar banco (Admin)
|
| 887 |
try:
|
| 888 |
from banco import init_schema
|
| 889 |
with st.sidebar.expander("⚙️ Manutenção do banco atual", expanded=False):
|
| 890 |
+
if st.button("Criar/atualizar schema neste banco", key="__btn_init_schema__", type="secondary"):
|
| 891 |
try:
|
| 892 |
init_schema()
|
| 893 |
st.sidebar.success("Schema criado/atualizado no banco selecionado com sucesso.")
|
|
|
|
| 908 |
st.success("init_db.run() executado com sucesso no banco selecionado.")
|
| 909 |
except Exception as e:
|
| 910 |
st.error(f"Falha ao rodar init_db.run(): {e}")
|
| 911 |
+
|
| 912 |
+
# 🔴 Zerar banco (somente Admin, e nunca em Produção)
|
| 913 |
+
try:
|
| 914 |
+
perfil_atual = (st.session_state.get("perfil") or "").strip().lower()
|
| 915 |
+
ch = current_db_choice() if _HAS_ROUTER else "prod"
|
| 916 |
+
except Exception:
|
| 917 |
+
perfil_atual = (st.session_state.get("perfil") or "").strip().lower()
|
| 918 |
+
ch = "prod"
|
| 919 |
+
|
| 920 |
+
if perfil_atual == "admin":
|
| 921 |
+
st.markdown("---")
|
| 922 |
+
st.markdown("### 🧨 Zerar banco (somente Admin)")
|
| 923 |
+
# Exibir apenas se não for produção
|
| 924 |
+
if ch in ("test", "treinamento", "train"):
|
| 925 |
+
st.info("Esta ação **apaga todo o conteúdo** do banco **selecionado** (Test/Treinamento) e recria o schema. **Irreversível.**")
|
| 926 |
+
colz1, colz2 = st.columns(2)
|
| 927 |
+
z_conf1 = colz1.checkbox("Confirmo que entendo os riscos", key="__wipe_c1__")
|
| 928 |
+
z_conf2 = colz2.checkbox("Estou ciente que é irreversível", key="__wipe_c2__")
|
| 929 |
+
safe_phrase = st.text_input("Digite **ZERAR** para habilitar", key="__wipe_phrase__")
|
| 930 |
+
# Seleção explícita do banco-alvo (precisa coincidir com o atual)
|
| 931 |
+
alvo = st.selectbox(
|
| 932 |
+
"Banco a zerar (deve ser o banco atual):",
|
| 933 |
+
["test", "treinamento"],
|
| 934 |
+
index=(0 if ch == "test" else 1 if ch in ("treinamento", "train") else 0),
|
| 935 |
+
key="__wipe_target__"
|
| 936 |
+
)
|
| 937 |
+
|
| 938 |
+
btn_wipe = st.button("🗑️ ZERAR banco **ATUAL**", key="__btn_wipe_db__", type="secondary")
|
| 939 |
+
if btn_wipe:
|
| 940 |
+
if alvo not in ("test", "treinamento"):
|
| 941 |
+
st.error("Selecione um alvo válido (test/treinamento).")
|
| 942 |
+
elif alvo != ("treinamento" if ch in ("treinamento", "train") else ch):
|
| 943 |
+
st.error("O alvo selecionado **não coincide** com o banco atual. Ajuste a seleção.")
|
| 944 |
+
elif not (z_conf1 and z_conf2):
|
| 945 |
+
st.error("Marque as duas confirmações para continuar.")
|
| 946 |
+
elif safe_phrase.strip().upper() != "ZERAR":
|
| 947 |
+
st.error("Frase de segurança incorreta. Digite exatamente **ZERAR**.")
|
| 948 |
+
else:
|
| 949 |
+
_wipe_current_database_safely()
|
| 950 |
+
else:
|
| 951 |
+
st.warning("Zerar banco indisponível: **Produção** está selecionado. Troque para **Teste** ou **Treinamento** para habilitar.")
|
| 952 |
except Exception:
|
| 953 |
pass
|
| 954 |
|