From f6351805ba200e0c18dff5ac4b76da714bc3364d Mon Sep 17 00:00:00 2001 From: gabdevele Date: Sat, 11 Apr 2026 23:58:05 +0200 Subject: [PATCH 1/2] feat: implement MongoDB configuration and database access functionality --- pyproject.toml | 2 ++ src/core/config.py | 10 +++++++++ src/db/mongodb.py | 22 ++++++++++++++++++++ uv.lock | 51 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/core/config.py create mode 100644 src/db/mongodb.py diff --git a/pyproject.toml b/pyproject.toml index 267a1c4..a02e7c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,8 @@ description = "Add your description here" requires-python = ">=3.14" dependencies = [ "fastapi[standard]>=0.135.3", + "motor>=3.7.1", + "pydantic-settings>=2.13.1", ] [tool.ruff.lint] diff --git a/src/core/config.py b/src/core/config.py new file mode 100644 index 0000000..09554b2 --- /dev/null +++ b/src/core/config.py @@ -0,0 +1,10 @@ +from pydantic_settings import BaseSettings, SettingsConfigDict + +class Settings(BaseSettings): + model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="ignore") + + MONGODB_URI: str + MONGODB_DB_NAME: str + + +settings = Settings() \ No newline at end of file diff --git a/src/db/mongodb.py b/src/db/mongodb.py new file mode 100644 index 0000000..2caca5b --- /dev/null +++ b/src/db/mongodb.py @@ -0,0 +1,22 @@ +from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase +from core.config import settings + +class _MongoDB: + client: AsyncIOMotorClient | None = None + + def get_database(self) -> AsyncIOMotorDatabase: + if self.client is None: + raise RuntimeError("MongoDB client has not been initialized") + return self.client[settings.MONGODB_DB_NAME] + +mongodb = _MongoDB() + +async def get_database() -> AsyncIOMotorDatabase: + return mongodb.get_database() + + +async def ensure_mongodb_available() -> None: + client = mongodb.client + if client is None: + raise RuntimeError("MongoDB client has not been initialized") + await client.admin.command("ping") diff --git a/uv.lock b/uv.lock index 6f4a661..03d840f 100644 --- a/uv.lock +++ b/uv.lock @@ -315,6 +315,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] +[[package]] +name = "motor" +version = "3.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pymongo" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/93/ae/96b88362d6a84cb372f7977750ac2a8aed7b2053eed260615df08d5c84f4/motor-3.7.1.tar.gz", hash = "sha256:27b4d46625c87928f331a6ca9d7c51c2f518ba0e270939d395bc1ddc89d64526", size = 280997, upload-time = "2025-05-14T18:56:33.653Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/01/9a/35e053d4f442addf751ed20e0e922476508ee580786546d699b0567c4c67/motor-3.7.1-py3-none-any.whl", hash = "sha256:8a63b9049e38eeeb56b4fdd57c3312a6d1f25d01db717fe7d82222393c410298", size = 74996, upload-time = "2025-05-14T18:56:31.665Z" }, +] + [[package]] name = "pydantic" version = "2.12.5" @@ -410,6 +422,37 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, ] +[[package]] +name = "pymongo" +version = "4.16.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dnspython" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/65/9c/a4895c4b785fc9865a84a56e14b5bd21ca75aadc3dab79c14187cdca189b/pymongo-4.16.0.tar.gz", hash = "sha256:8ba8405065f6e258a6f872fe62d797a28f383a12178c7153c01ed04e845c600c", size = 2495323, upload-time = "2026-01-07T18:05:48.107Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/9e/4d343f8d0512002fce17915a89477b9f916bda1205729e042d8f23acf194/pymongo-4.16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:8a254d49a9ffe9d7f888e3c677eed3729b14ce85abb08cd74732cead6ccc3c66", size = 1026634, upload-time = "2026-01-07T18:04:54.359Z" }, + { url = "https://files.pythonhosted.org/packages/c3/e3/341f88c5535df40c0450fda915f582757bb7d988cdfc92990a5e27c4c324/pymongo-4.16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a1bf44e13cf2d44d2ea2e928a8140d5d667304abe1a61c4d55b4906f389fbe64", size = 1026252, upload-time = "2026-01-07T18:04:56.642Z" }, + { url = "https://files.pythonhosted.org/packages/af/64/9471b22eb98f0a2ca0b8e09393de048502111b2b5b14ab1bd9e39708aab5/pymongo-4.16.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f1c5f1f818b669875d191323a48912d3fcd2e4906410e8297bb09ac50c4d5ccc", size = 2207399, upload-time = "2026-01-07T18:04:58.255Z" }, + { url = "https://files.pythonhosted.org/packages/87/ac/47c4d50b25a02f21764f140295a2efaa583ee7f17992a5e5fa542b3a690f/pymongo-4.16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77cfd37a43a53b02b7bd930457c7994c924ad8bbe8dff91817904bcbf291b371", size = 2260595, upload-time = "2026-01-07T18:04:59.788Z" }, + { url = "https://files.pythonhosted.org/packages/ee/1b/0ce1ce9dd036417646b2fe6f63b58127acff3cf96eeb630c34ec9cd675ff/pymongo-4.16.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:36ef2fee50eee669587d742fb456e349634b4fcf8926208766078b089054b24b", size = 2366958, upload-time = "2026-01-07T18:05:01.942Z" }, + { url = "https://files.pythonhosted.org/packages/3e/3c/a5a17c0d413aa9d6c17bc35c2b472e9e79cda8068ba8e93433b5f43028e9/pymongo-4.16.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55f8d5a6fe2fa0b823674db2293f92d74cd5f970bc0360f409a1fc21003862d3", size = 2346081, upload-time = "2026-01-07T18:05:03.576Z" }, + { url = "https://files.pythonhosted.org/packages/65/19/f815533d1a88fb8a3b6c6e895bb085ffdae68ccb1e6ed7102202a307f8e2/pymongo-4.16.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9caacac0dd105e2555521002e2d17afc08665187017b466b5753e84c016628e6", size = 2246053, upload-time = "2026-01-07T18:05:05.459Z" }, + { url = "https://files.pythonhosted.org/packages/c6/88/4be3ec78828dc64b212c123114bd6ae8db5b7676085a7b43cc75d0131bd2/pymongo-4.16.0-cp314-cp314-win32.whl", hash = "sha256:c789236366525c3ee3cd6e4e450a9ff629a7d1f4d88b8e18a0aea0615fd7ecf8", size = 989461, upload-time = "2026-01-07T18:05:07.018Z" }, + { url = "https://files.pythonhosted.org/packages/af/5a/ab8d5af76421b34db483c9c8ebc3a2199fb80ae63dc7e18f4cf1df46306a/pymongo-4.16.0-cp314-cp314-win_amd64.whl", hash = "sha256:2b0714d7764efb29bf9d3c51c964aed7c4c7237b341f9346f15ceaf8321fdb35", size = 1017803, upload-time = "2026-01-07T18:05:08.499Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f4/98d68020728ac6423cf02d17cfd8226bf6cce5690b163d30d3f705e8297e/pymongo-4.16.0-cp314-cp314-win_arm64.whl", hash = "sha256:12762e7cc0f8374a8cae3b9f9ed8dabb5d438c7b33329232dd9b7de783454033", size = 997184, upload-time = "2026-01-07T18:05:09.944Z" }, + { url = "https://files.pythonhosted.org/packages/50/00/dc3a271daf06401825b9c1f4f76f018182c7738281ea54b9762aea0560c1/pymongo-4.16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1c01e8a7cd0ea66baf64a118005535ab5bf9f9eb63a1b50ac3935dccf9a54abe", size = 1083303, upload-time = "2026-01-07T18:05:11.702Z" }, + { url = "https://files.pythonhosted.org/packages/b8/4b/b5375ee21d12eababe46215011ebc63801c0d2c5ffdf203849d0d79f9852/pymongo-4.16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4c4872299ebe315a79f7f922051061634a64fda95b6b17677ba57ef00b2ba2a4", size = 1083233, upload-time = "2026-01-07T18:05:13.182Z" }, + { url = "https://files.pythonhosted.org/packages/ee/e3/52efa3ca900622c7dcb56c5e70f15c906816d98905c22d2ee1f84d9a7b60/pymongo-4.16.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:78037d02389745e247fe5ab0bcad5d1ab30726eaac3ad79219c7d6bbb07eec53", size = 2527438, upload-time = "2026-01-07T18:05:14.981Z" }, + { url = "https://files.pythonhosted.org/packages/cb/96/43b1be151c734e7766c725444bcbfa1de6b60cc66bfb406203746839dd25/pymongo-4.16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c126fb72be2518395cc0465d4bae03125119136462e1945aea19840e45d89cfc", size = 2600399, upload-time = "2026-01-07T18:05:16.794Z" }, + { url = "https://files.pythonhosted.org/packages/e7/62/fa64a5045dfe3a1cd9217232c848256e7bc0136cffb7da4735c5e0d30e40/pymongo-4.16.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f3867dc225d9423c245a51eaac2cfcd53dde8e0a8d8090bb6aed6e31bd6c2d4f", size = 2720960, upload-time = "2026-01-07T18:05:18.498Z" }, + { url = "https://files.pythonhosted.org/packages/54/7b/01577eb97e605502821273a5bc16ce0fb0be5c978fe03acdbff471471202/pymongo-4.16.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f25001a955073b80510c0c3db0e043dbbc36904fd69e511c74e3d8640b8a5111", size = 2699344, upload-time = "2026-01-07T18:05:20.073Z" }, + { url = "https://files.pythonhosted.org/packages/55/68/6ef6372d516f703479c3b6cbbc45a5afd307173b1cbaccd724e23919bb1a/pymongo-4.16.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d9885aad05f82fd7ea0c9ca505d60939746b39263fa273d0125170da8f59098", size = 2577133, upload-time = "2026-01-07T18:05:22.052Z" }, + { url = "https://files.pythonhosted.org/packages/15/c7/b5337093bb01da852f945802328665f85f8109dbe91d81ea2afe5ff059b9/pymongo-4.16.0-cp314-cp314t-win32.whl", hash = "sha256:948152b30eddeae8355495f9943a3bf66b708295c0b9b6f467de1c620f215487", size = 1040560, upload-time = "2026-01-07T18:05:23.888Z" }, + { url = "https://files.pythonhosted.org/packages/96/8c/5b448cd1b103f3889d5713dda37304c81020ff88e38a826e8a75ddff4610/pymongo-4.16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f6e42c1bc985d9beee884780ae6048790eb4cd565c46251932906bdb1630034a", size = 1075081, upload-time = "2026-01-07T18:05:26.874Z" }, + { url = "https://files.pythonhosted.org/packages/32/cd/ddc794cdc8500f6f28c119c624252fb6dfb19481c6d7ed150f13cf468a6d/pymongo-4.16.0-cp314-cp314t-win_arm64.whl", hash = "sha256:6b2a20edb5452ac8daa395890eeb076c570790dfce6b7a44d788af74c2f8cf96", size = 1047725, upload-time = "2026-01-07T18:05:28.47Z" }, +] + [[package]] name = "python-dotenv" version = "1.2.2" @@ -559,10 +602,16 @@ version = "0.1.0" source = { virtual = "." } dependencies = [ { name = "fastapi", extra = ["standard"] }, + { name = "motor" }, + { name = "pydantic-settings" }, ] [package.metadata] -requires-dist = [{ name = "fastapi", extras = ["standard"], specifier = ">=0.135.3" }] +requires-dist = [ + { name = "fastapi", extras = ["standard"], specifier = ">=0.135.3" }, + { name = "motor", specifier = ">=3.7.1" }, + { name = "pydantic-settings", specifier = ">=2.13.1" }, +] [[package]] name = "typer" From b5c854a2437049bb8cc6d25ef31d48af197d96eb Mon Sep 17 00:00:00 2001 From: gabdevele Date: Sun, 12 Apr 2026 00:16:46 +0200 Subject: [PATCH 2/2] feat: add Redis support and update service/proxy models --- pyproject.toml | 1 + src/core/config.py | 1 + src/{db => core}/mongodb.py | 2 +- src/core/redis.py | 21 +++++++++++++++++++++ src/models/proxy.py | 6 ++++++ src/models/service.py | 6 ++++++ uv.lock | 11 +++++++++++ 7 files changed, 47 insertions(+), 1 deletion(-) rename src/{db => core}/mongodb.py (94%) create mode 100644 src/core/redis.py create mode 100644 src/models/proxy.py create mode 100644 src/models/service.py diff --git a/pyproject.toml b/pyproject.toml index a02e7c0..85203a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,7 @@ dependencies = [ "fastapi[standard]>=0.135.3", "motor>=3.7.1", "pydantic-settings>=2.13.1", + "redis>=7.4.0", ] [tool.ruff.lint] diff --git a/src/core/config.py b/src/core/config.py index 09554b2..23be48d 100644 --- a/src/core/config.py +++ b/src/core/config.py @@ -5,6 +5,7 @@ class Settings(BaseSettings): MONGODB_URI: str MONGODB_DB_NAME: str + REDIS_URL: str settings = Settings() \ No newline at end of file diff --git a/src/db/mongodb.py b/src/core/mongodb.py similarity index 94% rename from src/db/mongodb.py rename to src/core/mongodb.py index 2caca5b..5d1bba7 100644 --- a/src/db/mongodb.py +++ b/src/core/mongodb.py @@ -19,4 +19,4 @@ async def ensure_mongodb_available() -> None: client = mongodb.client if client is None: raise RuntimeError("MongoDB client has not been initialized") - await client.admin.command("ping") + await client.admin.command("ping") \ No newline at end of file diff --git a/src/core/redis.py b/src/core/redis.py new file mode 100644 index 0000000..3dff882 --- /dev/null +++ b/src/core/redis.py @@ -0,0 +1,21 @@ +import redis.asyncio as aioredis +from core.config import settings + +_redis_pool: aioredis.Redis | None = None + +async def init_redis() -> None: + global _redis_pool + _redis_pool = aioredis.from_url( + settings.REDIS_URL, encoding="utf-8", decode_responses=True + ) + + +async def close_redis() -> None: + if _redis_pool: + await _redis_pool.aclose() + + +async def get_redis() -> aioredis.Redis: + if _redis_pool is None: + raise RuntimeError("Redis pool has not been initialized") + return _redis_pool diff --git a/src/models/proxy.py b/src/models/proxy.py new file mode 100644 index 0000000..6c423f3 --- /dev/null +++ b/src/models/proxy.py @@ -0,0 +1,6 @@ +from pydantic import BaseModel, Field +from models.service import ServiceDocument + +class ProxyDocument(BaseModel): + port: int = Field(..., description="Port number of the proxy") + service: ServiceDocument = Field(..., description="Associated service details") \ No newline at end of file diff --git a/src/models/service.py b/src/models/service.py new file mode 100644 index 0000000..7caff45 --- /dev/null +++ b/src/models/service.py @@ -0,0 +1,6 @@ +from pydantic import BaseModel, Field + +class ServiceDocument(BaseModel): + name: str = Field(..., description="Name of the service") + port: int = Field(..., description="Port number of the service") + category: str = Field(..., description="Category of the service (e.g., web, pwn, etc.)") diff --git a/uv.lock b/uv.lock index 03d840f..88ce3c5 100644 --- a/uv.lock +++ b/uv.lock @@ -497,6 +497,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, ] +[[package]] +name = "redis" +version = "7.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/7f/3759b1d0d72b7c92f0d70ffd9dc962b7b7b5ee74e135f9d7d8ab06b8a318/redis-7.4.0.tar.gz", hash = "sha256:64a6ea7bf567ad43c964d2c30d82853f8df927c5c9017766c55a1d1ed95d18ad", size = 4943913, upload-time = "2026-03-24T09:14:37.53Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/3a/95deec7db1eb53979973ebd156f3369a72732208d1391cd2e5d127062a32/redis-7.4.0-py3-none-any.whl", hash = "sha256:a9c74a5c893a5ef8455a5adb793a31bb70feb821c86eccb62eebef5a19c429ec", size = 409772, upload-time = "2026-03-24T09:14:35.968Z" }, +] + [[package]] name = "rich" version = "14.3.4" @@ -604,6 +613,7 @@ dependencies = [ { name = "fastapi", extra = ["standard"] }, { name = "motor" }, { name = "pydantic-settings" }, + { name = "redis" }, ] [package.metadata] @@ -611,6 +621,7 @@ requires-dist = [ { name = "fastapi", extras = ["standard"], specifier = ">=0.135.3" }, { name = "motor", specifier = ">=3.7.1" }, { name = "pydantic-settings", specifier = ">=2.13.1" }, + { name = "redis", specifier = ">=7.4.0" }, ] [[package]]