diff --git a/docs/openapi.json b/docs/openapi.json index 346559624..d7f16e69f 100644 --- a/docs/openapi.json +++ b/docs/openapi.json @@ -16311,6 +16311,14 @@ }, "ssl_mode": { "type": "string", + "enum": [ + "disable", + "allow", + "prefer", + "require", + "verify-ca", + "verify-full" + ], "title": "SSL mode", "description": "SSL mode", "default": "prefer" diff --git a/src/constants.py b/src/constants.py index 88dd2aee5..81556042c 100644 --- a/src/constants.py +++ b/src/constants.py @@ -1,6 +1,6 @@ """Constants used in business logic.""" -from typing import Final +from typing import Final, Literal # Use Final[type] as type hint for all constants to ensure that type checkers (Mypy etc.) # will be able to detect assignements to such constants. @@ -158,7 +158,7 @@ # PostgreSQL connection constants # See: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-SSLMODE -POSTGRES_DEFAULT_SSL_MODE: Final[str] = "prefer" +POSTGRES_DEFAULT_SSL_MODE: Final[Literal["prefer"]] = "prefer" # See: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-GSSENCMODE POSTGRES_DEFAULT_GSS_ENCMODE: Final[str] = "prefer" diff --git a/src/models/config.py b/src/models/config.py index c245a4da3..c922be8de 100644 --- a/src/models/config.py +++ b/src/models/config.py @@ -228,8 +228,10 @@ class PostgreSQLDatabaseConfiguration(ConfigurationBase): description="Database namespace", ) - ssl_mode: str = Field( - constants.POSTGRES_DEFAULT_SSL_MODE, + ssl_mode: Literal[ + "disable", "allow", "prefer", "require", "verify-ca", "verify-full" + ] = Field( + default=constants.POSTGRES_DEFAULT_SSL_MODE, title="SSL mode", description="SSL mode", ) diff --git a/tests/unit/models/config/test_postgresql_database_configuration.py b/tests/unit/models/config/test_postgresql_database_configuration.py index bddaf1ab3..5bff8c759 100644 --- a/tests/unit/models/config/test_postgresql_database_configuration.py +++ b/tests/unit/models/config/test_postgresql_database_configuration.py @@ -219,3 +219,48 @@ def test_postgresql_database_configuration_ca_cert_path(subtests: SubTests) -> N port=1234, ca_cert_path=Path(""), ) # pyright: ignore[reportCallIssue] + + +def test_postgresql_database_configuration_ssl_mode(subtests: SubTests) -> None: + """Test the PostgreSQLDatabaseConfiguration model.""" + ssl_modes = ("disable", "allow", "prefer", "require", "verify-ca", "verify-full") + + for ssl_mode in ssl_modes: + with subtests.test(msg=f"SSL mode {ssl_mode}"): + # pylint: disable=no-member + c = PostgreSQLDatabaseConfiguration( + db="db", + user="user", + password="password", + ssl_mode=ssl_mode, + ) # pyright: ignore[reportCallIssue] + + # most attributes are set to default values + assert c is not None + assert c.host == "localhost" + assert c.port == 5432 + assert c.db == "db" + assert c.user == "user" + assert c.password.get_secret_value() == "password" + assert c.ssl_mode == ssl_mode + assert c.gss_encmode == POSTGRES_DEFAULT_GSS_ENCMODE + assert c.namespace == "public" + assert c.ca_cert_path is None + + +def test_postgresql_database_configuration_improper_ssl_mode( + subtests: SubTests, +) -> None: + """Test the PostgreSQLDatabaseConfiguration model.""" + ssl_modes = ("foo", "bar", "baz", "") + + for ssl_mode in ssl_modes: + with subtests.test(msg=f"SSL mode {ssl_mode}"): + with pytest.raises(ValueError, match="Input should be 'disable'"): + # pylint: disable=no-member + PostgreSQLDatabaseConfiguration( + db="db", + user="user", + password="password", + ssl_mode=ssl_mode, + ) # pyright: ignore[reportCallIssue]