habulaj commited on
Commit
a65980c
·
verified ·
1 Parent(s): 2ceb8de

Update routes/users.py

Browse files
Files changed (1) hide show
  1. routes/users.py +1 -261
routes/users.py CHANGED
@@ -13,9 +13,6 @@ router = APIRouter()
13
  SUPABASE_URL = "https://ussxqnifefkgkaumjann.supabase.co"
14
  SUPABASE_KEY = os.getenv("SUPA_KEY")
15
  SUPABASE_ROLE_KEY = os.getenv("SUPA_SERVICE_KEY")
16
-
17
- class FeedDeleteRequest(BaseModel):
18
- feed_id: int
19
 
20
  if not SUPABASE_KEY or not SUPABASE_ROLE_KEY:
21
  raise ValueError("❌ SUPA_KEY ou SUPA_SERVICE_KEY não foram definidos no ambiente!")
@@ -198,261 +195,4 @@ async def get_recent_users_endpoint(
198
 
199
  except Exception as e:
200
  logger.error(f"❌ Erro ao obter usuários: {str(e)}")
201
- raise HTTPException(status_code=500, detail=str(e))
202
-
203
- @router.post("/admin/update-user")
204
- async def update_user(
205
- request: Dict[str, Any],
206
- user_token: str = Header(None, alias="User-key")
207
- ):
208
- """
209
- Endpoint para atualizar informações de um usuário específico.
210
- Atualmente suporta atualização de name e fee.
211
- Usa a chave de serviço para bypassar RLS do Supabase.
212
- """
213
- try:
214
- # Verificar se o usuário tem permissão para gerenciar usuários
215
- user_info = await verify_token_with_permissions(user_token, "manage_users")
216
- admin_id = user_info["user_id"]
217
-
218
- # Validar os parâmetros da requisição
219
- user_id = request.get("user_id")
220
- name = request.get("name")
221
- fee = request.get("fee")
222
-
223
- if not user_id:
224
- raise HTTPException(status_code=400, detail="ID do usuário é obrigatório")
225
-
226
- if name is None and fee is None:
227
- raise HTTPException(status_code=400, detail="Pelo menos um campo para atualização (name ou fee) deve ser fornecido")
228
-
229
- # Verificar se o usuário existe - usando os headers normais para consulta
230
- user_query = f"{SUPABASE_URL}/rest/v1/User?select=name,fee&id=eq.{user_id}"
231
-
232
- async with aiohttp.ClientSession() as session:
233
- async with session.get(user_query, headers=SUPABASE_HEADERS) as response:
234
- if response.status != 200:
235
- logger.error(f"❌ Erro ao verificar usuário: {response.status}")
236
- raise HTTPException(status_code=response.status, detail="Erro ao consultar usuário")
237
-
238
- user_data = await response.json()
239
-
240
- if not user_data:
241
- raise HTTPException(status_code=404, detail="Usuário não encontrado")
242
-
243
- current_user = user_data[0]
244
-
245
- # Preparar os campos para atualização, apenas se forem diferentes
246
- update_fields = {}
247
-
248
- if name is not None and name != current_user.get("name"):
249
- update_fields["name"] = name
250
-
251
- if fee is not None and isinstance(fee, int) and fee != current_user.get("fee"):
252
- update_fields["fee"] = fee
253
-
254
- # Se não há campos para atualizar, retornar sem modificar
255
- if not update_fields:
256
- return {"message": "Nenhuma alteração necessária", "user_id": user_id}
257
-
258
- # Atualizar o usuário no Supabase usando a chave de serviço para bypassar RLS
259
- update_url = f"{SUPABASE_URL}/rest/v1/User?id=eq.{user_id}"
260
-
261
- headers_with_prefer = SUPABASE_ROLE_HEADERS.copy()
262
- headers_with_prefer["Prefer"] = "return=representation"
263
-
264
- async with session.patch(update_url, json=update_fields, headers=headers_with_prefer) as update_response:
265
- if update_response.status != 200:
266
- logger.error(f"❌ Erro ao atualizar usuário: {update_response.status} - {await update_response.text()}")
267
- raise HTTPException(status_code=update_response.status, detail="Erro ao atualizar usuário")
268
-
269
- updated_user_data = await update_response.json()
270
- raw_user = updated_user_data[0] if updated_user_data else {}
271
- updated_user = {
272
- "name": raw_user.get("name"),
273
- "avatar": raw_user.get("avatar"),
274
- "role": raw_user.get("role"),
275
- "fee": raw_user.get("fee")
276
- }
277
-
278
- logger.info(f"✅ Usuário {user_id} atualizado com sucesso por {admin_id}: {update_fields}")
279
-
280
- return {
281
- "message": "Usuário atualizado com sucesso",
282
- "user": updated_user,
283
- "updated_by": admin_id
284
- }
285
-
286
- except HTTPException as he:
287
- raise he
288
-
289
- except Exception as e:
290
- logger.error(f"❌ Erro ao atualizar usuário: {str(e)}")
291
- raise HTTPException(status_code=500, detail="Erro interno do servidor")
292
-
293
- @router.post("/admin/delete-feed")
294
- async def delete_feed(
295
- request: FeedDeleteRequest,
296
- user_token: str = Header(None, alias="User-key")
297
- ):
298
- """
299
- Deleta um feed, seus portfolios relacionados e as imagens no bucket.
300
- """
301
- try:
302
- await verify_admin_token(user_token)
303
-
304
- feed_id = request.feed_id
305
-
306
- headers = SUPABASE_ROLE_HEADERS.copy()
307
- headers["Accept"] = "application/json"
308
-
309
- async with aiohttp.ClientSession() as session:
310
- # Buscar o feed pelo ID
311
- feed_query = f"{SUPABASE_URL}/rest/v1/Feeds?select=portfolios&limit=1&id=eq.{feed_id}"
312
- async with session.get(feed_query, headers=headers) as feed_response:
313
- if feed_response.status != 200:
314
- raise HTTPException(status_code=feed_response.status, detail="Erro ao buscar feed")
315
-
316
- feed_data = await feed_response.json()
317
- if not feed_data:
318
- raise HTTPException(status_code=404, detail="Feed não encontrado")
319
-
320
- portfolio_ids = feed_data[0].get("portfolios", [])
321
- if not isinstance(portfolio_ids, list):
322
- import json
323
- portfolio_ids = json.loads(portfolio_ids) # Caso venha como string JSON
324
-
325
- # Buscar os portfolios para pegar os URLs das imagens
326
- image_urls = []
327
- if portfolio_ids:
328
- ids_str = ",".join([str(pid) for pid in portfolio_ids])
329
- portfolio_query = f"{SUPABASE_URL}/rest/v1/Portfolio?select=id,image_url&id=in.({ids_str})"
330
- async with session.get(portfolio_query, headers=headers) as portfolio_response:
331
- if portfolio_response.status == 200:
332
- portfolio_data = await portfolio_response.json()
333
- image_urls = [item["image_url"] for item in portfolio_data if "image_url" in item]
334
-
335
- # Deletar os portfolios
336
- if portfolio_ids:
337
- delete_portfolios_url = f"{SUPABASE_URL}/rest/v1/Portfolio?id=in.({','.join(map(str, portfolio_ids))})"
338
- async with session.delete(delete_portfolios_url, headers=headers) as delete_response:
339
- if delete_response.status != 204:
340
- raise HTTPException(status_code=delete_response.status, detail="Erro ao deletar portfolios")
341
-
342
- # Deletar imagens do bucket Supabase Storage
343
- async def delete_image_from_storage(image_url: str):
344
- from urllib.parse import urlparse
345
- path = urlparse(image_url).path
346
- # Extraindo bucket e key
347
- parts = path.strip("/").split("/")
348
- if len(parts) < 3:
349
- return
350
- bucket_id = parts[1]
351
- file_key = "/".join(parts[2:])
352
- delete_url = f"{SUPABASE_URL}/storage/v1/object/{bucket_id}/{file_key}"
353
- async with session.delete(delete_url, headers=headers) as delete_img_response:
354
- if delete_img_response.status not in (200, 204):
355
- logger.warning(f"❌ Falha ao deletar imagem: {file_key}")
356
-
357
- await asyncio.gather(*[delete_image_from_storage(url) for url in image_urls])
358
-
359
- # Deletar o feed
360
- delete_feed_url = f"{SUPABASE_URL}/rest/v1/Feeds?id=eq.{feed_id}"
361
- async with session.delete(delete_feed_url, headers=headers) as delete_feed_response:
362
- if delete_feed_response.status != 204:
363
- raise HTTPException(status_code=delete_feed_response.status, detail="Erro ao deletar feed")
364
-
365
- logger.info(f"✅ Feed {feed_id} e portfolios relacionados deletados com sucesso.")
366
- return {"message": f"Feed {feed_id} e portfolios deletados com sucesso."}
367
-
368
- except HTTPException as he:
369
- raise he
370
- except Exception as e:
371
- logger.error(f"❌ Erro ao deletar feed: {str(e)}")
372
- raise HTTPException(status_code=500, detail="Erro interno do servidor")
373
-
374
- @router.get("/admin/user")
375
- async def get_user_name(
376
- user_id: str = Query(..., description="ID do usuário"),
377
- user_token: str = Header(None, alias="User-key")
378
- ):
379
- """
380
- Endpoint para obter informações de um usuário específico a partir do ID,
381
- incluindo seus feeds e uma imagem de portfólio para cada feed.
382
- """
383
- try:
384
- # Verificar se o usuário tem permissão para visualizar usuários
385
- user_info = await verify_token_with_permissions(user_token, "view_users")
386
-
387
- # Buscar informações básicas do usuário
388
- user_query = f"{SUPABASE_URL}/rest/v1/User?select=name,avatar,role,fee&id=eq.{user_id}"
389
-
390
- # Buscar feeds do usuário
391
- feeds_query = f"{SUPABASE_URL}/rest/v1/Feeds?select=id,portfolios,created_at,description,urls,user_id&user_id=eq.{user_id}&order=created_at.desc"
392
-
393
- headers = SUPABASE_HEADERS.copy()
394
- headers["Accept"] = "application/json; charset=utf-8"
395
-
396
- async with aiohttp.ClientSession() as session:
397
- # Fazer as requisições em paralelo
398
- user_task = session.get(user_query, headers=headers)
399
- feeds_task = session.get(feeds_query, headers=headers)
400
-
401
- async with user_task as user_response, feeds_task as feeds_response:
402
- if user_response.status != 200 or feeds_response.status != 200:
403
- status = user_response.status if user_response.status != 200 else feeds_response.status
404
- raise HTTPException(status_code=status, detail="Erro ao consultar o Supabase")
405
-
406
- user_data = await user_response.json()
407
- feeds_data = await feeds_response.json()
408
-
409
- if not user_data:
410
- raise HTTPException(status_code=404, detail="Usuário não encontrado")
411
-
412
- # Processar feeds para buscar imagens de portfólio
413
- feeds_with_images = []
414
- for feed in feeds_data:
415
- feed_info = {
416
- "id": feed["id"],
417
- "created_at": feed["created_at"],
418
- "description": feed["description"],
419
- "urls": feed["urls"],
420
- "portfolios": feed["portfolios"]
421
- }
422
-
423
- # Verificar se há portfolios associados
424
- if feed["portfolios"] and len(feed["portfolios"]) > 0:
425
- # Pegar o primeiro portfolio do array
426
- first_portfolio_id = feed["portfolios"][0]
427
-
428
- # Buscar informações da imagem deste portfolio
429
- portfolio_query = f"{SUPABASE_URL}/rest/v1/Portfolio?select=image_url,blurhash,width,height&id=eq.{first_portfolio_id}"
430
-
431
- async with session.get(portfolio_query, headers=headers) as portfolio_response:
432
- if portfolio_response.status == 200:
433
- portfolio_data = await portfolio_response.json()
434
-
435
- if portfolio_data and len(portfolio_data) > 0:
436
- feed_info["thumbnail"] = {
437
- "image_url": portfolio_data[0]["image_url"],
438
- "blurhash": portfolio_data[0]["blurhash"],
439
- "width": portfolio_data[0]["width"],
440
- "height": portfolio_data[0]["height"]
441
- }
442
-
443
- feeds_with_images.append(feed_info)
444
-
445
- # Construir a resposta completa
446
- response = {
447
- "user": user_data[0],
448
- "feeds": feeds_with_images,
449
- "feeds_count": len(feeds_with_images)
450
- }
451
-
452
- return response
453
-
454
- except HTTPException as he:
455
- raise he
456
- except Exception as e:
457
- logger.error(f"❌ Erro ao buscar usuário e feeds: {str(e)}")
458
- raise HTTPException(status_code=500, detail="Erro interno do servidor")
 
13
  SUPABASE_URL = "https://ussxqnifefkgkaumjann.supabase.co"
14
  SUPABASE_KEY = os.getenv("SUPA_KEY")
15
  SUPABASE_ROLE_KEY = os.getenv("SUPA_SERVICE_KEY")
 
 
 
16
 
17
  if not SUPABASE_KEY or not SUPABASE_ROLE_KEY:
18
  raise ValueError("❌ SUPA_KEY ou SUPA_SERVICE_KEY não foram definidos no ambiente!")
 
195
 
196
  except Exception as e:
197
  logger.error(f"❌ Erro ao obter usuários: {str(e)}")
198
+ raise HTTPException(status_code=500, detail=str(e))