From 396bf8f50394273b29fa802138e1976adcc9922c Mon Sep 17 00:00:00 2001 From: rishabhpoddar Date: Mon, 21 Oct 2024 18:41:19 +0530 Subject: [PATCH] more changes --- .../tenant-management/overview.mdx | 2 +- .../tenant-management/overview.mdx | 2 +- .../tenant-management/overview.mdx | 2 +- .../tenant-management/overview.mdx | 2 +- .../automatic-account-linking.mdx | 45 +++- .../manual-account-linking.mdx | 234 ++++++++++++++++-- .../saml/with-boxyhq/integration-steps.mdx | 2 +- .../tenant-management/overview.mdx | 2 +- .../tenant-management/overview.mdx | 2 +- .../automatic-account-linking.mdx | 45 +++- .../manual-account-linking.mdx | 234 ++++++++++++++++-- .../saml/with-boxyhq/integration-steps.mdx | 2 +- .../tenant-management/overview.mdx | 2 +- .../tenant-management/overview.mdx | 2 +- .../automatic-account-linking.mdx | 45 +++- .../manual-account-linking.mdx | 234 ++++++++++++++++-- .../saml/with-boxyhq/integration-steps.mdx | 2 +- .../tenant-management/overview.mdx | 2 +- .../tenant-management/overview.mdx | 2 +- .../tenant-management/overview.mdx | 2 +- 20 files changed, 776 insertions(+), 89 deletions(-) diff --git a/v2/emailpassword/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx b/v2/emailpassword/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx index c0fe4e604..32c5447bd 100644 --- a/v2/emailpassword/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx +++ b/v2/emailpassword/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx @@ -16,7 +16,7 @@ Once the dashboard recipe is initialised, the tenant management should be availa :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. ::: diff --git a/v2/emailpassword/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx b/v2/emailpassword/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx index c0fe4e604..32c5447bd 100644 --- a/v2/emailpassword/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx +++ b/v2/emailpassword/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx @@ -16,7 +16,7 @@ Once the dashboard recipe is initialised, the tenant management should be availa :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. ::: diff --git a/v2/passwordless/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx b/v2/passwordless/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx index c0fe4e604..32c5447bd 100644 --- a/v2/passwordless/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx +++ b/v2/passwordless/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx @@ -16,7 +16,7 @@ Once the dashboard recipe is initialised, the tenant management should be availa :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. ::: diff --git a/v2/passwordless/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx b/v2/passwordless/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx index c0fe4e604..32c5447bd 100644 --- a/v2/passwordless/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx +++ b/v2/passwordless/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx @@ -16,7 +16,7 @@ Once the dashboard recipe is initialised, the tenant management should be availa :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. ::: diff --git a/v2/thirdparty/common-customizations/account-linking/automatic-account-linking.mdx b/v2/thirdparty/common-customizations/account-linking/automatic-account-linking.mdx index c4651bf62..74785918e 100644 --- a/v2/thirdparty/common-customizations/account-linking/automatic-account-linking.mdx +++ b/v2/thirdparty/common-customizations/account-linking/automatic-account-linking.mdx @@ -84,9 +84,48 @@ Coming Soon -:::note -Coming Soon -::: +```python +from supertokens_python import init, InputAppInfo, SupertokensConfig +from supertokens_python.recipe import accountlinking +from supertokens_python.types import User +from supertokens_python.recipe.session.interfaces import SessionContainer +from supertokens_python.recipe.accountlinking.types import AccountInfoWithRecipeIdAndUserId, ShouldNotAutomaticallyLink, ShouldAutomaticallyLink +from typing import Dict, Any, Optional, Union + +async def should_do_automatic_account_linking( + new_account_info: AccountInfoWithRecipeIdAndUserId, + user: Optional[User], + session: Optional[SessionContainer], + tenant_id: str, + user_context: Dict[str, Any] +) -> Union[ShouldNotAutomaticallyLink, ShouldAutomaticallyLink]: + if session is not None: + return ShouldNotAutomaticallyLink() + + if new_account_info.recipe_user_id is not None and user is not None: + _user_id = new_account_info.recipe_user_id.get_as_string() + has_info_associated_with_user_id = False # TODO: add your own implementation here. + if has_info_associated_with_user_id: + return ShouldNotAutomaticallyLink() + + return ShouldAutomaticallyLink(should_require_verification=True) + + +init( + app_info=InputAppInfo( + app_name="...", + api_domain="...", + website_domain="...", + ), + supertokens_config=SupertokensConfig( + connection_uri="...", + ), + framework='...', # type: ignore + recipe_list=[ + accountlinking.init(should_do_automatic_account_linking=should_do_automatic_account_linking) + ], +) +``` diff --git a/v2/thirdparty/common-customizations/account-linking/manual-account-linking.mdx b/v2/thirdparty/common-customizations/account-linking/manual-account-linking.mdx index 23efb0e63..1efedbddc 100644 --- a/v2/thirdparty/common-customizations/account-linking/manual-account-linking.mdx +++ b/v2/thirdparty/common-customizations/account-linking/manual-account-linking.mdx @@ -10,6 +10,7 @@ hide_title: true import AccountLinkingPaidBanner from '../../../community/reusableMD/accountlinking/AccountLinkingPaidBanner.mdx' import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; import TabItem from '@theme/TabItem'; +import PythonSyncAsyncSubTabs from "/src/components/tabs/PythonSyncAsyncSubTabs"; @@ -43,13 +44,7 @@ supertokens.init({ }, recipeList: [ // highlight-start - AccountLinking.init({ - shouldDoAutomaticAccountLinking: async (newAccountInfo: AccountInfoWithRecipeId & { recipeUserId?: RecipeUserId }, user: User | undefined, session: SessionContainerInterface | undefined, tenantId: string, userContext: any) => { - return { - shouldAutomaticallyLink: false - } - } - }) + AccountLinking.init() // highlight-end ] }); @@ -65,9 +60,26 @@ Coming Soon -:::note -Coming Soon -::: +```python +from supertokens_python import init, InputAppInfo, SupertokensConfig +from supertokens_python.recipe import accountlinking + + +init( + app_info=InputAppInfo( + app_name="...", + api_domain="...", + website_domain="...", + ), + supertokens_config=SupertokensConfig( + connection_uri="...", + ), + framework='...', # type: ignore + recipe_list=[ + accountlinking.init() + ], +) +``` @@ -116,9 +128,62 @@ Coming Soon -:::note -Coming Soon -::: + + + +```python +from supertokens_python.recipe.accountlinking.asyncio import create_primary_user +from supertokens_python.types import RecipeUserId + +async def make_user_primary(recipe_user_id: RecipeUserId): + response = await create_primary_user(recipe_user_id) + if response.status == "OK": + if response.was_already_a_primary_user: + # The input user was already a primary user and accounts can be linked to it. + pass + else: + # User is now primary and accounts can be linked to it. + pass + modified_user = response.user + print(modified_user.is_primary_user) # will print True + elif response.status == "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if there already exists another primary user with the same email or phone number + # in at least one of the tenants that this user belongs to. + pass + elif response.status == "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR": + # This happens if this user is already linked to another primary user. + pass +``` + + + + +```python +from supertokens_python.recipe.accountlinking.syncio import create_primary_user +from supertokens_python.types import RecipeUserId + +def make_user_primary(recipe_user_id: RecipeUserId): + response = create_primary_user(recipe_user_id) + if response.status == "OK": + if response.was_already_a_primary_user: + # The input user was already a primary user and accounts can be linked to it. + pass + else: + # User is now primary and accounts can be linked to it. + pass + modified_user = response.user + print(modified_user.is_primary_user) # will print True + elif response.status == "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if there already exists another primary user with the same email or phone number + # in at least one of the tenants that this user belongs to. + pass + elif response.status == "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR": + # This happens if this user is already linked to another primary user. + pass +``` + + + @@ -168,9 +233,72 @@ Coming Soon -:::note -Coming Soon -::: + + + +```python +from supertokens_python.recipe.accountlinking.asyncio import link_accounts +from supertokens_python.types import RecipeUserId + +async def link_accounts_helper(primary_user_id: str, recipe_user_id: RecipeUserId): + response = await link_accounts(recipe_user_id, primary_user_id) + if response.status == "OK": + if response.accounts_already_linked: + # The input users were already linked + pass + else: + # The two users are now linked + pass + modified_user = response.user + print(modified_user.login_methods) # this will now contain the login method of the recipeUserId as well. + elif response.status == "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if there already exists another primary user with the same email or phone number + # as the recipeUserId's account. + pass + elif response.status == "INPUT_USER_IS_NOT_A_PRIMARY_USER": + # This happens if the input primaryUserId is not actually a primary user ID. + # You can call create_primary_user and call link_accounts again + pass + elif response.status == "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if the input recipe user ID is already linked to another primary user. + # You can call unlink_accounts on the recipe user ID and then try linking again. + pass +``` + + + + +```python +from supertokens_python.recipe.accountlinking.syncio import link_accounts +from supertokens_python.types import RecipeUserId + +def link_accounts_helper(primary_user_id: str, recipe_user_id: RecipeUserId): + response = link_accounts(recipe_user_id, primary_user_id) + if response.status == "OK": + if response.accounts_already_linked: + # The input users were already linked + pass + else: + # The two users are now linked + pass + modified_user = response.user + print(modified_user.login_methods) # this will now contain the login method of the recipeUserId as well. + elif response.status == "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if there already exists another primary user with the same email or phone number + # as the recipeUserId's account. + pass + elif response.status == "INPUT_USER_IS_NOT_A_PRIMARY_USER": + # This happens if the input primaryUserId is not actually a primary user ID. + # You can call create_primary_user and call link_accounts again + pass + elif response.status == "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if the input recipe user ID is already linked to another primary user. + # You can call unlink_accounts on the recipe user ID and then try linking again. + pass +``` + + + @@ -221,9 +349,68 @@ Coming Soon -:::note -Coming Soon -::: + + + +```python +from supertokens_python.recipe.accountlinking.asyncio import unlink_account +from supertokens_python.types import RecipeUserId + +async def unlink_account_helper(recipe_user_id: RecipeUserId): + response = await unlink_account(recipe_user_id) + if response.was_linked: + # This means that we unlinked the account from its primary user ID + pass + else: + # This means that the user was never linked in the first place + pass + + if response.was_recipe_user_deleted: + # This is true if we call unlink_account on the recipe user ID of the primary user ID user. + # We delete this user because if we don't and we call get_user_by_id() on this user's ID, SuperTokens + # won't know which user info to return - the primary user, or the recipe user. + # Note that even though the recipe user is deleted, the session, metadata, roles etc for this + # primary user is still intact, and calling get_user_by_id(primary_user_id) will still return + # the user object with the other login methods. + pass + else: + # There now exists a user account which is not a primary user, with the recipe_user_id equal to the + # input recipe_user_id. + pass +``` + + + + +```python +from supertokens_python.recipe.accountlinking.syncio import unlink_account +from supertokens_python.types import RecipeUserId + +def unlink_account_helper(recipe_user_id: RecipeUserId): + response = unlink_account(recipe_user_id) + if response.was_linked: + # This means that we unlinked the account from its primary user ID + pass + else: + # This means that the user was never linked in the first place + pass + + if response.was_recipe_user_deleted: + # This is true if we call unlink_account on the recipe user ID of the primary user ID user. + # We delete this user because if we don't and we call get_user_by_id() on this user's ID, SuperTokens + # won't know which user info to return - the primary user, or the recipe user. + # Note that even though the recipe user is deleted, the session, metadata, roles etc for this + # primary user is still intact, and calling get_user_by_id(primary_user_id) will still return + # the user object with the other login methods. + pass + else: + # There now exists a user account which is not a primary user, with the recipe_user_id equal to the + # input recipe_user_id. + pass +``` + + + @@ -252,9 +439,12 @@ Coming Soon -:::note -Coming Soon -::: +```python +from supertokens_python.types import RecipeUserId + +user_id = "some_user_id"; +recipe_user_id = RecipeUserId(user_id) +``` diff --git a/v2/thirdparty/common-customizations/saml/with-boxyhq/integration-steps.mdx b/v2/thirdparty/common-customizations/saml/with-boxyhq/integration-steps.mdx index 3b0c42dda..c1fdabbbd 100644 --- a/v2/thirdparty/common-customizations/saml/with-boxyhq/integration-steps.mdx +++ b/v2/thirdparty/common-customizations/saml/with-boxyhq/integration-steps.mdx @@ -23,7 +23,7 @@ import CoreInjector from "/src/components/coreInjector" :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. ::: diff --git a/v2/thirdparty/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx b/v2/thirdparty/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx index c0fe4e604..32c5447bd 100644 --- a/v2/thirdparty/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx +++ b/v2/thirdparty/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx @@ -16,7 +16,7 @@ Once the dashboard recipe is initialised, the tenant management should be availa :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. ::: diff --git a/v2/thirdparty/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx b/v2/thirdparty/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx index c0fe4e604..32c5447bd 100644 --- a/v2/thirdparty/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx +++ b/v2/thirdparty/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx @@ -16,7 +16,7 @@ Once the dashboard recipe is initialised, the tenant management should be availa :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. ::: diff --git a/v2/thirdpartyemailpassword/common-customizations/account-linking/automatic-account-linking.mdx b/v2/thirdpartyemailpassword/common-customizations/account-linking/automatic-account-linking.mdx index 66928222e..c51d114c7 100644 --- a/v2/thirdpartyemailpassword/common-customizations/account-linking/automatic-account-linking.mdx +++ b/v2/thirdpartyemailpassword/common-customizations/account-linking/automatic-account-linking.mdx @@ -84,9 +84,48 @@ Coming Soon -:::note -Coming Soon -::: +```python +from supertokens_python import init, InputAppInfo, SupertokensConfig +from supertokens_python.recipe import accountlinking +from supertokens_python.types import User +from supertokens_python.recipe.session.interfaces import SessionContainer +from supertokens_python.recipe.accountlinking.types import AccountInfoWithRecipeIdAndUserId, ShouldNotAutomaticallyLink, ShouldAutomaticallyLink +from typing import Dict, Any, Optional, Union + +async def should_do_automatic_account_linking( + new_account_info: AccountInfoWithRecipeIdAndUserId, + user: Optional[User], + session: Optional[SessionContainer], + tenant_id: str, + user_context: Dict[str, Any] +) -> Union[ShouldNotAutomaticallyLink, ShouldAutomaticallyLink]: + if session is not None: + return ShouldNotAutomaticallyLink() + + if new_account_info.recipe_user_id is not None and user is not None: + _user_id = new_account_info.recipe_user_id.get_as_string() + has_info_associated_with_user_id = False # TODO: add your own implementation here. + if has_info_associated_with_user_id: + return ShouldNotAutomaticallyLink() + + return ShouldAutomaticallyLink(should_require_verification=True) + + +init( + app_info=InputAppInfo( + app_name="...", + api_domain="...", + website_domain="...", + ), + supertokens_config=SupertokensConfig( + connection_uri="...", + ), + framework='...', # type: ignore + recipe_list=[ + accountlinking.init(should_do_automatic_account_linking=should_do_automatic_account_linking) + ], +) +``` diff --git a/v2/thirdpartyemailpassword/common-customizations/account-linking/manual-account-linking.mdx b/v2/thirdpartyemailpassword/common-customizations/account-linking/manual-account-linking.mdx index b73408c8a..e0e20ec04 100644 --- a/v2/thirdpartyemailpassword/common-customizations/account-linking/manual-account-linking.mdx +++ b/v2/thirdpartyemailpassword/common-customizations/account-linking/manual-account-linking.mdx @@ -10,6 +10,7 @@ hide_title: true import AccountLinkingPaidBanner from '../../../community/reusableMD/accountlinking/AccountLinkingPaidBanner.mdx' import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; import TabItem from '@theme/TabItem'; +import PythonSyncAsyncSubTabs from "/src/components/tabs/PythonSyncAsyncSubTabs"; @@ -43,13 +44,7 @@ supertokens.init({ }, recipeList: [ // highlight-start - AccountLinking.init({ - shouldDoAutomaticAccountLinking: async (newAccountInfo: AccountInfoWithRecipeId & { recipeUserId?: RecipeUserId }, user: User | undefined, session: SessionContainerInterface | undefined, tenantId: string, userContext: any) => { - return { - shouldAutomaticallyLink: false - } - } - }) + AccountLinking.init() // highlight-end ] }); @@ -65,9 +60,26 @@ Coming Soon -:::note -Coming Soon -::: +```python +from supertokens_python import init, InputAppInfo, SupertokensConfig +from supertokens_python.recipe import accountlinking + + +init( + app_info=InputAppInfo( + app_name="...", + api_domain="...", + website_domain="...", + ), + supertokens_config=SupertokensConfig( + connection_uri="...", + ), + framework='...', # type: ignore + recipe_list=[ + accountlinking.init() + ], +) +``` @@ -116,9 +128,62 @@ Coming Soon -:::note -Coming Soon -::: + + + +```python +from supertokens_python.recipe.accountlinking.asyncio import create_primary_user +from supertokens_python.types import RecipeUserId + +async def make_user_primary(recipe_user_id: RecipeUserId): + response = await create_primary_user(recipe_user_id) + if response.status == "OK": + if response.was_already_a_primary_user: + # The input user was already a primary user and accounts can be linked to it. + pass + else: + # User is now primary and accounts can be linked to it. + pass + modified_user = response.user + print(modified_user.is_primary_user) # will print True + elif response.status == "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if there already exists another primary user with the same email or phone number + # in at least one of the tenants that this user belongs to. + pass + elif response.status == "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR": + # This happens if this user is already linked to another primary user. + pass +``` + + + + +```python +from supertokens_python.recipe.accountlinking.syncio import create_primary_user +from supertokens_python.types import RecipeUserId + +def make_user_primary(recipe_user_id: RecipeUserId): + response = create_primary_user(recipe_user_id) + if response.status == "OK": + if response.was_already_a_primary_user: + # The input user was already a primary user and accounts can be linked to it. + pass + else: + # User is now primary and accounts can be linked to it. + pass + modified_user = response.user + print(modified_user.is_primary_user) # will print True + elif response.status == "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if there already exists another primary user with the same email or phone number + # in at least one of the tenants that this user belongs to. + pass + elif response.status == "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR": + # This happens if this user is already linked to another primary user. + pass +``` + + + @@ -168,9 +233,72 @@ Coming Soon -:::note -Coming Soon -::: + + + +```python +from supertokens_python.recipe.accountlinking.asyncio import link_accounts +from supertokens_python.types import RecipeUserId + +async def link_accounts_helper(primary_user_id: str, recipe_user_id: RecipeUserId): + response = await link_accounts(recipe_user_id, primary_user_id) + if response.status == "OK": + if response.accounts_already_linked: + # The input users were already linked + pass + else: + # The two users are now linked + pass + modified_user = response.user + print(modified_user.login_methods) # this will now contain the login method of the recipeUserId as well. + elif response.status == "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if there already exists another primary user with the same email or phone number + # as the recipeUserId's account. + pass + elif response.status == "INPUT_USER_IS_NOT_A_PRIMARY_USER": + # This happens if the input primaryUserId is not actually a primary user ID. + # You can call create_primary_user and call link_accounts again + pass + elif response.status == "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if the input recipe user ID is already linked to another primary user. + # You can call unlink_accounts on the recipe user ID and then try linking again. + pass +``` + + + + +```python +from supertokens_python.recipe.accountlinking.syncio import link_accounts +from supertokens_python.types import RecipeUserId + +def link_accounts_helper(primary_user_id: str, recipe_user_id: RecipeUserId): + response = link_accounts(recipe_user_id, primary_user_id) + if response.status == "OK": + if response.accounts_already_linked: + # The input users were already linked + pass + else: + # The two users are now linked + pass + modified_user = response.user + print(modified_user.login_methods) # this will now contain the login method of the recipeUserId as well. + elif response.status == "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if there already exists another primary user with the same email or phone number + # as the recipeUserId's account. + pass + elif response.status == "INPUT_USER_IS_NOT_A_PRIMARY_USER": + # This happens if the input primaryUserId is not actually a primary user ID. + # You can call create_primary_user and call link_accounts again + pass + elif response.status == "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if the input recipe user ID is already linked to another primary user. + # You can call unlink_accounts on the recipe user ID and then try linking again. + pass +``` + + + @@ -221,9 +349,68 @@ Coming Soon -:::note -Coming Soon -::: + + + +```python +from supertokens_python.recipe.accountlinking.asyncio import unlink_account +from supertokens_python.types import RecipeUserId + +async def unlink_account_helper(recipe_user_id: RecipeUserId): + response = await unlink_account(recipe_user_id) + if response.was_linked: + # This means that we unlinked the account from its primary user ID + pass + else: + # This means that the user was never linked in the first place + pass + + if response.was_recipe_user_deleted: + # This is true if we call unlink_account on the recipe user ID of the primary user ID user. + # We delete this user because if we don't and we call get_user_by_id() on this user's ID, SuperTokens + # won't know which user info to return - the primary user, or the recipe user. + # Note that even though the recipe user is deleted, the session, metadata, roles etc for this + # primary user is still intact, and calling get_user_by_id(primary_user_id) will still return + # the user object with the other login methods. + pass + else: + # There now exists a user account which is not a primary user, with the recipe_user_id equal to the + # input recipe_user_id. + pass +``` + + + + +```python +from supertokens_python.recipe.accountlinking.syncio import unlink_account +from supertokens_python.types import RecipeUserId + +def unlink_account_helper(recipe_user_id: RecipeUserId): + response = unlink_account(recipe_user_id) + if response.was_linked: + # This means that we unlinked the account from its primary user ID + pass + else: + # This means that the user was never linked in the first place + pass + + if response.was_recipe_user_deleted: + # This is true if we call unlink_account on the recipe user ID of the primary user ID user. + # We delete this user because if we don't and we call get_user_by_id() on this user's ID, SuperTokens + # won't know which user info to return - the primary user, or the recipe user. + # Note that even though the recipe user is deleted, the session, metadata, roles etc for this + # primary user is still intact, and calling get_user_by_id(primary_user_id) will still return + # the user object with the other login methods. + pass + else: + # There now exists a user account which is not a primary user, with the recipe_user_id equal to the + # input recipe_user_id. + pass +``` + + + @@ -252,9 +439,12 @@ Coming Soon -:::note -Coming Soon -::: +```python +from supertokens_python.types import RecipeUserId + +user_id = "some_user_id"; +recipe_user_id = RecipeUserId(user_id) +``` diff --git a/v2/thirdpartyemailpassword/common-customizations/saml/with-boxyhq/integration-steps.mdx b/v2/thirdpartyemailpassword/common-customizations/saml/with-boxyhq/integration-steps.mdx index 5fdffecab..d39b92cde 100644 --- a/v2/thirdpartyemailpassword/common-customizations/saml/with-boxyhq/integration-steps.mdx +++ b/v2/thirdpartyemailpassword/common-customizations/saml/with-boxyhq/integration-steps.mdx @@ -23,7 +23,7 @@ import CoreInjector from "/src/components/coreInjector" :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. ::: diff --git a/v2/thirdpartyemailpassword/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx b/v2/thirdpartyemailpassword/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx index c0fe4e604..32c5447bd 100644 --- a/v2/thirdpartyemailpassword/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx +++ b/v2/thirdpartyemailpassword/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx @@ -16,7 +16,7 @@ Once the dashboard recipe is initialised, the tenant management should be availa :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. ::: diff --git a/v2/thirdpartyemailpassword/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx b/v2/thirdpartyemailpassword/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx index c0fe4e604..32c5447bd 100644 --- a/v2/thirdpartyemailpassword/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx +++ b/v2/thirdpartyemailpassword/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx @@ -16,7 +16,7 @@ Once the dashboard recipe is initialised, the tenant management should be availa :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. ::: diff --git a/v2/thirdpartypasswordless/common-customizations/account-linking/automatic-account-linking.mdx b/v2/thirdpartypasswordless/common-customizations/account-linking/automatic-account-linking.mdx index c4651bf62..74785918e 100644 --- a/v2/thirdpartypasswordless/common-customizations/account-linking/automatic-account-linking.mdx +++ b/v2/thirdpartypasswordless/common-customizations/account-linking/automatic-account-linking.mdx @@ -84,9 +84,48 @@ Coming Soon -:::note -Coming Soon -::: +```python +from supertokens_python import init, InputAppInfo, SupertokensConfig +from supertokens_python.recipe import accountlinking +from supertokens_python.types import User +from supertokens_python.recipe.session.interfaces import SessionContainer +from supertokens_python.recipe.accountlinking.types import AccountInfoWithRecipeIdAndUserId, ShouldNotAutomaticallyLink, ShouldAutomaticallyLink +from typing import Dict, Any, Optional, Union + +async def should_do_automatic_account_linking( + new_account_info: AccountInfoWithRecipeIdAndUserId, + user: Optional[User], + session: Optional[SessionContainer], + tenant_id: str, + user_context: Dict[str, Any] +) -> Union[ShouldNotAutomaticallyLink, ShouldAutomaticallyLink]: + if session is not None: + return ShouldNotAutomaticallyLink() + + if new_account_info.recipe_user_id is not None and user is not None: + _user_id = new_account_info.recipe_user_id.get_as_string() + has_info_associated_with_user_id = False # TODO: add your own implementation here. + if has_info_associated_with_user_id: + return ShouldNotAutomaticallyLink() + + return ShouldAutomaticallyLink(should_require_verification=True) + + +init( + app_info=InputAppInfo( + app_name="...", + api_domain="...", + website_domain="...", + ), + supertokens_config=SupertokensConfig( + connection_uri="...", + ), + framework='...', # type: ignore + recipe_list=[ + accountlinking.init(should_do_automatic_account_linking=should_do_automatic_account_linking) + ], +) +``` diff --git a/v2/thirdpartypasswordless/common-customizations/account-linking/manual-account-linking.mdx b/v2/thirdpartypasswordless/common-customizations/account-linking/manual-account-linking.mdx index 23efb0e63..1efedbddc 100644 --- a/v2/thirdpartypasswordless/common-customizations/account-linking/manual-account-linking.mdx +++ b/v2/thirdpartypasswordless/common-customizations/account-linking/manual-account-linking.mdx @@ -10,6 +10,7 @@ hide_title: true import AccountLinkingPaidBanner from '../../../community/reusableMD/accountlinking/AccountLinkingPaidBanner.mdx' import BackendSDKTabs from "/src/components/tabs/BackendSDKTabs"; import TabItem from '@theme/TabItem'; +import PythonSyncAsyncSubTabs from "/src/components/tabs/PythonSyncAsyncSubTabs"; @@ -43,13 +44,7 @@ supertokens.init({ }, recipeList: [ // highlight-start - AccountLinking.init({ - shouldDoAutomaticAccountLinking: async (newAccountInfo: AccountInfoWithRecipeId & { recipeUserId?: RecipeUserId }, user: User | undefined, session: SessionContainerInterface | undefined, tenantId: string, userContext: any) => { - return { - shouldAutomaticallyLink: false - } - } - }) + AccountLinking.init() // highlight-end ] }); @@ -65,9 +60,26 @@ Coming Soon -:::note -Coming Soon -::: +```python +from supertokens_python import init, InputAppInfo, SupertokensConfig +from supertokens_python.recipe import accountlinking + + +init( + app_info=InputAppInfo( + app_name="...", + api_domain="...", + website_domain="...", + ), + supertokens_config=SupertokensConfig( + connection_uri="...", + ), + framework='...', # type: ignore + recipe_list=[ + accountlinking.init() + ], +) +``` @@ -116,9 +128,62 @@ Coming Soon -:::note -Coming Soon -::: + + + +```python +from supertokens_python.recipe.accountlinking.asyncio import create_primary_user +from supertokens_python.types import RecipeUserId + +async def make_user_primary(recipe_user_id: RecipeUserId): + response = await create_primary_user(recipe_user_id) + if response.status == "OK": + if response.was_already_a_primary_user: + # The input user was already a primary user and accounts can be linked to it. + pass + else: + # User is now primary and accounts can be linked to it. + pass + modified_user = response.user + print(modified_user.is_primary_user) # will print True + elif response.status == "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if there already exists another primary user with the same email or phone number + # in at least one of the tenants that this user belongs to. + pass + elif response.status == "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR": + # This happens if this user is already linked to another primary user. + pass +``` + + + + +```python +from supertokens_python.recipe.accountlinking.syncio import create_primary_user +from supertokens_python.types import RecipeUserId + +def make_user_primary(recipe_user_id: RecipeUserId): + response = create_primary_user(recipe_user_id) + if response.status == "OK": + if response.was_already_a_primary_user: + # The input user was already a primary user and accounts can be linked to it. + pass + else: + # User is now primary and accounts can be linked to it. + pass + modified_user = response.user + print(modified_user.is_primary_user) # will print True + elif response.status == "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if there already exists another primary user with the same email or phone number + # in at least one of the tenants that this user belongs to. + pass + elif response.status == "RECIPE_USER_ID_ALREADY_LINKED_WITH_PRIMARY_USER_ID_ERROR": + # This happens if this user is already linked to another primary user. + pass +``` + + + @@ -168,9 +233,72 @@ Coming Soon -:::note -Coming Soon -::: + + + +```python +from supertokens_python.recipe.accountlinking.asyncio import link_accounts +from supertokens_python.types import RecipeUserId + +async def link_accounts_helper(primary_user_id: str, recipe_user_id: RecipeUserId): + response = await link_accounts(recipe_user_id, primary_user_id) + if response.status == "OK": + if response.accounts_already_linked: + # The input users were already linked + pass + else: + # The two users are now linked + pass + modified_user = response.user + print(modified_user.login_methods) # this will now contain the login method of the recipeUserId as well. + elif response.status == "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if there already exists another primary user with the same email or phone number + # as the recipeUserId's account. + pass + elif response.status == "INPUT_USER_IS_NOT_A_PRIMARY_USER": + # This happens if the input primaryUserId is not actually a primary user ID. + # You can call create_primary_user and call link_accounts again + pass + elif response.status == "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if the input recipe user ID is already linked to another primary user. + # You can call unlink_accounts on the recipe user ID and then try linking again. + pass +``` + + + + +```python +from supertokens_python.recipe.accountlinking.syncio import link_accounts +from supertokens_python.types import RecipeUserId + +def link_accounts_helper(primary_user_id: str, recipe_user_id: RecipeUserId): + response = link_accounts(recipe_user_id, primary_user_id) + if response.status == "OK": + if response.accounts_already_linked: + # The input users were already linked + pass + else: + # The two users are now linked + pass + modified_user = response.user + print(modified_user.login_methods) # this will now contain the login method of the recipeUserId as well. + elif response.status == "ACCOUNT_INFO_ALREADY_ASSOCIATED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if there already exists another primary user with the same email or phone number + # as the recipeUserId's account. + pass + elif response.status == "INPUT_USER_IS_NOT_A_PRIMARY_USER": + # This happens if the input primaryUserId is not actually a primary user ID. + # You can call create_primary_user and call link_accounts again + pass + elif response.status == "RECIPE_USER_ID_ALREADY_LINKED_WITH_ANOTHER_PRIMARY_USER_ID_ERROR": + # This happens if the input recipe user ID is already linked to another primary user. + # You can call unlink_accounts on the recipe user ID and then try linking again. + pass +``` + + + @@ -221,9 +349,68 @@ Coming Soon -:::note -Coming Soon -::: + + + +```python +from supertokens_python.recipe.accountlinking.asyncio import unlink_account +from supertokens_python.types import RecipeUserId + +async def unlink_account_helper(recipe_user_id: RecipeUserId): + response = await unlink_account(recipe_user_id) + if response.was_linked: + # This means that we unlinked the account from its primary user ID + pass + else: + # This means that the user was never linked in the first place + pass + + if response.was_recipe_user_deleted: + # This is true if we call unlink_account on the recipe user ID of the primary user ID user. + # We delete this user because if we don't and we call get_user_by_id() on this user's ID, SuperTokens + # won't know which user info to return - the primary user, or the recipe user. + # Note that even though the recipe user is deleted, the session, metadata, roles etc for this + # primary user is still intact, and calling get_user_by_id(primary_user_id) will still return + # the user object with the other login methods. + pass + else: + # There now exists a user account which is not a primary user, with the recipe_user_id equal to the + # input recipe_user_id. + pass +``` + + + + +```python +from supertokens_python.recipe.accountlinking.syncio import unlink_account +from supertokens_python.types import RecipeUserId + +def unlink_account_helper(recipe_user_id: RecipeUserId): + response = unlink_account(recipe_user_id) + if response.was_linked: + # This means that we unlinked the account from its primary user ID + pass + else: + # This means that the user was never linked in the first place + pass + + if response.was_recipe_user_deleted: + # This is true if we call unlink_account on the recipe user ID of the primary user ID user. + # We delete this user because if we don't and we call get_user_by_id() on this user's ID, SuperTokens + # won't know which user info to return - the primary user, or the recipe user. + # Note that even though the recipe user is deleted, the session, metadata, roles etc for this + # primary user is still intact, and calling get_user_by_id(primary_user_id) will still return + # the user object with the other login methods. + pass + else: + # There now exists a user account which is not a primary user, with the recipe_user_id equal to the + # input recipe_user_id. + pass +``` + + + @@ -252,9 +439,12 @@ Coming Soon -:::note -Coming Soon -::: +```python +from supertokens_python.types import RecipeUserId + +user_id = "some_user_id"; +recipe_user_id = RecipeUserId(user_id) +``` diff --git a/v2/thirdpartypasswordless/common-customizations/saml/with-boxyhq/integration-steps.mdx b/v2/thirdpartypasswordless/common-customizations/saml/with-boxyhq/integration-steps.mdx index 3b0c42dda..c1fdabbbd 100644 --- a/v2/thirdpartypasswordless/common-customizations/saml/with-boxyhq/integration-steps.mdx +++ b/v2/thirdpartypasswordless/common-customizations/saml/with-boxyhq/integration-steps.mdx @@ -23,7 +23,7 @@ import CoreInjector from "/src/components/coreInjector" :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. ::: diff --git a/v2/thirdpartypasswordless/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx b/v2/thirdpartypasswordless/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx index c0fe4e604..32c5447bd 100644 --- a/v2/thirdpartypasswordless/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx +++ b/v2/thirdpartypasswordless/custom-ui/init/user-management-dashboard/tenant-management/overview.mdx @@ -16,7 +16,7 @@ Once the dashboard recipe is initialised, the tenant management should be availa :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. ::: diff --git a/v2/thirdpartypasswordless/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx b/v2/thirdpartypasswordless/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx index c0fe4e604..32c5447bd 100644 --- a/v2/thirdpartypasswordless/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx +++ b/v2/thirdpartypasswordless/pre-built-ui/setup/user-management-dashboard/tenant-management/overview.mdx @@ -16,7 +16,7 @@ Once the dashboard recipe is initialised, the tenant management should be availa :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. ::: diff --git a/v2/userdashboard/tenant-management/overview.mdx b/v2/userdashboard/tenant-management/overview.mdx index c0fe4e604..32c5447bd 100644 --- a/v2/userdashboard/tenant-management/overview.mdx +++ b/v2/userdashboard/tenant-management/overview.mdx @@ -16,7 +16,7 @@ Once the dashboard recipe is initialised, the tenant management should be availa :::caution -Currently this is only available with the Node SDK version >= 20.0.1 and will be available for python and golang SDKs soon. +Currently, this is only available with our Node and Python SDKs. :::