feat: migrate to Pydantic V2 and implement rate limiting middleware
- Migrate settings.py to Pydantic V2 (SettingsConfigDict, validation_alias) - Update config models to use @field_validator with @classmethod - Replace deprecated datetime.utcnow() with datetime.now(timezone.utc) - Migrate FastAPI app from @app.on_event to lifespan context manager - Implement comprehensive rate limiting middleware with: * Endpoint-specific rate limits (login: 5/min, register: 3/min) * IP-based and user-based tracking * Authenticated user multiplier (2x limits) * Bypass paths for health, docs, static, websocket endpoints * Rate limit headers in responses - Add 13 comprehensive tests for rate limiting (all passing) - Update instructions.md to mark completed tasks - Fix asyncio.create_task usage in anime_service.py All 714 tests passing. No deprecation warnings.
This commit is contained in:
21
data/config_backups/config_backup_20251023_210321.json
Normal file
21
data/config_backups/config_backup_20251023_210321.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "Aniworld",
|
||||
"data_dir": "data",
|
||||
"scheduler": {
|
||||
"enabled": true,
|
||||
"interval_minutes": 60
|
||||
},
|
||||
"logging": {
|
||||
"level": "INFO",
|
||||
"file": null,
|
||||
"max_bytes": null,
|
||||
"backup_count": 3
|
||||
},
|
||||
"backup": {
|
||||
"enabled": false,
|
||||
"path": "data/backups",
|
||||
"keep_days": 30
|
||||
},
|
||||
"other": {},
|
||||
"version": "1.0.0"
|
||||
}
|
||||
21
data/config_backups/config_backup_20251023_213153.json
Normal file
21
data/config_backups/config_backup_20251023_213153.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "Aniworld",
|
||||
"data_dir": "data",
|
||||
"scheduler": {
|
||||
"enabled": true,
|
||||
"interval_minutes": 60
|
||||
},
|
||||
"logging": {
|
||||
"level": "INFO",
|
||||
"file": null,
|
||||
"max_bytes": null,
|
||||
"backup_count": 3
|
||||
},
|
||||
"backup": {
|
||||
"enabled": false,
|
||||
"path": "data/backups",
|
||||
"keep_days": 30
|
||||
},
|
||||
"other": {},
|
||||
"version": "1.0.0"
|
||||
}
|
||||
21
data/config_backups/config_backup_20251023_213614.json
Normal file
21
data/config_backups/config_backup_20251023_213614.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "Aniworld",
|
||||
"data_dir": "data",
|
||||
"scheduler": {
|
||||
"enabled": true,
|
||||
"interval_minutes": 60
|
||||
},
|
||||
"logging": {
|
||||
"level": "INFO",
|
||||
"file": null,
|
||||
"max_bytes": null,
|
||||
"backup_count": 3
|
||||
},
|
||||
"backup": {
|
||||
"enabled": false,
|
||||
"path": "data/backups",
|
||||
"keep_days": 30
|
||||
},
|
||||
"other": {},
|
||||
"version": "1.0.0"
|
||||
}
|
||||
21
data/config_backups/config_backup_20251023_214540.json
Normal file
21
data/config_backups/config_backup_20251023_214540.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "Aniworld",
|
||||
"data_dir": "data",
|
||||
"scheduler": {
|
||||
"enabled": true,
|
||||
"interval_minutes": 60
|
||||
},
|
||||
"logging": {
|
||||
"level": "INFO",
|
||||
"file": null,
|
||||
"max_bytes": null,
|
||||
"backup_count": 3
|
||||
},
|
||||
"backup": {
|
||||
"enabled": false,
|
||||
"path": "data/backups",
|
||||
"keep_days": 30
|
||||
},
|
||||
"other": {},
|
||||
"version": "1.0.0"
|
||||
}
|
||||
21
data/config_backups/config_backup_20251023_214839.json
Normal file
21
data/config_backups/config_backup_20251023_214839.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "Aniworld",
|
||||
"data_dir": "data",
|
||||
"scheduler": {
|
||||
"enabled": true,
|
||||
"interval_minutes": 60
|
||||
},
|
||||
"logging": {
|
||||
"level": "INFO",
|
||||
"file": null,
|
||||
"max_bytes": null,
|
||||
"backup_count": 3
|
||||
},
|
||||
"backup": {
|
||||
"enabled": false,
|
||||
"path": "data/backups",
|
||||
"keep_days": 30
|
||||
},
|
||||
"other": {},
|
||||
"version": "1.0.0"
|
||||
}
|
||||
21
data/config_backups/config_backup_20251023_215649.json
Normal file
21
data/config_backups/config_backup_20251023_215649.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "Aniworld",
|
||||
"data_dir": "data",
|
||||
"scheduler": {
|
||||
"enabled": true,
|
||||
"interval_minutes": 60
|
||||
},
|
||||
"logging": {
|
||||
"level": "INFO",
|
||||
"file": null,
|
||||
"max_bytes": null,
|
||||
"backup_count": 3
|
||||
},
|
||||
"backup": {
|
||||
"enabled": false,
|
||||
"path": "data/backups",
|
||||
"keep_days": 30
|
||||
},
|
||||
"other": {},
|
||||
"version": "1.0.0"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"pending": [
|
||||
{
|
||||
"id": "8d8d2b02-7b05-479a-b94e-371b9c23819d",
|
||||
"id": "31c7cb94-fa71-40ed-aa7b-356ecb6e4332",
|
||||
"serie_id": "workflow-series",
|
||||
"serie_name": "Workflow Test Series",
|
||||
"episode": {
|
||||
@@ -11,7 +11,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "high",
|
||||
"added_at": "2025-10-23T18:56:07.879607Z",
|
||||
"added_at": "2025-10-23T19:56:51.755530Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -20,7 +20,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "088b6498-a692-4e1b-b678-51703130f6da",
|
||||
"id": "6a3d347b-0af4-4ed9-8a07-13fc7e8ac163",
|
||||
"serie_id": "series-2",
|
||||
"serie_name": "Series 2",
|
||||
"episode": {
|
||||
@@ -30,7 +30,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.379395Z",
|
||||
"added_at": "2025-10-23T19:56:51.465503Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -39,7 +39,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "69a2ab5d-71cd-4734-8268-dcd24dad5b7e",
|
||||
"id": "fe1b2f0e-e1e1-400e-8228-debdde9b4de0",
|
||||
"serie_id": "series-1",
|
||||
"serie_name": "Series 1",
|
||||
"episode": {
|
||||
@@ -49,7 +49,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.372160Z",
|
||||
"added_at": "2025-10-23T19:56:51.462159Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -58,7 +58,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "05e02166-33e1-461e-8006-d0f740f90c5b",
|
||||
"id": "7fac71fe-9902-4109-a127-31f4f7e10e8c",
|
||||
"serie_id": "series-0",
|
||||
"serie_name": "Series 0",
|
||||
"episode": {
|
||||
@@ -68,7 +68,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.364902Z",
|
||||
"added_at": "2025-10-23T19:56:51.457543Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -77,7 +77,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "66e2ae42-9e16-4f0d-993c-f6d21c830748",
|
||||
"id": "d17b1756-a563-4af0-a916-2049b4ccf5a9",
|
||||
"serie_id": "series-high",
|
||||
"serie_name": "Series High",
|
||||
"episode": {
|
||||
@@ -87,7 +87,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "high",
|
||||
"added_at": "2025-10-23T18:56:07.005089Z",
|
||||
"added_at": "2025-10-23T19:56:51.216398Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -96,7 +96,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "0489a62c-e8e3-4b5b-9ecb-217b1e753d49",
|
||||
"id": "f3b1fde7-a405-427d-ac41-8c43568aa2f3",
|
||||
"serie_id": "test-series-2",
|
||||
"serie_name": "Another Series",
|
||||
"episode": {
|
||||
@@ -106,7 +106,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "high",
|
||||
"added_at": "2025-10-23T18:56:06.959188Z",
|
||||
"added_at": "2025-10-23T19:56:51.189202Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -115,7 +115,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "c42bca2b-fa02-4ecd-a965-e2446cd0fa66",
|
||||
"id": "2cf0ef50-f4db-4c56-a3fb-9081a2e18eec",
|
||||
"serie_id": "test-series-1",
|
||||
"serie_name": "Test Anime Series",
|
||||
"episode": {
|
||||
@@ -125,7 +125,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:06.918975Z",
|
||||
"added_at": "2025-10-23T19:56:51.161055Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -134,7 +134,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "4ca92e8c-691e-4240-92ea-e3914171c432",
|
||||
"id": "aa579aab-5c97-486a-91e6-54c46231b90a",
|
||||
"serie_id": "test-series-1",
|
||||
"serie_name": "Test Anime Series",
|
||||
"episode": {
|
||||
@@ -144,7 +144,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:06.919182Z",
|
||||
"added_at": "2025-10-23T19:56:51.161286Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -153,7 +153,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "6b558e48-a736-4fc8-b2b3-50981b34841a",
|
||||
"id": "55e34b18-9825-4f70-86c4-8d590356316a",
|
||||
"serie_id": "series-normal",
|
||||
"serie_name": "Series Normal",
|
||||
"episode": {
|
||||
@@ -163,7 +163,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.008701Z",
|
||||
"added_at": "2025-10-23T19:56:51.218456Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -172,7 +172,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "3d7d639c-41f9-4351-8454-6509700fc416",
|
||||
"id": "12253698-64ea-4fc8-99c2-5ae0d4ed6895",
|
||||
"serie_id": "series-low",
|
||||
"serie_name": "Series Low",
|
||||
"episode": {
|
||||
@@ -182,7 +182,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "low",
|
||||
"added_at": "2025-10-23T18:56:07.014732Z",
|
||||
"added_at": "2025-10-23T19:56:51.220209Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -191,7 +191,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "20e951f3-3a6c-4c4b-97bd-45baadad5f69",
|
||||
"id": "ae30a3d7-3481-4b3f-a6f9-e49a5a0c8fe5",
|
||||
"serie_id": "test-series",
|
||||
"serie_name": "Test Series",
|
||||
"episode": {
|
||||
@@ -201,7 +201,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.278164Z",
|
||||
"added_at": "2025-10-23T19:56:51.405934Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -210,7 +210,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "c6e60fd2-09ad-4eba-b57b-956b6e2ad9a8",
|
||||
"id": "fae088ee-b2f1-44ea-bbb9-f5806e0994a6",
|
||||
"serie_id": "test-series",
|
||||
"serie_name": "Test Series",
|
||||
"episode": {
|
||||
@@ -220,7 +220,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.431987Z",
|
||||
"added_at": "2025-10-23T19:56:51.490971Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -229,7 +229,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "203f5769-0dcc-4a33-bed3-a0356e9089ac",
|
||||
"id": "9c85e739-6fa0-4a92-896d-8aedd57618e0",
|
||||
"serie_id": "invalid-series",
|
||||
"serie_name": "Invalid Series",
|
||||
"episode": {
|
||||
@@ -239,7 +239,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.530025Z",
|
||||
"added_at": "2025-10-23T19:56:51.546058Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -248,7 +248,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "5fef071d-0702-42df-a8ec-c286feca0eb6",
|
||||
"id": "45829428-d7d5-4242-a929-4c4b71a4bec6",
|
||||
"serie_id": "test-series",
|
||||
"serie_name": "Test Series",
|
||||
"episode": {
|
||||
@@ -258,7 +258,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.575124Z",
|
||||
"added_at": "2025-10-23T19:56:51.571105Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -267,7 +267,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "42d40c09-04d3-4403-94bb-4c8a5b23a55c",
|
||||
"id": "672bf347-2ad7-45ae-9799-d9999c1d9368",
|
||||
"serie_id": "series-1",
|
||||
"serie_name": "Series 1",
|
||||
"episode": {
|
||||
@@ -277,7 +277,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.662542Z",
|
||||
"added_at": "2025-10-23T19:56:51.614228Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -286,45 +286,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "47a9c44b-c2d4-4247-85fd-9681178679c3",
|
||||
"serie_id": "series-0",
|
||||
"serie_name": "Series 0",
|
||||
"episode": {
|
||||
"season": 1,
|
||||
"episode": 1,
|
||||
"title": null
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.665741Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
"error": null,
|
||||
"retry_count": 0,
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "8231d255-d19b-423a-a2d1-c3ced2dc485e",
|
||||
"serie_id": "series-3",
|
||||
"serie_name": "Series 3",
|
||||
"episode": {
|
||||
"season": 1,
|
||||
"episode": 1,
|
||||
"title": null
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.668864Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
"error": null,
|
||||
"retry_count": 0,
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "225e0667-0fa7-4f00-a3c9-8dee5a6386b6",
|
||||
"id": "e95a02fd-5cbf-4f0f-8a08-9ac4bcdf6c15",
|
||||
"serie_id": "series-2",
|
||||
"serie_name": "Series 2",
|
||||
"episode": {
|
||||
@@ -334,7 +296,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.670113Z",
|
||||
"added_at": "2025-10-23T19:56:51.615864Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -343,7 +305,26 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "3f1a34d0-7d0c-493a-9da1-366f57216f98",
|
||||
"id": "c7127db3-c62e-4af3-ae81-04f521320519",
|
||||
"serie_id": "series-0",
|
||||
"serie_name": "Series 0",
|
||||
"episode": {
|
||||
"season": 1,
|
||||
"episode": 1,
|
||||
"title": null
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T19:56:51.616544Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
"error": null,
|
||||
"retry_count": 0,
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "d01e8e1f-6522-49cd-bc45-f7f28ca76228",
|
||||
"serie_id": "series-4",
|
||||
"serie_name": "Series 4",
|
||||
"episode": {
|
||||
@@ -353,7 +334,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.671251Z",
|
||||
"added_at": "2025-10-23T19:56:51.617214Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -362,7 +343,26 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "b55f33c1-1e2a-4b01-9409-62c711f26cb0",
|
||||
"id": "ee067702-e382-4758-ae83-173a2bc2a8a3",
|
||||
"serie_id": "series-3",
|
||||
"serie_name": "Series 3",
|
||||
"episode": {
|
||||
"season": 1,
|
||||
"episode": 1,
|
||||
"title": null
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T19:56:51.617883Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
"error": null,
|
||||
"retry_count": 0,
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "3159eadc-8298-4418-ac78-a61d2646f84c",
|
||||
"serie_id": "persistent-series",
|
||||
"serie_name": "Persistent Series",
|
||||
"episode": {
|
||||
@@ -372,7 +372,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.768987Z",
|
||||
"added_at": "2025-10-23T19:56:51.680519Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -381,7 +381,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "650b02fd-e6f4-4bc1-b8dd-e2591ec2fd7b",
|
||||
"id": "4e7a25db-819f-4782-bd59-01d443497131",
|
||||
"serie_id": "ws-series",
|
||||
"serie_name": "WebSocket Series",
|
||||
"episode": {
|
||||
@@ -391,7 +391,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:07.844702Z",
|
||||
"added_at": "2025-10-23T19:56:51.731180Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -400,7 +400,7 @@
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "126329c1-0944-41bf-9e43-c1e543193ff2",
|
||||
"id": "2f6b4857-6cc9-43ca-bb21-b55e8e4931f8",
|
||||
"serie_id": "pause-test",
|
||||
"serie_name": "Pause Test Series",
|
||||
"episode": {
|
||||
@@ -410,7 +410,7 @@
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-10-23T18:56:08.030854Z",
|
||||
"added_at": "2025-10-23T19:56:51.890630Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
@@ -421,5 +421,5 @@
|
||||
],
|
||||
"active": [],
|
||||
"failed": [],
|
||||
"timestamp": "2025-10-23T18:56:08.031367+00:00"
|
||||
"timestamp": "2025-10-23T19:56:51.891251+00:00"
|
||||
}
|
||||
Reference in New Issue
Block a user