habulaj commited on
Commit
aa5273d
·
verified ·
1 Parent(s): 5ceb41d

Update routes/notifications.py

Browse files
Files changed (1) hide show
  1. routes/notifications.py +55 -16
routes/notifications.py CHANGED
@@ -4,6 +4,7 @@ from fastapi import APIRouter, HTTPException, Header
4
  from pydantic import BaseModel
5
  from google.oauth2 import service_account
6
  from google.auth.transport.requests import Request
 
7
 
8
  router = APIRouter()
9
 
@@ -25,14 +26,12 @@ SUPABASE_HEADERS = {
25
  SERVICE_ACCOUNT_FILE = './closetcoach-2d50b-firebase-adminsdk-fbsvc-7fcccbacb1.json'
26
  FCM_PROJECT_ID = "closetcoach-2d50b"
27
 
28
- # Modelo da requisição
29
  class SimpleNotification(BaseModel):
30
- target: str # "all" ou user_id
31
  title: str
32
  content: str
33
  image_url: str = ""
34
 
35
- # Função para obter token do Firebase
36
  def get_fcm_access_token():
37
  credentials = service_account.Credentials.from_service_account_file(
38
  SERVICE_ACCOUNT_FILE
@@ -43,7 +42,6 @@ def get_fcm_access_token():
43
  scoped.refresh(Request())
44
  return scoped.token
45
 
46
- # Verifica o token de usuário no Supabase
47
  async def get_user_id_from_token(user_token: str) -> str:
48
  url = f"{SUPABASE_URL}/auth/v1/user"
49
  headers = {
@@ -59,27 +57,50 @@ async def get_user_id_from_token(user_token: str) -> str:
59
  data = await resp.json()
60
  return data.get("id")
61
 
62
- # Busca informações de um usuário pelo ID
63
- async def get_user(user_id: str):
64
- url = f"{SUPABASE_URL}/rest/v1/User?id=eq.{user_id}&select=id,token_fcm,manage_notifications"
65
  async with aiohttp.ClientSession() as session:
66
  async with session.get(url, headers=SUPABASE_HEADERS) as resp:
67
  if resp.status != 200:
68
- raise HTTPException(status_code=resp.status, detail="Failed to fetch user info")
69
  data = await resp.json()
70
  return data[0] if data else None
71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  @router.post("/send-global-notification")
73
  async def send_global_notification(
74
  payload: SimpleNotification,
75
  user_token: str = Header(..., alias="User-key")
76
  ):
77
- # Verifica o ID do usuário autenticado
78
  sender_id = await get_user_id_from_token(user_token)
79
- sender = await get_user(sender_id)
80
 
81
  if not sender or not sender.get("manage_notifications"):
82
- raise HTTPException(status_code=403, detail="Not authorized to send notifications")
83
 
84
  message = {
85
  "notification": {
@@ -88,17 +109,25 @@ async def send_global_notification(
88
  }
89
  }
90
 
 
 
91
  if payload.image_url:
92
  message["notification"]["image"] = payload.image_url
93
 
94
- if payload.target == "all":
95
  message["topic"] = "all"
96
  else:
97
- target_user = await get_user(payload.target)
98
- if not target_user or not target_user.get("token_fcm"):
99
- raise HTTPException(status_code=404, detail="Target user or FCM token not found")
 
 
 
 
100
  message["token"] = target_user["token_fcm"]
 
101
 
 
102
  access_token = get_fcm_access_token()
103
  headers = {
104
  "Authorization": f"Bearer {access_token}",
@@ -111,4 +140,14 @@ async def send_global_notification(
111
  response_text = await resp.text()
112
  if resp.status != 200:
113
  raise HTTPException(status_code=resp.status, detail=f"FCM error: {response_text}")
114
- return {"detail": "Notification sent successfully"}
 
 
 
 
 
 
 
 
 
 
 
4
  from pydantic import BaseModel
5
  from google.oauth2 import service_account
6
  from google.auth.transport.requests import Request
7
+ from datetime import datetime
8
 
9
  router = APIRouter()
10
 
 
26
  SERVICE_ACCOUNT_FILE = './closetcoach-2d50b-firebase-adminsdk-fbsvc-7fcccbacb1.json'
27
  FCM_PROJECT_ID = "closetcoach-2d50b"
28
 
 
29
  class SimpleNotification(BaseModel):
30
+ target: str # email or "all"
31
  title: str
32
  content: str
33
  image_url: str = ""
34
 
 
35
  def get_fcm_access_token():
36
  credentials = service_account.Credentials.from_service_account_file(
37
  SERVICE_ACCOUNT_FILE
 
42
  scoped.refresh(Request())
43
  return scoped.token
44
 
 
45
  async def get_user_id_from_token(user_token: str) -> str:
46
  url = f"{SUPABASE_URL}/auth/v1/user"
47
  headers = {
 
57
  data = await resp.json()
58
  return data.get("id")
59
 
60
+ async def get_user_by_email(email: str):
61
+ url = f"{SUPABASE_URL}/rest/v1/User?email=eq.{email}&select=id,token_fcm"
 
62
  async with aiohttp.ClientSession() as session:
63
  async with session.get(url, headers=SUPABASE_HEADERS) as resp:
64
  if resp.status != 200:
65
+ raise HTTPException(status_code=500, detail="Failed to fetch target user from database")
66
  data = await resp.json()
67
  return data[0] if data else None
68
 
69
+ async def get_user_by_id(user_id: str):
70
+ url = f"{SUPABASE_URL}/rest/v1/User?id=eq.{user_id}&select=id,manage_notifications"
71
+ async with aiohttp.ClientSession() as session:
72
+ async with session.get(url, headers=SUPABASE_HEADERS) as resp:
73
+ if resp.status != 200:
74
+ raise HTTPException(status_code=500, detail="Failed to fetch sender user from database")
75
+ data = await resp.json()
76
+ return data[0] if data else None
77
+
78
+ async def log_notification(send_by: str, title: str, content: str, target_id: str | None, image_url: str):
79
+ payload = {
80
+ "send_by": send_by,
81
+ "title": title,
82
+ "content": content,
83
+ "target": target_id,
84
+ "image_url": image_url or None,
85
+ "created_at": datetime.utcnow().isoformat()
86
+ }
87
+ url = f"{SUPABASE_URL}/rest/v1/fcm_notifications"
88
+ async with aiohttp.ClientSession() as session:
89
+ async with session.post(url, headers=SUPABASE_HEADERS, json=payload) as resp:
90
+ if resp.status not in (200, 201):
91
+ detail = await resp.text()
92
+ raise HTTPException(status_code=500, detail=f"Failed to log notification: {detail}")
93
+
94
  @router.post("/send-global-notification")
95
  async def send_global_notification(
96
  payload: SimpleNotification,
97
  user_token: str = Header(..., alias="User-key")
98
  ):
 
99
  sender_id = await get_user_id_from_token(user_token)
100
+ sender = await get_user_by_id(sender_id)
101
 
102
  if not sender or not sender.get("manage_notifications"):
103
+ raise HTTPException(status_code=403, detail="You are not authorized to send notifications.")
104
 
105
  message = {
106
  "notification": {
 
109
  }
110
  }
111
 
112
+ target_user_id = None
113
+
114
  if payload.image_url:
115
  message["notification"]["image"] = payload.image_url
116
 
117
+ if payload.target.lower() == "all":
118
  message["topic"] = "all"
119
  else:
120
+ target_user = await get_user_by_email(payload.target.lower().strip())
121
+
122
+ if not target_user:
123
+ raise HTTPException(status_code=404, detail="The provided email does not correspond to any user.")
124
+ if not target_user.get("token_fcm"):
125
+ raise HTTPException(status_code=400, detail="The target user does not have a registered FCM token.")
126
+
127
  message["token"] = target_user["token_fcm"]
128
+ target_user_id = target_user["id"]
129
 
130
+ # Envia para o Firebase
131
  access_token = get_fcm_access_token()
132
  headers = {
133
  "Authorization": f"Bearer {access_token}",
 
140
  response_text = await resp.text()
141
  if resp.status != 200:
142
  raise HTTPException(status_code=resp.status, detail=f"FCM error: {response_text}")
143
+
144
+ # Salvar notificação no banco
145
+ await log_notification(
146
+ send_by=sender_id,
147
+ title=payload.title,
148
+ content=payload.content,
149
+ target_id=target_user_id,
150
+ image_url=payload.image_url
151
+ )
152
+
153
+ return {"detail": "Notification sent and logged successfully."}