Skip to content

Commit

Permalink
Config Validation
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnGrubba committed Jul 26, 2024
1 parent 1055a32 commit 5667556
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 6 deletions.
70 changes: 70 additions & 0 deletions src/tools/conf/AccountFeaturesConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,83 @@ class AccountFeaturesConfig:
issuer_name_2fa: str = config["account_features"]["2fa"]["issuer_name"]
issuer_image_url_2fa: str = config["account_features"]["2fa"]["issuer_image_url"]
qr_code_endpoint_2fa: bool = config["account_features"]["2fa"]["qr_endpoint"]

if not isinstance(config["account_features"]["allow_add_fields_on_signup"], list):
raise ValueError(
"account_features.allow_add_fields_on_signup must be a list (got type {})".format(
type(config["account_features"]["allow_add_fields_on_signup"])
)
)

allow_add_fields_on_signup: set[str] = set(
config["account_features"]["allow_add_fields_on_signup"]
) - set(not_updateable_cols_internal)

if not isinstance(config["account_features"]["allow_add_fields_patch_user"], list):
raise ValueError(
"account_features.allow_add_fields_patch_user must be a list (got type {})".format(
type(config["account_features"]["allow_add_fields_patch_user"])
)
)

allow_add_fields_patch_user: set[str] = set(
config["account_features"]["allow_add_fields_patch_user"]
) - set(not_updateable_cols_internal)
allow_deletion: bool = config["account_features"]["allow_deletion"]
deletion_pending_minutes: int = config["account_features"][
"deletion_pending_minutes"
]

def validate_types(self) -> bool:
"""This is to Type Check the Configuration"""
if not isinstance(self.enable_reset_pswd, bool):
raise ValueError(
"account_features.enable_reset_pswd must be a boolean (got type {})".format(
type(self.enable_reset_pswd)
)
)
if not isinstance(self.reset_pswd_conf_mail, bool):
raise ValueError(
"account_features.reset_pswd_conf_mail must be a boolean (got type {})".format(
type(self.reset_pswd_conf_mail)
)
)
if not isinstance(self.enable_2fa, bool):
raise ValueError(
"account_features.2fa.enable must be a boolean (got type {})".format(
type(self.enable_2fa)
)
)
if not isinstance(self.issuer_name_2fa, str):
raise ValueError(
"account_features.2fa.issuer_name must be a string (got type {})".format(
type(self.issuer_name_2fa)
)
)
if not isinstance(self.issuer_image_url_2fa, str):
raise ValueError(
"account_features.2fa.issuer_image_url must be a string (got type {})".format(
type(self.issuer_image_url_2fa)
)
)
if not isinstance(self.qr_code_endpoint_2fa, bool):
raise ValueError(
"account_features.2fa.qr_endpoint must be a boolean (got type {})".format(
type(self.qr_code_endpoint_2fa)
)
)
if not isinstance(self.allow_deletion, bool):
raise ValueError(
"account_features.allow_deletion must be a boolean (got type {})".format(
type(self.allow_deletion)
)
)
if not isinstance(self.deletion_pending_minutes, int):
raise ValueError(
"account_features.deletion_pending_minutes must be an integer (got type {})".format(
type(self.deletion_pending_minutes)
)
)


AccountFeaturesConfig().validate_types()
36 changes: 36 additions & 0 deletions src/tools/conf/EmailConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,39 @@ class EmailConfig:
sender_email: str = config["email"]["sender_email"]
smtp_host: str = config["email"]["smtp_host"]
smtp_port: int = config["email"]["smtp_port"]

def validate_types(self) -> None:
"""This is to Type Check the Configuration"""
if not isinstance(self.login_usr, str):
raise ValueError(
"email.login_usr must be a string (got type {})".format(
type(self.login_usr)
)
)
if not isinstance(self.login_pwd, str):
raise ValueError(
"email.login_pwd must be a string (got type {})".format(
type(self.login_pwd)
)
)
if not isinstance(self.sender_email, str):
raise ValueError(
"email.sender_email must be a string (got type {})".format(
type(self.sender_email)
)
)
if not isinstance(self.smtp_host, str):
raise ValueError(
"email.smtp_host must be a string (got type {})".format(
type(self.smtp_host)
)
)
if not isinstance(self.smtp_port, int):
raise ValueError(
"email.smtp_port must be an integer (got type {})".format(
type(self.smtp_port)
)
)


EmailConfig().validate_types()
29 changes: 27 additions & 2 deletions src/tools/conf/InternalConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,38 @@

class InternalConfig:
internal_api_key: str = config["internal"]["internal_api_key"]
# Type Check here because calculations need to be done immediately
if not isinstance(config["internal"]["internal_columns"], list):
raise ValueError(
"internal.internal_columns must be a list (got type {})".format(
type(config["internal"]["internal_columns"])
)
)
internal_columns: dict = dict(
ChainMap(*[{col: 0} for col in config["internal"]["internal_columns"]])
ChainMap(*[{col: 0} for col in set(config["internal"]["internal_columns"])])
)
internal_columns.update(insecure_cols)
# Insecure Cols + Internal Cols can't be updated by the user
not_updateable_columns: list = (
if not isinstance(config["internal"]["not_updateable_columns"], list):
raise ValueError(
"internal.not_updateable_columns must be a list (got type {})".format(
type(config["internal"]["not_updateable_columns"])
)
)
not_updateable_columns: set = set(
config["internal"]["not_updateable_columns"]
+ list(internal_columns.keys())
+ not_updateable_cols_internal
)

def validate_types(self) -> bool:
"""This is to Type Check the Configuration"""
if not isinstance(self.internal_api_key, str):
raise ValueError(
"internal.internal_api_key must be a string (got type {})".format(
type(self.internal_api_key)
)
)


InternalConfig().validate_types()
42 changes: 40 additions & 2 deletions src/tools/conf/SecurityConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,46 @@


class SecurityConfig:
access_control_origins: set[str] = set(config["security"]["allow_origins"])
allow_headers: set[str] = set(config["security"]["allow_headers"])
access_control_origins: set[str] = config["security"]["allow_origins"]
allow_headers: set[str] = config["security"]["allow_headers"]
max_login_attempts: int = config["security"]["max_login_attempts"]
login_timeout: int = config["security"]["login_timeout"]
expire_unfinished_timeout: int = config["security"]["expire_unfinished_timeout"]

def validate_types(self) -> bool:
"""This is to Type Check the Configuration"""
if not isinstance(self.access_control_origins, list):
self.access_control_origins = set(self.access_control_origins)
raise ValueError(
"security.allow_origins must be a list (got type {})".format(
type(self.access_control_origins)
)
)
if not isinstance(self.allow_headers, list):
self.allow_headers = set(self.allow_headers)
raise ValueError(
"security.allow_headers must be a list (got type {})".format(
type(self.allow_headers)
)
)
if not isinstance(self.max_login_attempts, int):
raise ValueError(
"security.max_login_attempts must be an integer (got type {})".format(
type(self.max_login_attempts)
)
)
if not isinstance(self.login_timeout, int):
raise ValueError(
"security.login_timeout must be an integer (got type {})".format(
type(self.login_timeout)
)
)
if not isinstance(self.expire_unfinished_timeout, int):
raise ValueError(
"security.expire_unfinished_timeout must be an integer (got type {})".format(
type(self.expire_unfinished_timeout)
)
)


SecurityConfig().validate_types()
42 changes: 42 additions & 0 deletions src/tools/conf/SessionConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,45 @@ class SessionConfig:
auto_cookie_name: str = config["session"]["auto_cookie_name"]
cookie_samesite: str = config["session"]["cookie_samesite"]
cookie_secure: bool = config["session"]["cookie_secure"]

def validate_types(self) -> bool:
"""This is to Type Check the Configuration"""
if not isinstance(self.session_expiry_seconds, int):
raise ValueError(
"session.session_expiry_seconds must be an integer (got type {})".format(
type(self.session_expiry_seconds)
)
)
if not isinstance(self.max_session_count, int):
raise ValueError(
"session.max_session_count must be an integer (got type {})".format(
type(self.max_session_count)
)
)
if not isinstance(self.auto_cookie, bool):
raise ValueError(
"session.auto_cookie must be a boolean (got type {})".format(
type(self.auto_cookie)
)
)
if not isinstance(self.auto_cookie_name, str):
raise ValueError(
"session.auto_cookie_name must be a string (got type {})".format(
type(self.auto_cookie_name)
)
)
if not isinstance(self.cookie_samesite, str):
raise ValueError(
"session.cookie_samesite must be a string (got type {})".format(
type(self.cookie_samesite)
)
)
if not isinstance(self.cookie_secure, bool):
raise ValueError(
"session.cookie_secure must be a boolean (got type {})".format(
type(self.cookie_secure)
)
)


SessionConfig().validate_types()
4 changes: 2 additions & 2 deletions src/tools/conf/SignupConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class SignupConfig:
conf_code_expiry: int = config["signup"]["conf_code_expiry"]
conf_code_complexity: int = config["signup"]["conf_code_complexity"]
enable_welcome_email: bool = config["signup"]["enable_welcome_email"]
oauth_providers: list[str] = config["signup"]["oauth"]["providers_enabled"]
oauth_providers: set[str] = config["signup"]["oauth"]["providers_enabled"]
oauth_base_url: str = str(config["signup"]["oauth"]["base_url"]).removesuffix("/")

def validate_types(self) -> bool:
Expand Down Expand Up @@ -36,6 +36,7 @@ def validate_types(self) -> bool:
)
)
if not isinstance(self.oauth_providers, list):
self.oauth_providers = set(self.oauth_providers)
raise ValueError(
"signup.oauth.providers_enabled must be a list (got type {})".format(
type(self.oauth_providers)
Expand All @@ -49,7 +50,6 @@ def validate_types(self) -> bool:
type(self.oauth_base_url)
)
)
pass


SignupConfig().validate_types()
2 changes: 2 additions & 0 deletions src/tools/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
# Create TTL For Account Deletions
users_collection.create_index("expiresAfter", expireAfterSeconds=0, sparse=True)

logger.info("\u001b[32m+ MongoDB Setup Done\u001b[0m")


def bson_to_json(data: bson.BSON) -> dict:
"""Convert BSON to JSON. From MongoDB to JSON.
Expand Down

0 comments on commit 5667556

Please sign in to comment.