From c5a7ae409bd33dbb2625ff08afe6f1ea4c029f00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Diemer?= Date: Thu, 12 Jan 2023 17:35:22 +0100 Subject: [PATCH] Raise specific exceptions in tool configuration --- pylti1p3/exception.py | 6 ++++- pylti1p3/lineitem.py | 2 +- pylti1p3/tool_config/abstract.py | 5 ++-- pylti1p3/tool_config/dict.py | 39 ++++++++++++++++++++----------- pylti1p3/tool_config/json_file.py | 9 +++++-- 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/pylti1p3/exception.py b/pylti1p3/exception.py index e8fccfa..a7be271 100644 --- a/pylti1p3/exception.py +++ b/pylti1p3/exception.py @@ -5,7 +5,11 @@ class LtiException(Exception): pass -class OIDCException(Exception): +class LtiConfigurationException(LtiException): + pass + + +class OIDCException(LtiException): pass diff --git a/pylti1p3/lineitem.py b/pylti1p3/lineitem.py index a9d77b3..66b3561 100644 --- a/pylti1p3/lineitem.py +++ b/pylti1p3/lineitem.py @@ -176,7 +176,7 @@ def set_submission_review( custom: t.Optional[t.Dict[str, str]] = None, ) -> "LineItem": if not isinstance(reviewable_status, list): - raise Exception('Invalid "reviewable_status" argument') + raise ValueError('Invalid "reviewable_status" argument') self._submission_review: TSubmissionReview = { "reviewableStatus": reviewable_status diff --git a/pylti1p3/tool_config/abstract.py b/pylti1p3/tool_config/abstract.py index e97d07e..93840bf 100644 --- a/pylti1p3/tool_config/abstract.py +++ b/pylti1p3/tool_config/abstract.py @@ -2,6 +2,7 @@ from abc import ABCMeta, abstractmethod import typing_extensions as te from ..deployment import Deployment +from ..exception import LtiConfigurationException from ..registration import Registration from ..request import Request @@ -109,9 +110,9 @@ def get_jwks( reg = self.find_registration(iss) elif self.check_iss_has_many_clients(iss): if not client_id: - raise Exception("client_id is not specified") + raise LtiConfigurationException("client_id is not specified") reg = self.find_registration_by_params(iss, client_id, **kwargs) else: - raise Exception("Invalid issuer relation type") + raise LtiConfigurationException("Invalid issuer relation type") keys = reg.get_jwks() return {"keys": keys} diff --git a/pylti1p3/tool_config/dict.py b/pylti1p3/tool_config/dict.py index fbde5e1..06ee866 100644 --- a/pylti1p3/tool_config/dict.py +++ b/pylti1p3/tool_config/dict.py @@ -1,6 +1,7 @@ import typing as t import typing_extensions as te from ..deployment import Deployment +from ..exception import LtiConfigurationException from ..registration import Registration, TKeySet from ..request import Request from .abstract import ToolConfAbstract @@ -79,7 +80,7 @@ def __init__(self, json_data: TJsonData): """ super().__init__() if not isinstance(json_data, dict): - raise Exception("Invalid tool conf format. Must be dict") + raise LtiConfigurationException("Invalid tool conf format. Must be dict") for iss, iss_conf in json_data.items(): if isinstance(iss_conf, dict): @@ -90,7 +91,7 @@ def __init__(self, json_data: TJsonData): for v in iss_conf: self._validate_iss_config_item(iss, v) else: - raise Exception( + raise LtiConfigurationException( "Invalid tool conf format. Allowed types of elements: list or dict" ) @@ -102,7 +103,7 @@ def __init__(self, json_data: TJsonData): def _validate_iss_config_item(self, iss: str, iss_conf: TIssConf): if not isinstance(iss_conf, dict): - raise Exception( + raise LtiConfigurationException( f"Invalid configuration {iss} for the {str(iss_conf)} issuer. Must be dict" ) required_keys = [ @@ -113,11 +114,11 @@ def _validate_iss_config_item(self, iss: str, iss_conf: TIssConf): ] for key in required_keys: if key not in iss_conf: - raise Exception( + raise LtiConfigurationException( f"Key '{key}' is missing in the {str(iss_conf)} config for the {iss} issuer" ) if not isinstance(iss_conf["deployment_ids"], list): - raise Exception( + raise LtiConfigurationException( f"Invalid deployment_ids value in the {str(iss_conf)} config for the {iss} issuer. " f"Must be a list" ) @@ -175,7 +176,9 @@ def set_public_key( ): if self.check_iss_has_many_clients(iss): if not client_id: - raise Exception("Can't set public key: missing client_id") + raise LtiConfigurationException( + "Can't set public key: missing client_id" + ) if iss not in self._public_key_many_clients: self._public_key_many_clients[iss] = {} self._public_key_many_clients[iss][client_id] = key_content @@ -185,10 +188,12 @@ def set_public_key( def get_public_key(self, iss: str, client_id: t.Optional[str] = None): if self.check_iss_has_many_clients(iss): if not client_id: - raise Exception("Can't get public key: missing client_id") + raise LtiConfigurationException( + "Can't get public key: missing client_id" + ) clients_dict = self._public_key_many_clients.get(iss, {}) if not isinstance(clients_dict, dict): - raise Exception("Invalid clients data") + raise LtiConfigurationException("Invalid clients data") return clients_dict.get(client_id) return self._public_key_one_client.get(iss) @@ -197,7 +202,9 @@ def set_private_key( ): if self.check_iss_has_many_clients(iss): if not client_id: - raise Exception("Can't set private key: missing client_id") + raise LtiConfigurationException( + "Can't set private key: missing client_id" + ) if iss not in self._private_key_many_clients: self._private_key_many_clients[iss] = {} self._private_key_many_clients[iss][client_id] = key_content # type: ignore @@ -207,18 +214,20 @@ def set_private_key( def get_private_key(self, iss: str, client_id: t.Optional[str] = None): if self.check_iss_has_many_clients(iss): if not client_id: - raise Exception("Can't get private key: missing client_id") + raise LtiConfigurationException( + "Can't get private key: missing client_id" + ) clients_dict = self._private_key_many_clients.get(iss, {}) if not isinstance(clients_dict, dict): - raise Exception("Invalid clients data") + raise LtiConfigurationException("Invalid clients data") return clients_dict.get(client_id) return self._private_key_one_client.get(iss) def get_iss_config(self, iss: str, client_id: t.Optional[str] = None): if not self._config: - raise Exception("Config is not set") + raise LtiConfigurationException("Config is not set") if iss not in self._config: - raise Exception(f"iss {iss} not found in settings") + raise LtiConfigurationException(f"iss {iss} not found in settings") config_iss = self._config[iss] if isinstance(config_iss, list): @@ -231,7 +240,9 @@ def get_iss_config(self, iss: str, client_id: t.Optional[str] = None): or (not client_id and items_len == 1) ): return subitem - raise Exception(f"iss {iss} [client_id={client_id}] not found in settings") + raise LtiConfigurationException( + f"iss {iss} [client_id={client_id}] not found in settings" + ) return config_iss def get_jwks( diff --git a/pylti1p3/tool_config/json_file.py b/pylti1p3/tool_config/json_file.py index e9ceaeb..c6cbae3 100644 --- a/pylti1p3/tool_config/json_file.py +++ b/pylti1p3/tool_config/json_file.py @@ -2,6 +2,7 @@ import json import os +from ..exception import LtiConfigurationException from .dict import ToolConfDict, TIssConf, TJsonData @@ -61,7 +62,9 @@ def __init__(self, config_file: str): deployment_ids (list) - The deployment_id passed by the platform during launch """ if not os.path.isfile(config_file): - raise Exception("LTI tool config file not found: " + config_file) + raise LtiConfigurationException( + f"LTI tool config file not found: {config_file}" + ) self._configs_dir = os.path.dirname(config_file) with open(config_file, encoding="utf-8") as cfg: @@ -83,7 +86,9 @@ def _process_iss_conf_item( ): private_key_file = iss_conf.get("private_key_file") if not private_key_file: - raise Exception("iss config error: private_key_file not found") + raise LtiConfigurationException( + "iss config error: private_key_file not found" + ) if not private_key_file.startswith("/"): private_key_file = self._configs_dir + "/" + private_key_file