Parth Kansal commited on
Commit
35dc52d
Β·
1 Parent(s): f17ed53
app/db/__pycache__/client.cpython-314.pyc CHANGED
Binary files a/app/db/__pycache__/client.cpython-314.pyc and b/app/db/__pycache__/client.cpython-314.pyc differ
 
app/db/client.py CHANGED
@@ -1,6 +1,17 @@
 
 
1
  from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase
 
2
  from ..core.config import settings
3
 
 
 
 
 
 
 
 
 
4
  _client: AsyncIOMotorClient = None
5
  _db: AsyncIOMotorDatabase = None
6
 
@@ -8,7 +19,13 @@ _db: AsyncIOMotorDatabase = None
8
  async def connect():
9
  global _client, _db
10
  _client = AsyncIOMotorClient(settings.MONGO_URL)
11
- _db = _client.get_default_database()
 
 
 
 
 
 
12
  await _db.alerts.create_index([("location", "2dsphere")])
13
  await _db.users.create_index("email", unique=True)
14
 
 
1
+ from pymongo.errors import ConfigurationError
2
+
3
  from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase
4
+
5
  from ..core.config import settings
6
 
7
+ # Default DB name used when the connection string doesn't carry one.
8
+ # Atlas users routinely paste a URL of the form
9
+ # `mongodb+srv://.../?retryWrites=true&w=majority` (no `/dbname` segment),
10
+ # which makes `get_default_database()` raise. Falling back to this name
11
+ # matches what the local-dev URL uses (`mongodb://localhost:27017/neighbouraid`)
12
+ # and keeps deploys forgiving.
13
+ _DEFAULT_DB_NAME = "neighbouraid"
14
+
15
  _client: AsyncIOMotorClient = None
16
  _db: AsyncIOMotorDatabase = None
17
 
 
19
  async def connect():
20
  global _client, _db
21
  _client = AsyncIOMotorClient(settings.MONGO_URL)
22
+ try:
23
+ _db = _client.get_default_database()
24
+ except ConfigurationError:
25
+ # Atlas SRV strings often omit the database segment. Picking up
26
+ # `neighbouraid` here keeps the user from having to learn the
27
+ # exact connection-string syntax just to deploy.
28
+ _db = _client[_DEFAULT_DB_NAME]
29
  await _db.alerts.create_index([("location", "2dsphere")])
30
  await _db.users.create_index("email", unique=True)
31
 
tests/__pycache__/test_security.cpython-314-pytest-9.0.3.pyc CHANGED
Binary files a/tests/__pycache__/test_security.cpython-314-pytest-9.0.3.pyc and b/tests/__pycache__/test_security.cpython-314-pytest-9.0.3.pyc differ
 
tests/test_security.py CHANGED
@@ -1,18 +1,20 @@
1
- """Tests for the security hardening layer.
2
 
3
  Covers:
4
  - Security-headers middleware applies on every response
5
  - Strengthened password rules (length, letter+digit complexity)
6
  - Per-IP rate limit on login + register + write endpoints
7
  - python-jose deprecation warning is silenced via pytest config
 
8
  """
9
 
10
  from __future__ import annotations
11
 
12
- from unittest.mock import AsyncMock, MagicMock
13
 
14
  import pytest
15
  from bson import ObjectId
 
16
 
17
 
18
  # ──────────────────────────────────────────────────────────────────────
@@ -190,3 +192,43 @@ async def test_rate_limiter_dependency_returns_429_message():
190
  await dep(_FakeReq())
191
  assert exc.value.status_code == 429
192
  assert "unit" in exc.value.detail
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Tests for the security hardening + reliability layer.
2
 
3
  Covers:
4
  - Security-headers middleware applies on every response
5
  - Strengthened password rules (length, letter+digit complexity)
6
  - Per-IP rate limit on login + register + write endpoints
7
  - python-jose deprecation warning is silenced via pytest config
8
+ - DB connect fallback when the Atlas URL omits the database segment
9
  """
10
 
11
  from __future__ import annotations
12
 
13
+ from unittest.mock import AsyncMock, MagicMock, patch
14
 
15
  import pytest
16
  from bson import ObjectId
17
+ from pymongo.errors import ConfigurationError
18
 
19
 
20
  # ──────────────────────────────────────────────────────────────────────
 
192
  await dep(_FakeReq())
193
  assert exc.value.status_code == 429
194
  assert "unit" in exc.value.detail
195
+
196
+
197
+ # ──────────────────────────────────────────────────────────────────────
198
+ # DB connect fallback β€” the most common HF Spaces deploy crash
199
+ # ──────────────────────────────────────────────────────────────────────
200
+
201
+
202
+ @pytest.mark.asyncio
203
+ async def test_connect_falls_back_to_default_db_name():
204
+ """Atlas users routinely paste a connection string with no /dbname
205
+ segment, which makes `get_default_database()` raise. Our connect()
206
+ should fall back to the `neighbouraid` database silently."""
207
+ from app.db import client as db_client
208
+
209
+ # Build a fake Motor client that:
210
+ # - raises ConfigurationError on get_default_database (the bug shape)
211
+ # - returns a mock DB when subscripted by name (the fallback path)
212
+ fake_db = MagicMock()
213
+ fake_db.alerts.create_index = AsyncMock()
214
+ fake_db.users.create_index = AsyncMock()
215
+
216
+ fake_client = MagicMock()
217
+ fake_client.get_default_database = MagicMock(
218
+ side_effect=ConfigurationError("no default db")
219
+ )
220
+ fake_client.__getitem__ = MagicMock(return_value=fake_db)
221
+
222
+ with patch.object(
223
+ db_client, "AsyncIOMotorClient", return_value=fake_client
224
+ ):
225
+ # Cache the original to restore afterwards so we don't pollute
226
+ # other tests (the global fixture swaps _db too).
227
+ original = db_client._db
228
+ try:
229
+ await db_client.connect()
230
+ # The fallback should have indexed `neighbouraid`
231
+ fake_client.__getitem__.assert_called_with("neighbouraid")
232
+ assert db_client._db is fake_db
233
+ finally:
234
+ db_client._db = original