1- from fastapi import FastAPI , HTTPException , Request
1+ from fastapi import FastAPI , HTTPException , Request , Depends , Query
22from fastapi .responses import RedirectResponse
3- import firebase_admin
3+
44from firebase_admin import credentials , db , auth
5+ import firebase_admin
6+
57import phonenumbers
68from phonenumbers import PhoneNumberFormat
7- import uuid
9+
10+ from pydantic import BaseModel
11+ from typing import Optional
12+
813from datetime import datetime
914import os
10- from dotenv import load_dotenv
1115import random
1216import string
17+ import uuid
18+ import hashlib
19+ import base64
20+
21+ from dotenv import load_dotenv
1322
1423load_dotenv ()
1524
@@ -61,10 +70,20 @@ def check_uid_exists(uid: str):
6170 print (f"⚠️ Error: { e } " )
6271 return False
6372
64- def generate_random_invite_url (length : int = 12 ) -> str :
73+ def generate_random_invite_key (length : int = 12 ) -> str :
6574 chars = string .ascii_letters + string .digits # A-Z, a-z, 0-9
6675 return '' .join (random .choices (chars , k = length ))
6776
77+ word = os .getenv ("SECRET_API_WORD" )
78+ hash_bytes = hashlib .sha256 (word .encode ()).digest ()
79+ API_KEY = base64 .urlsafe_b64encode (hash_bytes ).rstrip (b'=' ).decode ()
80+ API_KEY_NAME = "api_key"
81+
82+ def get_api_key (api_key : str = Query (default = None , alias = API_KEY_NAME )):
83+ if api_key == API_KEY :
84+ return api_key
85+ raise HTTPException (status_code = 403 , detail = "Chave API não autorizada" )
86+
6887STANDARD_RESPONSES = {
6988 400 : {"description" : "Bad Request" },
7089 401 : {"description" : "Unauthorized" },
@@ -84,7 +103,11 @@ def generate_random_invite_url(length: int = 12) -> str:
84103 },
85104]
86105
87- app = FastAPI (openapi_tags = tags_metadata )
106+ app = FastAPI (title = 'Cosmos API' , openapi_tags = tags_metadata )
107+
108+ class AgendaPatch (BaseModel ):
109+ nome_agenda : Optional [str ] = None
110+ uid_do_responsável : Optional [str ] = None
88111
89112@app .get ("/" )
90113def read_root ():
@@ -94,20 +117,20 @@ def read_root():
94117def testar_o_firebase ():
95118 try :
96119 if ref .get ():
97- message = "Conectado com successo ao Firebase"
98- return {"message" : message }
120+ return {"message" : "Conectado com successo ao Firebase" }
99121 except Exception as e :
100122 raise HTTPException (status_code = 500 , detail = f"Falha ao se conectar com o Firebase: { str (e )} " )
101123
102- from fastapi import APIRouter
103-
104- @app .get ("/invite/{uid_da_agenda}" , responses = STANDARD_RESPONSES )
105- def mandar_um_convite_para_entrar_na_turma_tipo_o_whatsapp (uid_da_agenda : str , request : Request ):
106- agenda_node = agenda_ref .child (uid_da_agenda )
124+ @app .get ("/invite/{chave_de_convite_da_agenda}" , responses = STANDARD_RESPONSES )
125+ def mandar_um_convite_para_entrar_na_turma_tipo_o_whatsapp (chave_de_convite_da_agenda : str , request : Request ):
126+ agenda_node = agenda_ref .order_by_child ('chave_de_convite' ).equal_to (chave_de_convite_da_agenda )
107127 agenda_data = agenda_node .get ()
108128
109129 if not agenda_data :
110- raise HTTPException (status_code = 404 , detail = f"A agenda com o UID { uid_da_agenda } não existe" )
130+ raise HTTPException (status_code = 404 , detail = f"Essa agenda não existe" )
131+
132+ for key , val in agenda_data .items ():
133+ return (f"UID da Agenda: { key } , Data: { val } " )
111134
112135 # Detecta o dispositivo
113136 user_agent = request .headers .get ("user-agent" , "" ).lower ()
@@ -134,7 +157,7 @@ def mandar_um_convite_para_entrar_na_turma_tipo_o_whatsapp(uid_da_agenda: str, r
134157 return RedirectResponse (play_store_url )
135158
136159@app .get ("/getAllUsers/" , tags = ["Usuários" ], responses = STANDARD_RESPONSES )
137- def conseguir_todos_os_usuarios_logado_com_o_email_normal_no_firebase ():
160+ def conseguir_todos_os_usuarios_logado_com_o_email_normal_no_firebase (api_key : str = Depends ( get_api_key ) ):
138161 users = []
139162 page = auth .list_users ()
140163 while page :
@@ -146,60 +169,57 @@ def conseguir_todos_os_usuarios_logado_com_o_email_normal_no_firebase():
146169 "passwordSalt" : user .password_salt ,
147170 "display_name" : user .display_name ,
148171 "phone_number" : user .phone_number or "" ,
149- "invite_url" : user .invite_url ,
150- "photo_url" : user .photo_url or "" ,
172+ "photo_url" : user .photo_url or ""
151173 })
152174 page = page .get_next_page ()
153175 return users
154176
155177@app .post ("/add/user/" , tags = ["Usuários" ], responses = STANDARD_RESPONSES )
156- async def criar_um_usuario_com_email_e_senha (email : str , password : str , display_name : str , phone_number : str | None = None , photo_url : str | None = None ):
178+ async def criar_um_usuario_com_email_e_senha (email : str , password : str , display_name : str , phone_number : str | None = None , photo_url : str | None = None , api_key : str = Depends ( get_api_key ) ):
157179 user = auth .create_user (
158180 email = email ,
159181 email_verified = False ,
160182 phone_number = to_e164_br (phone_number ),
161183 password = password ,
162184 display_name = display_name ,
163185 photo_url = photo_url ,
164- invite_url = generate_random_invite_url (),
165186 disabled = False )
166- message = 'Criado um usuário com sucesso. UID: {0}' . format ( user . uid )
167- return {"message" : message }
187+
188+ return {"message" : 'Criado um usuário com sucesso. UID: {0}' . format ( user . uid ) }
168189
169190@app .delete ("/delete/user" , tags = ["Usuários" ], responses = STANDARD_RESPONSES )
170- async def deletar_um_usuario_com_o_uid (uid : str ):
191+ async def deletar_um_usuario_com_o_uid (uid : str , api_key : str = Depends ( get_api_key ) ):
171192 if check_uid_exists (uid ):
172193 auth .delete_user (uid )
173- message = f'O usuário com o UID { uid } foi deletado com sucesso.'
174- return {"message" : message }
194+ return {"message" : f'O usuário com o UID { uid } foi deletado com sucesso.' }
175195 else :
176196 raise HTTPException (status_code = 400 , detail = "Este usuário não existe no banco de dados" )
177197
178198@app .get ("/getAllAgendas" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
179- async def mostrar_todas_as_agendas_criadas ():
199+ async def mostrar_todas_as_agendas_criadas (api_key : str = Depends ( get_api_key ) ):
180200 if agenda_ref .get () is None :
181- message = f'Nenhuma agenda foi criada'
182- return {"message" : message }
201+ return {"message" : 'Nenhuma agenda foi criada' }
183202 else :
184203 return agenda_ref .get ()
185204
186205@app .post ("/add/agenda/" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
187- async def criar_uma_agenda (nome_agenda : str , uid_do_responsavel : str ):
206+ async def criar_uma_agenda (nome_agenda : str , uid_do_responsavel : str , api_key : str = Depends ( get_api_key ) ):
188207 if check_uid_exists (uid_do_responsavel ):
189208 uid = str (uuid .uuid4 ())
190209 agenda_ref .update ({
191210 uid : {
192211 'nome_agenda' : nome_agenda ,
193- 'uid_do_responsável' : uid_do_responsavel
212+ 'uid_do_responsável' : uid_do_responsavel ,
213+ 'chave_de_convite' : generate_random_invite_key ()
194214 }
195215 })
196- message = f'A agenda { nome_agenda } com o UID { uid } foi criada com sucesso'
197- return {"message" : message }
216+
217+ return {"message" : f'A agenda { nome_agenda } com o UID { uid } foi criada com sucesso' }
198218 else :
199219 raise HTTPException (status_code = 401 , detail = "Este usuário não existe no banco de dados" )
200220
201221@app .post ("/add/agenda/membro" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
202- async def adicionar_um_membro_na_agenda_já_criada (uid_da_agenda : str , uid_do_membro : str ):
222+ async def adicionar_um_membro_na_agenda_já_criada (uid_da_agenda : str , uid_do_membro : str , api_key : str = Depends ( get_api_key ) ):
203223 agenda_node = agenda_ref .child (uid_da_agenda )
204224 agenda_data = agenda_node .get ()
205225 if not agenda_data :
@@ -216,11 +236,11 @@ async def adicionar_um_membro_na_agenda_já_criada(uid_da_agenda: str, uid_do_me
216236 'nome_do_usuário' : user .display_name
217237 }
218238 })
219- message = f'O membro { user . display } com o UID { user . uid } foi adicionado com sucesso'
220- return {"message" : message }
239+
240+ return {"message" : f'O membro { user . display } com o UID { user . uid } foi adicionado com sucesso' }
221241
222242@app .post ("/add/agenda/materia" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
223- async def criar_uma_materia_na_agenda_já_criada (uid_da_agenda : str , nome_da_matéria : str , nome_do_professor : str | None = None , horario_de_inicio_da_materia : str | None = None , horario_de_fim_da_materia : str | None = None ):
243+ async def criar_uma_materia_na_agenda_já_criada (uid_da_agenda : str , nome_da_matéria : str , nome_do_professor : str | None = None , horario_de_inicio_da_materia : str | None = None , horario_de_fim_da_materia : str | None = None , api_key : str = Depends ( get_api_key ) ):
224244 agenda_node = agenda_ref .child (uid_da_agenda )
225245 agenda_data = agenda_node .get ()
226246 if not agenda_data :
@@ -236,11 +256,11 @@ async def criar_uma_materia_na_agenda_já_criada(uid_da_agenda: str, nome_da_mat
236256 "horário_de_fim" : horario_de_fim_da_materia
237257 }
238258 })
239- message = f'A matéria { nome_da_matéria } com o UID { uid } foi criada com sucesso'
240- return {"message" : message }
259+
260+ return {"message" : f'A matéria { nome_da_matéria } com o UID { uid } foi criada com sucesso' }
241261
242262@app .post ("/add/agenda/tarefa" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
243- async def criar_uma_tarefa_na_agenda_já_criada (uid_da_agenda : str , nome_da_tarefa : str , timestamp : str ):
263+ async def criar_uma_tarefa_na_agenda_já_criada (uid_da_agenda : str , nome_da_tarefa : str , timestamp : str , api_key : str = Depends ( get_api_key ) ):
244264 agenda_node = agenda_ref .child (uid_da_agenda )
245265 agenda_data = agenda_node .get ()
246266 if not agenda_data :
@@ -254,11 +274,11 @@ async def criar_uma_tarefa_na_agenda_já_criada(uid_da_agenda: str, nome_da_tare
254274 'timestamp' : timestamp_formatado (timestamp )
255275 }
256276 })
257- message = f'A tarefa com o UID { uid } foi criada com sucesso.'
258- return {"message" : message }
277+
278+ return {"message" : f'A tarefa com o UID { uid } foi criada com sucesso.' }
259279
260280@app .post ("/add/agenda/evento" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
261- async def criar_um_evento_na_agenda_já_criada (uid_da_agenda : str , nome_do_evento : str , timestamp : str ):
281+ async def criar_um_evento_na_agenda_já_criada (uid_da_agenda : str , nome_do_evento : str , timestamp : str , api_key : str = Depends ( get_api_key ) ):
262282 agenda_node = agenda_ref .child (uid_da_agenda )
263283 agenda_data = agenda_node .get ()
264284 if not agenda_data :
@@ -272,49 +292,137 @@ async def criar_um_evento_na_agenda_já_criada(uid_da_agenda: str, nome_do_event
272292 'timestamp' : timestamp_formatado (timestamp )
273293 }
274294 })
275- message = f'O evento com o UID { uid } foi criado com sucesso.'
276- return {"message" : message }
295+
296+ return {"message" : f'O evento com o UID { uid } foi criado com sucesso.' }
277297
278298@app .delete ("/delete/agenda/" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
279- async def deletar_uma_agenda_com_o_uid (uid_da_agenda : str ):
299+ async def deletar_uma_agenda_com_o_uid (uid_da_agenda : str , api_key : str = Depends ( get_api_key ) ):
280300 agenda_node = agenda_ref .child (uid_da_agenda )
281301 agenda_data = agenda_node .get ()
282302 if not agenda_data :
283303 raise HTTPException (status_code = 404 , detail = f"A agenda com o UID { uid_da_agenda } não existe" )
284304
285305 agenda_node .delete ()
286- message = f'A agenda com o UID { uid_da_agenda } foi deletada com sucesso.'
287- return {"message" : message }
306+
307+ return {"message" : f'A agenda com o UID { uid_da_agenda } foi deletada com sucesso.' }
288308
289309@app .delete ("/delete/agenda/materia" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
290- async def deletar_uma_materia_com_o_uid (uid_da_agenda : str , uid_da_materia : str ):
310+ async def deletar_uma_materia_com_o_uid (uid_da_agenda : str , uid_da_materia : str , api_key : str = Depends ( get_api_key ) ):
291311 matéria_node = agenda_ref .child (uid_da_agenda ).child ("matérias" ).child (uid_da_materia )
292312 matéria_data = matéria_node .get ()
293313 if not matéria_data :
294314 raise HTTPException (status_code = 404 , detail = f"A matéria com o UID { uid_da_materia } na agenda { uid_da_agenda } não existe" )
295315
296316 matéria_node .delete ()
297- message = f'A matéria com o UID { uid_da_materia } foi deletada com sucesso.'
298- return {"message" : message }
317+
318+ return {"message" : f'A matéria com o UID { uid_da_materia } foi deletada com sucesso.' }
299319
300320@app .delete ("/delete/agenda/tarefa" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
301- async def deletar_uma_tarefa_com_o_uid (uid_da_agenda : str , uid_da_tarefa : str ):
321+ async def deletar_uma_tarefa_com_o_uid (uid_da_agenda : str , uid_da_tarefa : str , api_key : str = Depends ( get_api_key ) ):
302322 tarefa_node = agenda_ref .child (uid_da_agenda ).child ("tarefas" ).child (uid_da_tarefa )
303323 tarefa_data = tarefa_node .get ()
304324 if not tarefa_data :
305325 raise HTTPException (status_code = 404 , detail = f"A tarefa com o UID { uid_da_tarefa } na agenda { uid_da_agenda } não existe" )
306326
307327 tarefa_node .delete ()
308- message = f'A tarefa com o UID { uid_da_tarefa } foi deletada com sucesso.'
309- return {"message" : message }
328+
329+ return {"message" : f'A tarefa com o UID { uid_da_tarefa } foi deletada com sucesso.' }
310330
311331@app .delete ("/delete/agenda/evento" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
312- async def deletar_um_evento_com_o_uid (uid_da_agenda : str , uid_do_evento : str ):
332+ async def deletar_um_evento_com_o_uid (uid_da_agenda : str , uid_do_evento : str , api_key : str = Depends ( get_api_key ) ):
313333 evento_node = agenda_ref .child (uid_da_agenda ).child ("eventos" ).child (uid_do_evento )
314334 evento_data = evento_node .get ()
315335 if not evento_data :
316336 raise HTTPException (status_code = 404 , detail = f"O evento com o UID { uid_do_evento } na agenda { uid_da_agenda } não existe" )
317337
318338 evento_node .delete ()
319- message = f'O evento com o UID { uid_do_evento } foi deletado com sucesso.'
320- return {"message" : message }
339+
340+ return {"message" : f'O evento com o UID { uid_do_evento } foi deletado com sucesso.' }
341+
342+ @app .patch ("/update/agenda" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
343+ async def atualizar_os_dados_da_agenda (uid_da_agenda : str = Query (...), nome_agenda : str = Query (None ), uid_do_responsável : str = Query (None ), api_key : str = Depends (get_api_key )):
344+ agenda_node = agenda_ref .child (uid_da_agenda )
345+ agenda_data = agenda_node .get ()
346+ if not agenda_data :
347+ raise HTTPException (status_code = 404 , detail = f"A agenda com o UID { uid_da_agenda } não existe" )
348+
349+ update_data = {}
350+ if nome_agenda is not None :
351+ update_data ["nome_agenda" ] = nome_agenda
352+ if uid_do_responsável is not None :
353+ update_data ["uid_do_responsável" ] = uid_do_responsável
354+
355+ if not update_data :
356+ raise HTTPException (status_code = 400 , detail = "Nenhum dado fornecido para atualização" )
357+
358+ agenda_node .update (update_data )
359+
360+ return {"message" : "Agenda atualizada com sucesso" , "dados" : update_data }
361+
362+ @app .patch ("/update/agenda/materia" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
363+ async def atualizar_os_dados_da_agenda (uid_da_agenda : str = Query (...), uid_da_materia : str = Query (...), nome_da_matéria : str = Query (None ), nome_do_professor : str = Query (None ), horario_de_inicio_da_materia : str = Query (None ), horario_de_fim_da_materia : str = Query (None ), api_key : str = Depends (get_api_key )):
364+ agenda_node = agenda_ref .child (uid_da_agenda ).child ("matérias" ).child (uid_da_materia )
365+ agenda_data = agenda_node .get ()
366+ if not matéria_data :
367+ raise HTTPException (status_code = 404 , detail = f"A matéria com o UID { uid_da_materia } na agenda { uid_da_agenda } não existe" )
368+
369+ update_data = {}
370+ if nome_da_matéria is not None :
371+ update_data ["nome_matéria" ] = nome_da_matéria
372+ if nome_do_professor is not None :
373+ update_data ["professor" ] = nome_do_professor
374+ if horario_de_inicio_da_materia is not None :
375+ update_data ["horario_de_início" ] = horario_de_inicio_da_materia
376+ if horario_de_fim_da_materia is not None :
377+ update_data ["horario_de_fim" ] = horario_de_fim_da_materia
378+
379+ if not update_data :
380+ raise HTTPException (status_code = 400 , detail = "Nenhum dado fornecido para atualização" )
381+
382+ agenda_node .update (update_data )
383+
384+ return {"message" : "Agenda atualizada com sucesso" , "dados" : update_data }
385+
386+ @app .patch ("/update/agenda/tarefa" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
387+ async def atualizar_os_dados_da_agenda (uid_da_agenda : str = Query (...), uid_da_tarefa : str = Query (...), nome_da_tarefa : str = Query (None ), timestamp : str = Query (None ), api_key : str = Depends (get_api_key )):
388+ agenda_node = agenda_ref .child (uid_da_agenda ).child ("tarefas" ).child (uid_da_tarefa )
389+ agenda_data = agenda_node .get ()
390+ if not matéria_data :
391+ raise HTTPException (status_code = 404 , detail = f"A tarefa com o UID { uid_da_tarefa } na agenda { uid_da_agenda } não existe" )
392+
393+ timestamp_definido = timestamp_formatado (timestamp )
394+
395+ update_data = {}
396+ if nome_da_tarefa is not None :
397+ update_data ["nome_da_tarefa" ] = nome_da_tarefa
398+ if timestamp_definido is not None :
399+ update_data ["timestamp" ] = timestamp_definido
400+
401+ if not update_data :
402+ raise HTTPException (status_code = 400 , detail = "Nenhum dado fornecido para atualização" )
403+
404+ agenda_node .update (update_data )
405+
406+ return {"message" : "Agenda atualizada com sucesso" , "dados" : update_data }
407+
408+ @app .patch ("/update/agenda/evento" , tags = ["Agenda" ], responses = STANDARD_RESPONSES )
409+ async def atualizar_os_dados_da_agenda (uid_da_agenda : str = Query (...), uid_do_evento : str = Query (...), nome_do_evento : str = Query (None ), timestamp : str = Query (None ), api_key : str = Depends (get_api_key )):
410+ agenda_node = agenda_ref .child (uid_da_agenda ).child ("eventos" ).child (uid_do_evento )
411+ agenda_data = agenda_node .get ()
412+ if not matéria_data :
413+ raise HTTPException (status_code = 404 , detail = f"O evento com o UID { uid_do_evento } na agenda { uid_da_agenda } não existe" )
414+
415+ timestamp_definido = timestamp_formatado (timestamp )
416+
417+ update_data = {}
418+ if nome_da_tarefa is not None :
419+ update_data ["nome_do_evento" ] = nome_do_evento
420+ if timestamp_definido is not None :
421+ update_data ["timestamp" ] = timestamp_definido
422+
423+ if not update_data :
424+ raise HTTPException (status_code = 400 , detail = "Nenhum dado fornecido para atualização" )
425+
426+ agenda_node .update (update_data )
427+
428+ return {"message" : "Agenda atualizada com sucesso" , "dados" : update_data }
0 commit comments