souzat19 commited on
Commit
23940b7
·
verified ·
1 Parent(s): c9fbe6e

Upload 11 files

Browse files
oauth/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # Arquivo vazio para marcar o diretório como um pacote Python
oauth/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (145 Bytes). View file
 
oauth/__pycache__/cadastro.cpython-311.pyc ADDED
Binary file (13.3 kB). View file
 
oauth/__pycache__/login.cpython-311.pyc ADDED
Binary file (2.48 kB). View file
 
oauth/__pycache__/loguin.cpython-311.pyc ADDED
Binary file (3.96 kB). View file
 
oauth/__pycache__/supabase_conex.cpython-311.pyc ADDED
Binary file (4.21 kB). View file
 
oauth/__pycache__/user_manager.cpython-311.pyc ADDED
Binary file (5.01 kB). View file
 
oauth/cadastro.py ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ from pathlib import Path
3
+
4
+ # Adicionar o diretório raiz ao PYTHONPATH
5
+ root_dir = Path(__file__).parent.parent
6
+ sys.path.append(str(root_dir))
7
+
8
+ import streamlit as st
9
+ import pandas as pd
10
+ from oauth.user_manager import UserManager
11
+ from oauth.supabase_conex import SupabaseConnection
12
+ from datetime import datetime
13
+ from sollai.assistentes import CriaAssistente, AssistenteConfig
14
+
15
+ def create_admin_user(email: str, password: str, nome: str, is_admin: bool = False):
16
+ """Cria um novo usuário diretamente"""
17
+ try:
18
+ # Usar admin client para ter permissões totais
19
+ admin_client = SupabaseConnection().get_admin_client()
20
+
21
+ # 1. Criar usuário na auth
22
+ auth_response = admin_client.auth.admin.create_user({
23
+ "email": email,
24
+ "password": password,
25
+ "email_confirm": True,
26
+ "user_metadata": {
27
+ "nome": nome,
28
+ "is_admin": is_admin
29
+ }
30
+ })
31
+
32
+ # Debug detalhado
33
+ print("\n=== Debug Auth Response ===")
34
+ print(f"Tipo: {type(auth_response)}")
35
+ print(f"Dir: {dir(auth_response)}")
36
+ print(f"Raw: {auth_response}")
37
+
38
+ if not auth_response:
39
+ raise Exception("Falha na criação da autenticação")
40
+
41
+ # Tentar diferentes formas de acessar o ID
42
+ user_id = None
43
+ if hasattr(auth_response, 'user'):
44
+ user_id = auth_response.user.id
45
+ elif hasattr(auth_response, 'id'):
46
+ user_id = auth_response.id
47
+ else:
48
+ # Último recurso: converter para dict
49
+ auth_dict = auth_response.model_dump() if hasattr(auth_response, 'model_dump') else vars(auth_response)
50
+ print(f"Auth Dict: {auth_dict}")
51
+ user_id = auth_dict.get('id') or auth_dict.get('user', {}).get('id')
52
+
53
+ if not user_id:
54
+ raise Exception("Não foi possível obter o ID do usuário")
55
+
56
+ # 2. Inserir dados na tabela public.users
57
+ user_data = {
58
+ "id": user_id,
59
+ "email": email,
60
+ "nome": nome,
61
+ "is_admin": is_admin,
62
+ "created_at": datetime.utcnow().isoformat(),
63
+ "updated_at": datetime.utcnow().isoformat(),
64
+ "is_active": True
65
+ }
66
+
67
+ response = admin_client.from_('users')\
68
+ .insert(user_data)\
69
+ .execute()
70
+
71
+ return response.data[0]
72
+
73
+ except Exception as e:
74
+ print(f"\n=== Erro Detalhado ===")
75
+ print(f"Tipo do erro: {type(e)}")
76
+ print(f"Mensagem: {str(e)}")
77
+ import traceback
78
+ print(f"Traceback:\n{traceback.format_exc()}")
79
+ raise Exception(f"Erro ao criar usuário: {str(e)}")
80
+
81
+ def delete_user(user_id: str):
82
+ """Deleta um usuário do sistema"""
83
+ try:
84
+ admin_client = SupabaseConnection().get_admin_client()
85
+
86
+ # 1. Deletar da tabela users primeiro
87
+ response = admin_client.from_('users')\
88
+ .delete()\
89
+ .eq('id', user_id)\
90
+ .execute()
91
+
92
+ # 2. Deletar da autenticação
93
+ auth_response = admin_client.auth.admin.delete_user(user_id)
94
+
95
+ return True
96
+
97
+ except Exception as e:
98
+ print(f"\n=== Erro ao deletar usuário ===")
99
+ print(f"Tipo do erro: {type(e)}")
100
+ print(f"Mensagem: {str(e)}")
101
+ import traceback
102
+ print(f"Traceback:\n{traceback.format_exc()}")
103
+ raise Exception(f"Erro ao deletar usuário: {str(e)}")
104
+
105
+ def create_user(email: str, password: str, nome: str):
106
+ """Cria um novo usuário e seu assistente"""
107
+ try:
108
+ # 1. Criar usuário no Supabase
109
+ user = create_admin_user(
110
+ email=email,
111
+ password=password,
112
+ nome=nome,
113
+ is_admin=False
114
+ )
115
+
116
+ # 2. Criar assistente no Pinecone
117
+ safe_name = "".join(c for c in nome if c.isalnum() or c.isspace()).strip()
118
+ safe_name = safe_name.lower().replace(" ", "-")
119
+ assistant_name = f"assistant-{safe_name}-{user['id'][:8]}"
120
+
121
+ config = AssistenteConfig(
122
+ nome=assistant_name,
123
+ instrucoes="Você é uma assistente amigável que responde perguntas do usuário. Responda sempre em português do Brasil."
124
+ )
125
+
126
+ try:
127
+ criador = CriaAssistente()
128
+ assistente = criador.criar(config)
129
+
130
+ # 3. Atualizar usuário com referências do assistente
131
+ admin_client = SupabaseConnection().get_admin_client()
132
+ response = admin_client.from_('users')\
133
+ .update({
134
+ "assistant_name": assistant_name # Salvando apenas o nome
135
+ })\
136
+ .eq('id', user['id'])\
137
+ .execute()
138
+
139
+ st.success(f"✅ Usuário {nome} criado com sucesso!")
140
+ st.success(f"✅ Assistente '{assistant_name}' criado com sucesso!")
141
+
142
+ return response.data[0]
143
+
144
+ except Exception as e:
145
+ st.error(f"❌ Erro ao criar assistente: {str(e)}")
146
+ delete_user(user['id'])
147
+ raise
148
+
149
+ except Exception as e:
150
+ st.error(f"❌ Erro ao criar usuário: {str(e)}")
151
+ raise
152
+
153
+ def main():
154
+ st.set_page_config(page_title="Cadastro de Usuários", page_icon="👤")
155
+
156
+ st.title("👤 Cadastro de Usuários")
157
+ st.markdown("### Área Administrativa")
158
+
159
+ # Formulário de cadastro
160
+ with st.form("admin_cadastro_form"):
161
+ nome = st.text_input("Nome completo", help="Digite o nome completo do usuário")
162
+ email = st.text_input("Email", help="Digite o email do usuário")
163
+ password = st.text_input("Senha", type="password", help="Mínimo 6 caracteres")
164
+ confirm_password = st.text_input("Confirmar senha", type="password")
165
+ is_admin = st.checkbox("👑 Usuário Administrador")
166
+
167
+ if st.form_submit_button("Criar Usuário"):
168
+ try:
169
+ # Validações
170
+ if not all([nome, email, password, confirm_password]):
171
+ st.error("❌ Todos os campos são obrigatórios!")
172
+ st.stop()
173
+
174
+ if password != confirm_password:
175
+ st.error("❌ As senhas não coincidem!")
176
+ st.stop()
177
+
178
+ if len(password) < 6:
179
+ st.error("❌ A senha deve ter no mínimo 6 caracteres!")
180
+ st.stop()
181
+
182
+ # Criar usuário
183
+ user = create_user(
184
+ email=email,
185
+ password=password,
186
+ nome=nome
187
+ )
188
+
189
+ st.json(user) # Mostra os dados do usuário criado
190
+
191
+ except Exception as e:
192
+ st.error(f"❌ Erro ao criar usuário: {str(e)}")
193
+
194
+ # Lista de usuários existentes
195
+ st.markdown("---")
196
+ st.subheader("📋 Usuários Cadastrados")
197
+
198
+ try:
199
+ admin_client = SupabaseConnection().get_admin_client()
200
+ response = admin_client.from_('users').select('*').execute()
201
+
202
+ if response.data:
203
+ # Criar DataFrame com os dados
204
+ df = pd.DataFrame(response.data)
205
+
206
+ # Mostrar tabela
207
+ st.dataframe(
208
+ df,
209
+ column_config={
210
+ "nome": "Nome",
211
+ "email": "Email",
212
+ "is_admin": "Admin",
213
+ "is_active": "Ativo",
214
+ "created_at": "Criado em"
215
+ },
216
+ hide_index=True
217
+ )
218
+
219
+ # Seleção de usuário para deletar
220
+ usuarios = [(f"{u['nome']} ({u['email']})", u['id']) for u in response.data]
221
+ selected_user = st.selectbox(
222
+ "Selecione um usuário para deletar:",
223
+ options=usuarios,
224
+ format_func=lambda x: x[0]
225
+ )
226
+
227
+ # Botão de deletar com confirmação
228
+ if st.button("🗑️ Deletar Usuário"):
229
+ if st.session_state.get('is_admin'): # Verifica se é admin
230
+ user_id = selected_user[1]
231
+
232
+ # Confirmação adicional
233
+ if st.warning(f"⚠️ Tem certeza que deseja deletar este usuário? Esta ação não pode ser desfeita."):
234
+ try:
235
+ delete_user(user_id)
236
+ st.success("✅ Usuário deletado com sucesso!")
237
+ st.rerun() # Atualiza a página
238
+ except Exception as e:
239
+ st.error(f"❌ Erro ao deletar usuário: {str(e)}")
240
+ else:
241
+ st.error("❌ Apenas administradores podem deletar usuários!")
242
+
243
+ else:
244
+ st.info("Nenhum usuário cadastrado.")
245
+
246
+ except Exception as e:
247
+ st.error(f"❌ Erro ao listar usuários: {str(e)}")
248
+
249
+ if __name__ == "__main__":
250
+ main()
oauth/login.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from oauth.user_manager import UserManager
3
+ from sollai.assistentes import Assistente
4
+
5
+ def main():
6
+ st.title("🔐 Login")
7
+
8
+ with st.form("login_form"):
9
+ email = st.text_input("Email")
10
+ password = st.text_input("Senha", type="password")
11
+
12
+ if st.form_submit_button("Entrar"):
13
+ try:
14
+ user_manager = UserManager()
15
+ user = user_manager.authenticate_user(email, password)
16
+
17
+ if user:
18
+ # Guardar dados do usuário
19
+ st.session_state['user'] = user
20
+ st.session_state['is_authenticated'] = True
21
+
22
+ # Carregar assistente usando o nome
23
+ assistant_name = user.get('assistant_name')
24
+ if assistant_name:
25
+ try:
26
+ assistente = Assistente(assistant_name)
27
+ st.session_state['assistant'] = assistente
28
+ st.success("✅ Login realizado com sucesso!")
29
+ st.rerun()
30
+ except Exception as e:
31
+ st.error(f"❌ Erro ao carregar assistente: {str(e)}")
32
+ else:
33
+ st.error("❌ Você não possui um assistente configurado.")
34
+ else:
35
+ st.error("❌ Email ou senha inválidos!")
36
+
37
+ except Exception as e:
38
+ st.error(f"❌ Erro ao fazer login: {str(e)}")
oauth/supabase_conex.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+ from supabase import create_client, Client
4
+ from typing import Optional
5
+
6
+ load_dotenv()
7
+
8
+ class SupabaseConnection:
9
+ """Gerenciador de conexão com Supabase"""
10
+
11
+ _instance: Optional['SupabaseConnection'] = None
12
+
13
+ def __new__(cls):
14
+ """Implementa Singleton para evitar múltiplas conexões"""
15
+ if cls._instance is None:
16
+ cls._instance = super().__new__(cls)
17
+ return cls._instance
18
+
19
+ def __init__(self):
20
+ """Inicializa a conexão com Supabase"""
21
+ if not hasattr(self, 'client'):
22
+ self.supabase_url = os.getenv("SUPABASE_URL")
23
+ self.supabase_key = os.getenv("SUPABASE_KEY")
24
+ self.service_role_key = os.getenv("SUPABASE_SERVICE_ROLE_KEY")
25
+
26
+ if not all([self.supabase_url, self.supabase_key, self.service_role_key]):
27
+ raise ValueError(
28
+ "SUPABASE_URL, SUPABASE_KEY e SUPABASE_SERVICE_ROLE_KEY devem estar definidos no arquivo .env"
29
+ )
30
+
31
+ # Cliente normal para operações regulares
32
+ self.client = create_client(
33
+ supabase_url=self.supabase_url,
34
+ supabase_key=self.supabase_key
35
+ )
36
+
37
+ # Cliente admin para operações administrativas
38
+ self.admin_client = create_client(
39
+ supabase_url=self.supabase_url,
40
+ supabase_key=self.service_role_key
41
+ )
42
+
43
+ def get_client(self) -> Client:
44
+ """Retorna o cliente Supabase regular"""
45
+ return self.client
46
+
47
+ def get_admin_client(self) -> Client:
48
+ """Retorna o cliente Supabase com privilégios administrativos"""
49
+ return self.admin_client
50
+
51
+ def test_connection(self) -> bool:
52
+ """Testa a conexão com Supabase"""
53
+ try:
54
+ # Tenta fazer uma query simples
55
+ print("🔍 Testando conexão com Supabase...")
56
+ response = self.client.table('users').select("*").limit(1).execute()
57
+ print("✅ Conexão Supabase bem sucedida!")
58
+ return True
59
+
60
+ except Exception as e:
61
+ print(f"❌ Erro na conexão Supabase: {str(e)}")
62
+ return False
63
+
64
+ def get_table(self, table_name: str):
65
+ """
66
+ Retorna uma referência para uma tabela específica
67
+
68
+ Args:
69
+ table_name: Nome da tabela
70
+
71
+ Returns:
72
+ PostgrestFilterBuilder: Referência para a tabela
73
+ """
74
+ return self.client.table(table_name)
oauth/user_manager.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime
2
+ from typing import Dict, Optional, List
3
+ from oauth.supabase_conex import SupabaseConnection
4
+
5
+ class UserManager:
6
+ """Gerenciador de usuários usando Supabase"""
7
+
8
+ def __init__(self):
9
+ self.supabase = SupabaseConnection().get_client()
10
+ self.users_table = 'users'
11
+
12
+ def authenticate_user(self, email: str, password: str) -> Optional[Dict]:
13
+ """Autentica um usuário"""
14
+ try:
15
+ # Autenticar usuário
16
+ auth_response = self.supabase.auth.sign_in_with_password({
17
+ "email": email,
18
+ "password": password
19
+ })
20
+
21
+ if auth_response:
22
+ # Usar admin_client para evitar recursão nas políticas
23
+ admin_client = SupabaseConnection().get_admin_client()
24
+
25
+ # Buscar dados completos do usuário
26
+ user_response = admin_client.from_('users')\
27
+ .select('*')\
28
+ .eq('email', email)\
29
+ .single()\
30
+ .execute()
31
+
32
+ if user_response.data:
33
+ print(f"=== Login realizado com sucesso ===")
34
+ print(f"Usuário: {user_response.data['nome']} ({user_response.data['email']})")
35
+
36
+ # Verificar se tem assistente
37
+ if not user_response.data.get('assistant_name'):
38
+ print("✗ Usuário não possui assistente configurado")
39
+
40
+ return user_response.data
41
+
42
+ return None
43
+
44
+ except Exception as e:
45
+ print(f"Erro na autenticação: {str(e)}")
46
+ raise
47
+
48
+ def get_user(self, user_id: str) -> Optional[Dict]:
49
+ """Busca um usuário pelo ID"""
50
+ try:
51
+ # Usar admin_client para bypass nas políticas
52
+ admin_client = SupabaseConnection().get_admin_client()
53
+
54
+ response = admin_client.from_(self.users_table)\
55
+ .select('*')\
56
+ .eq('id', user_id)\
57
+ .execute()
58
+
59
+ return response.data[0] if response.data else None
60
+
61
+ except Exception as e:
62
+ raise Exception(f"Erro ao buscar usuário: {str(e)}")
63
+
64
+ def get_current_user(self) -> Optional[Dict]:
65
+ """Retorna o usuário atual"""
66
+ try:
67
+ session = self.supabase.auth.get_session()
68
+ if not session:
69
+ return None
70
+
71
+ return self.get_user(session.user.id)
72
+ except Exception as e:
73
+ print(f"Erro ao buscar usuário atual: {str(e)}")
74
+ return None
75
+
76
+ def is_admin(self, user_id: str) -> bool:
77
+ """Verifica se um usuário é admin"""
78
+ try:
79
+ user = self.get_user(user_id)
80
+ return user.get('is_admin', False) if user else False
81
+ except Exception as e:
82
+ print(f"Erro ao verificar admin: {str(e)}")
83
+ return False
84
+
85
+ # Exemplo de uso
86
+ if __name__ == "__main__":
87
+ user_manager = UserManager()
88
+
89
+