jebin2 commited on
Commit
913ed88
·
1 Parent(s): 24b2623

Fix encryption: support direct RSA-OAEP and hybrid RSA+AES-GCM modes

Browse files
Files changed (3) hide show
  1. app.py +45 -1
  2. models.py +2 -0
  3. requirements.txt +1 -0
app.py CHANGED
@@ -6,8 +6,9 @@ decrypting it, and storing in SQLite database.
6
  """
7
  import logging
8
  from contextlib import asynccontextmanager
9
- from typing import Optional
10
 
 
11
  from fastapi import FastAPI, Query, Request, Depends, HTTPException, status
12
  from fastapi.middleware.cors import CORSMiddleware
13
  from fastapi.responses import JSONResponse, HTMLResponse
@@ -29,6 +30,40 @@ logger = logging.getLogger(__name__)
29
  # User ID length constant
30
  USER_ID_LENGTH = 20
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  @asynccontextmanager
34
  async def lifespan(app: FastAPI):
@@ -123,6 +158,8 @@ async def get_data(
123
  "user_id": item.user_id,
124
  "refer_url": item.refer_url,
125
  "ip_address": item.ip_address,
 
 
126
  "json_data": item.json_data,
127
  "created_at": item.created_at.isoformat() if item.created_at else None
128
  }
@@ -202,6 +239,9 @@ async def blink(
202
  # Fall back to direct client IP
203
  ip_address = request.client.host if request.client else None
204
 
 
 
 
205
  # Store each decrypted result as separate records
206
  records_created = 0
207
  for json_data in decrypted_results:
@@ -209,6 +249,8 @@ async def blink(
209
  user_id=user_id,
210
  refer_url=refer_url,
211
  ip_address=ip_address,
 
 
212
  json_data=json_data
213
  )
214
  db.add(blink_record)
@@ -220,6 +262,8 @@ async def blink(
220
  user_id=user_id,
221
  refer_url=refer_url,
222
  ip_address=ip_address,
 
 
223
  json_data={"encrypted_length": len(encrypted_data)}
224
  )
225
  db.add(blink_record)
 
6
  """
7
  import logging
8
  from contextlib import asynccontextmanager
9
+ from typing import Optional, Tuple
10
 
11
+ import httpx
12
  from fastapi import FastAPI, Query, Request, Depends, HTTPException, status
13
  from fastapi.middleware.cors import CORSMiddleware
14
  from fastapi.responses import JSONResponse, HTMLResponse
 
30
  # User ID length constant
31
  USER_ID_LENGTH = 20
32
 
33
+ # Geolocation API settings
34
+ GEOLOCATION_API_URL = "http://ip-api.com/json/{ip}?fields=status,country,regionName"
35
+ GEOLOCATION_TIMEOUT = 2.0 # seconds
36
+
37
+
38
+ async def get_geolocation(ip_address: str) -> Tuple[Optional[str], Optional[str]]:
39
+ """
40
+ Get country and region for an IP address using ip-api.com.
41
+
42
+ Args:
43
+ ip_address: IPv4 or IPv6 address
44
+
45
+ Returns:
46
+ Tuple of (country, region) or (None, None) if lookup fails
47
+ """
48
+ if not ip_address:
49
+ return None, None
50
+
51
+ # Skip geolocation for localhost/private IPs
52
+ if ip_address in ("127.0.0.1", "::1", "localhost") or ip_address.startswith(("192.168.", "10.", "172.")):
53
+ return None, None
54
+
55
+ try:
56
+ async with httpx.AsyncClient(timeout=GEOLOCATION_TIMEOUT) as client:
57
+ response = await client.get(GEOLOCATION_API_URL.format(ip=ip_address))
58
+ if response.status_code == 200:
59
+ data = response.json()
60
+ if data.get("status") == "success":
61
+ return data.get("country"), data.get("regionName")
62
+ except Exception as e:
63
+ logger.warning(f"Geolocation lookup failed for {ip_address}: {e}")
64
+
65
+ return None, None
66
+
67
 
68
  @asynccontextmanager
69
  async def lifespan(app: FastAPI):
 
158
  "user_id": item.user_id,
159
  "refer_url": item.refer_url,
160
  "ip_address": item.ip_address,
161
+ "country": item.country,
162
+ "region": item.region,
163
  "json_data": item.json_data,
164
  "created_at": item.created_at.isoformat() if item.created_at else None
165
  }
 
239
  # Fall back to direct client IP
240
  ip_address = request.client.host if request.client else None
241
 
242
+ # Get geolocation from IP address
243
+ country, region = await get_geolocation(ip_address)
244
+
245
  # Store each decrypted result as separate records
246
  records_created = 0
247
  for json_data in decrypted_results:
 
249
  user_id=user_id,
250
  refer_url=refer_url,
251
  ip_address=ip_address,
252
+ country=country,
253
+ region=region,
254
  json_data=json_data
255
  )
256
  db.add(blink_record)
 
262
  user_id=user_id,
263
  refer_url=refer_url,
264
  ip_address=ip_address,
265
+ country=country,
266
+ region=region,
267
  json_data={"encrypted_length": len(encrypted_data)}
268
  )
269
  db.add(blink_record)
models.py CHANGED
@@ -23,6 +23,8 @@ class BlinkData(Base):
23
  user_id = Column(String(20), index=True, nullable=False)
24
  refer_url = Column(Text, nullable=True)
25
  ip_address = Column(String(45), nullable=True) # IPv6 can be up to 45 chars
 
 
26
  json_data = Column(JSON, nullable=True)
27
  created_at = Column(DateTime(timezone=True), server_default=func.now())
28
 
 
23
  user_id = Column(String(20), index=True, nullable=False)
24
  refer_url = Column(Text, nullable=True)
25
  ip_address = Column(String(45), nullable=True) # IPv6 can be up to 45 chars
26
+ country = Column(String(100), nullable=True) # Country from IP geolocation
27
+ region = Column(String(100), nullable=True) # Region/State from IP geolocation
28
  json_data = Column(JSON, nullable=True)
29
  created_at = Column(DateTime(timezone=True), server_default=func.now())
30
 
requirements.txt CHANGED
@@ -5,3 +5,4 @@ sqlalchemy>=2.0.0
5
  aiosqlite>=0.19.0
6
  cryptography>=41.0.0
7
  pydantic>=2.0.0
 
 
5
  aiosqlite>=0.19.0
6
  cryptography>=41.0.0
7
  pydantic>=2.0.0
8
+ httpx>=0.25.0