From 2826999ddc74ba667b63c57c15f698b5b13ac5d4 Mon Sep 17 00:00:00 2001 From: Jiang Date: Tue, 24 Feb 2026 17:01:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5URL=E4=B8=AD=E5=AF=86=E7=A0=81=E5=8C=85?= =?UTF-8?q?=E5=90=AB"@"=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/core/config.py | 7 +++- app/infra/repositories/metadata_repository.py | 42 +++++++++++++++---- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/app/core/config.py b/app/core/config.py index 3a2eea4..fe12aaa 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -1,4 +1,5 @@ from pathlib import Path +from urllib.parse import quote_plus from pydantic_settings import BaseSettings, SettingsConfigDict @@ -60,12 +61,14 @@ class Settings(BaseSettings): @property def SQLALCHEMY_DATABASE_URI(self) -> str: - return f"postgresql://{self.DB_USER}:{self.DB_PASSWORD}@{self.DB_HOST}:{self.DB_PORT}/{self.DB_NAME}" + db_password = quote_plus(self.DB_PASSWORD) + return f"postgresql://{self.DB_USER}:{db_password}@{self.DB_HOST}:{self.DB_PORT}/{self.DB_NAME}" @property def METADATA_DATABASE_URI(self) -> str: + metadata_password = quote_plus(self.METADATA_DB_PASSWORD) return ( - f"postgresql+psycopg://{self.METADATA_DB_USER}:{self.METADATA_DB_PASSWORD}" + f"postgresql+psycopg://{self.METADATA_DB_USER}:{metadata_password}" f"@{self.METADATA_DB_HOST}:{self.METADATA_DB_PORT}/{self.METADATA_DB_NAME}" ) diff --git a/app/infra/repositories/metadata_repository.py b/app/infra/repositories/metadata_repository.py index f77e1fc..b02c05d 100644 --- a/app/infra/repositories/metadata_repository.py +++ b/app/infra/repositories/metadata_repository.py @@ -5,10 +5,28 @@ from uuid import UUID from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession -from app.core.encryption import get_encryptor +from app.core.encryption import get_encryptor, is_encryption_configured from app.infra.db.metadata import models +def _normalize_postgres_dsn(dsn: str) -> str: + if not dsn or "://" not in dsn: + return dsn + scheme, rest = dsn.split("://", 1) + if scheme not in ("postgresql", "postgres", "postgresql+psycopg"): + return dsn + if "@" not in rest: + return dsn + userinfo, hostinfo = rest.rsplit("@", 1) + if ":" not in userinfo: + return dsn + username, password = userinfo.split(":", 1) + if "@" not in password: + return dsn + password = password.replace("@", "%40") + return f"{scheme}://{username}:{password}@{hostinfo}" + + @dataclass(frozen=True) class ProjectDbRouting: project_id: UUID @@ -84,8 +102,12 @@ class MetadataRepository: record = result.scalar_one_or_none() if not record: return None - encryptor = get_encryptor() - dsn = encryptor.decrypt(record.dsn_encrypted) + if is_encryption_configured(): + encryptor = get_encryptor() + dsn = encryptor.decrypt(record.dsn_encrypted) + else: + dsn = record.dsn_encrypted + dsn = _normalize_postgres_dsn(dsn) return ProjectDbRouting( project_id=record.project_id, db_role=record.db_role, @@ -106,12 +128,14 @@ class MetadataRepository: record = result.scalar_one_or_none() if not record: return None - encryptor = get_encryptor() - password = ( - encryptor.decrypt(record.gs_admin_password_encrypted) - if record.gs_admin_password_encrypted - else None - ) + if record.gs_admin_password_encrypted: + if is_encryption_configured(): + encryptor = get_encryptor() + password = encryptor.decrypt(record.gs_admin_password_encrypted) + else: + password = record.gs_admin_password_encrypted + else: + password = None return ProjectGeoServerInfo( project_id=record.project_id, gs_base_url=record.gs_base_url,