Skip to content

fix: handle tenant not found error #403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions supertokens_python/recipe/multitenancy/api/implementation.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ async def login_methods_get(
tenant_id, user_context
)

if tenant_config_res is None:
raise Exception("Tenant not found")

provider_inputs_from_static = api_options.static_third_party_providers
provider_configs_from_core = tenant_config_res.third_party.providers

Expand All @@ -61,6 +64,11 @@ async def login_methods_get(
client_type,
user_context,
)

if provider_instance is None:
# because creating instance from the merged provider list itself
raise Exception("Should never come here")

final_provider_list.append(
ThirdPartyProvider(
provider_instance.id, provider_instance.config.name
Expand Down
2 changes: 1 addition & 1 deletion supertokens_python/recipe/multitenancy/asyncio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ async def delete_tenant(

async def get_tenant(
tenant_id: str, user_context: Optional[Dict[str, Any]] = None
) -> GetTenantOkResult:
) -> Optional[GetTenantOkResult]:
if user_context is None:
user_context = {}
recipe = MultitenancyRecipe.get_instance()
Expand Down
2 changes: 1 addition & 1 deletion supertokens_python/recipe/multitenancy/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ async def delete_tenant(
@abstractmethod
async def get_tenant(
self, tenant_id: str, user_context: Dict[str, Any]
) -> GetTenantOkResult:
) -> Optional[GetTenantOkResult]:
pass

@abstractmethod
Expand Down
7 changes: 7 additions & 0 deletions supertokens_python/recipe/multitenancy/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ async def login_methods_get(
tenant_id, user_context
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you have two api imple for multi tenancy? One here, and one in supertokens_python/recipe/multitenancy/api/implementation.py

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the redundant one from recipe.py


if tenant_config is None:
raise Exception("Tenant not found")

provider_inputs_from_static = api_options.static_third_party_providers
provider_configs_from_core = tenant_config.third_party.providers

Expand All @@ -233,6 +236,10 @@ async def login_methods_get(
client_type,
user_context,
)

if provider_instance is None:
raise Exception("Should never come here")

except ClientTypeNotFoundError:
continue
final_provider_list.append(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,16 @@ async def delete_tenant(

async def get_tenant(
self, tenant_id: Optional[str], user_context: Dict[str, Any]
) -> GetTenantOkResult:
) -> Optional[GetTenantOkResult]:
res = await self.querier.send_get_request(
NormalisedURLPath(
f"{tenant_id or DEFAULT_TENANT_ID}/recipe/multitenancy/tenant"
),
)

if res["status"] == "TENANT_NOT_FOUND_ERROR":
return None

tenant_config = parse_tenant_config(res)

return GetTenantOkResult(
Expand Down
9 changes: 7 additions & 2 deletions supertokens_python/recipe/thirdparty/api/authorisation_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
if TYPE_CHECKING:
from supertokens_python.recipe.thirdparty.interfaces import APIOptions, APIInterface

from supertokens_python.exceptions import raise_bad_input_exception
from supertokens_python.exceptions import raise_bad_input_exception, BadInputError
from supertokens_python.utils import send_200_response


Expand Down Expand Up @@ -53,7 +53,12 @@ async def handle_authorisation_url_api(
user_context=user_context,
)

provider = provider_response.provider
if provider_response is None:
raise BadInputError(
f"the provider {third_party_id} could not be found in the configuration"
)

provider = provider_response
result = await api_implementation.authorisation_url_get(
provider=provider,
redirect_uri_on_provider_dashboard=redirect_uri_on_provider_dashboard,
Expand Down
9 changes: 7 additions & 2 deletions supertokens_python/recipe/thirdparty/api/signinup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
if TYPE_CHECKING:
from supertokens_python.recipe.thirdparty.interfaces import APIOptions, APIInterface

from supertokens_python.exceptions import raise_bad_input_exception
from supertokens_python.exceptions import raise_bad_input_exception, BadInputError
from supertokens_python.utils import send_200_response


Expand Down Expand Up @@ -64,7 +64,12 @@ async def handle_sign_in_up_api(
user_context=user_context,
)

provider = provider_response.provider
if provider_response is None:
raise BadInputError(
f"the provider {third_party_id} could not be found in the configuration"
)

provider = provider_response

result = await api_implementation.sign_in_up_post(
provider=provider,
Expand Down
2 changes: 1 addition & 1 deletion supertokens_python/recipe/thirdparty/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ async def get_provider(
client_type: Optional[str],
tenant_id: str,
user_context: Dict[str, Any],
) -> GetProviderOkResult:
) -> Optional[Provider]:
pass


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,11 @@ async def find_and_create_provider_instance(
third_party_id: str,
client_type: Optional[str],
user_context: Dict[str, Any],
) -> Provider:
) -> Optional[Provider]:
for provider_input in providers:
if provider_input.config.third_party_id == third_party_id:
provider_instance = create_provider(provider_input)
await fetch_and_set_config(provider_instance, client_type, user_context)
return provider_instance

raise Exception(
f"the provider {third_party_id} could not be found in the configuration"
)
return None
8 changes: 4 additions & 4 deletions supertokens_python/recipe/thirdparty/recipe_implementation.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
from supertokens_python.querier import Querier

from .interfaces import (
GetProviderOkResult,
ManuallyCreateOrUpdateUserOkResult,
RecipeInterface,
SignInUpOkResult,
Expand Down Expand Up @@ -189,6 +188,9 @@ async def get_provider(
user_context=user_context,
)

if tenant_config is None:
raise Exception("Tenant not found")

merged_providers = merge_providers_from_core_and_static(
provider_configs_from_core=tenant_config.third_party.providers,
provider_inputs_from_static=self.providers,
Expand All @@ -198,6 +200,4 @@ async def get_provider(
merged_providers, third_party_id, client_type, user_context
)

return GetProviderOkResult(
provider,
)
return provider
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ async def thirdparty_get_provider(
client_type: Optional[str],
tenant_id: str,
user_context: Dict[str, Any],
) -> ThirdPartyInterfaces.GetProviderOkResult:
) -> Optional[ThirdPartyInterfaces.Provider]:
pass

@abstractmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
from typing import TYPE_CHECKING, Any, Dict, List, Union, Callable, Optional

import supertokens_python.recipe.emailpassword.interfaces as EPInterfaces
from supertokens_python.recipe.thirdparty.interfaces import GetProviderOkResult
from supertokens_python.recipe.thirdparty.provider import ProviderInput
from supertokens_python.recipe.thirdparty.provider import ProviderInput, Provider
from supertokens_python.recipe.thirdparty.types import RawUserInfoFromProvider
from supertokens_python.recipe.emailpassword.utils import EmailPasswordConfig

Expand Down Expand Up @@ -276,7 +275,7 @@ async def thirdparty_get_provider(
client_type: Optional[str],
tenant_id: str,
user_context: Dict[str, Any],
) -> GetProviderOkResult:
) -> Optional[Provider]:
if self.tp_get_provider is None:
raise Exception("No thirdparty provider configured")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
from typing import Any, Dict, List, Optional, Union

from supertokens_python.recipe.thirdparty.interfaces import (
GetProviderOkResult,
ManuallyCreateOrUpdateUserOkResult,
RecipeInterface,
SignInUpOkResult,
)
from supertokens_python.recipe.thirdparty.provider import Provider
from supertokens_python.recipe.thirdparty.types import RawUserInfoFromProvider, User
from supertokens_python.recipe.thirdpartyemailpassword.interfaces import (
RecipeInterface as ThirdPartyEmailPasswordRecipeInterface,
Expand Down Expand Up @@ -164,7 +164,7 @@ async def get_provider(
client_type: Optional[str],
tenant_id: str,
user_context: Dict[str, Any],
) -> GetProviderOkResult:
) -> Optional[Provider]:
return await self.recipe_implementation.thirdparty_get_provider(
third_party_id,
client_type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ async def thirdparty_get_provider(
client_type: Optional[str],
tenant_id: str,
user_context: Dict[str, Any],
) -> ThirdPartyInterfaces.GetProviderOkResult:
) -> Optional[ThirdPartyInterfaces.Provider]:
pass

@abstractmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union

from supertokens_python.recipe.thirdparty.provider import ProviderInput
from supertokens_python.recipe.thirdparty.provider import ProviderInput, Provider
from supertokens_python.recipe.thirdparty.types import RawUserInfoFromProvider

from ...passwordless.interfaces import (
Expand All @@ -42,7 +42,6 @@
UpdateUserUnknownUserIdError,
)
from ...thirdparty.interfaces import (
GetProviderOkResult,
ManuallyCreateOrUpdateUserOkResult,
SignInUpOkResult,
)
Expand Down Expand Up @@ -296,7 +295,7 @@ async def thirdparty_get_provider(
client_type: Optional[str],
tenant_id: str,
user_context: Dict[str, Any],
) -> GetProviderOkResult:
) -> Optional[Provider]:
if self.tp_get_provider is None:
raise Exception("No thirdparty provider configured")
return await self.tp_get_provider(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@
from typing import Any, Dict, List, Optional, Union

from supertokens_python.recipe.thirdparty.interfaces import (
GetProviderOkResult,
ManuallyCreateOrUpdateUserOkResult,
RecipeInterface,
SignInUpOkResult,
)
from supertokens_python.recipe.thirdparty.types import RawUserInfoFromProvider, User

from ..interfaces import RecipeInterface as ThirdPartyPasswordlessRecipeInterface
from ...thirdparty.provider import Provider


class RecipeImplementation(RecipeInterface):
Expand Down Expand Up @@ -138,7 +138,7 @@ async def get_provider(
client_type: Optional[str],
tenant_id: str,
user_context: Dict[str, Any],
) -> GetProviderOkResult:
) -> Optional[Provider]:
return await self.recipe_implementation.thirdparty_get_provider(
third_party_id, client_type, tenant_id, user_context
)
9 changes: 9 additions & 0 deletions tests/multitenancy/test_tenants_crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,21 @@ async def test_tenant_crud():
assert len(tenants.tenants) == 4

t1_config = await get_tenant("t1")
assert t1_config is not None
assert t1_config.emailpassword.enabled is True
assert t1_config.passwordless.enabled is False
assert t1_config.third_party.enabled is False
assert t1_config.core_config == {}

t2_config = await get_tenant("t2")
assert t2_config is not None
assert t2_config.emailpassword.enabled is False
assert t2_config.passwordless.enabled is True
assert t2_config.third_party.enabled is False
assert t2_config.core_config == {}

t3_config = await get_tenant("t3")
assert t3_config is not None
assert t3_config.emailpassword.enabled is False
assert t3_config.passwordless.enabled is False
assert t3_config.third_party.enabled is True
Expand All @@ -95,6 +98,7 @@ async def test_tenant_crud():
# update tenant1 to add passwordless:
await create_or_update_tenant("t1", TenantConfig(passwordless_enabled=True))
t1_config = await get_tenant("t1")
assert t1_config is not None
assert t1_config.emailpassword.enabled is True
assert t1_config.passwordless.enabled is True
assert t1_config.third_party.enabled is False
Expand All @@ -103,6 +107,8 @@ async def test_tenant_crud():
# update tenant1 to add thirdparty:
await create_or_update_tenant("t1", TenantConfig(third_party_enabled=True))
t1_config = await get_tenant("t1")
assert t1_config is not None
assert t1_config is not None
assert t1_config.emailpassword.enabled is True
assert t1_config.passwordless.enabled is True
assert t1_config.third_party.enabled is True
Expand Down Expand Up @@ -131,6 +137,7 @@ async def test_tenant_thirdparty_config():
)

tenant_config = await get_tenant("t1")
assert tenant_config is not None

assert len(tenant_config.third_party.providers) == 1
provider = tenant_config.third_party.providers[0]
Expand Down Expand Up @@ -189,6 +196,7 @@ async def generate_fake_email(_: str, __: str, ___: Dict[str, Any]):
)

tenant_config = await get_tenant("t1")
assert tenant_config is not None
assert len(tenant_config.third_party.providers) == 1
provider = tenant_config.third_party.providers[0]
assert provider.third_party_id == "google"
Expand Down Expand Up @@ -232,6 +240,7 @@ async def generate_fake_email(_: str, __: str, ___: Dict[str, Any]):
await delete_third_party_config("t1", "google")

tenant_config = await get_tenant("t1")
assert tenant_config is not None
assert len(tenant_config.third_party.providers) == 0


Expand Down
18 changes: 12 additions & 6 deletions tests/thirdparty/test_multitenancy.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,19 +201,25 @@ async def test_get_provider():
)

provider1 = await get_provider("t1", "google", None)
assert provider1.provider.config.third_party_id == "google"
assert provider1 is not None
assert provider1.config.third_party_id == "google"

provider2 = await get_provider("t1", "facebook", None)
assert provider2.provider.config.third_party_id == "facebook"
assert provider2 is not None
assert provider2.config.third_party_id == "facebook"

provider3 = await get_provider("t2", "facebook", None)
assert provider3.provider.config.third_party_id == "facebook"
assert provider3 is not None
assert provider3.config.third_party_id == "facebook"

provider4 = await get_provider("t2", "discord", None)
assert provider4.provider.config.third_party_id == "discord"
assert provider4 is not None
assert provider4.config.third_party_id == "discord"

provider5 = await get_provider("t3", "discord", None)
assert provider5.provider.config.third_party_id == "discord"
assert provider5 is not None
assert provider5.config.third_party_id == "discord"

provider6 = await get_provider("t3", "linkedin", None)
assert provider6.provider.config.third_party_id == "linkedin"
assert provider6 is not None
assert provider6.config.third_party_id == "linkedin"