diff --git a/tests/test-server/accountlinking.py b/tests/test-server/accountlinking.py index 8a17e40b..92fb0b33 100644 --- a/tests/test-server/accountlinking.py +++ b/tests/test-server/accountlinking.py @@ -29,256 +29,235 @@ from supertokens_python.recipe.thirdparty.types import ThirdPartyInfo from supertokens_python.types import User from utils import serialize_user # pylint: disable=import-error +from session import convert_session_to_container def add_accountlinking_routes(app: Flask): @app.route("/test/accountlinking/createprimaryuser", methods=["POST"]) # type: ignore def create_primary_user_api(): # type: ignore - try: - assert request.json is not None - recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) - response = create_primary_user( - recipe_user_id, request.json.get("userContext") + assert request.json is not None + recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) + response = create_primary_user(recipe_user_id, request.json.get("userContext")) + if isinstance(response, CreatePrimaryUserOkResult): + return jsonify( + { + "status": "OK", + **serialize_user( + response.user, request.headers.get("fdi-version", "") + ), + "wasAlreadyAPrimaryUser": response.was_already_a_primary_user, + } + ) + elif isinstance(response, CreatePrimaryUserRecipeUserIdAlreadyLinkedError): + return jsonify( + { + "description": response.description, + "primaryUserId": response.primary_user_id, + "status": response.status, + } + ) + elif isinstance(response, CreatePrimaryUserRecipeUserIdAlreadyLinkedError): + return jsonify( + { + "description": response.description, + "primaryUserId": response.primary_user_id, + "status": response.status, + } + ) + else: + return jsonify( + { + "description": response.description, + "primaryUserId": response.primary_user_id, + "status": response.status, + } ) - if isinstance(response, CreatePrimaryUserOkResult): - return jsonify( - { - "status": "OK", - **serialize_user( - response.user, request.headers.get("fdi-version", "") - ), - "wasAlreadyAPrimaryUser": response.was_already_a_primary_user, - } - ) - elif isinstance(response, CreatePrimaryUserRecipeUserIdAlreadyLinkedError): - return jsonify( - { - "description": response.description, - "primaryUserId": response.primary_user_id, - "status": response.status, - } - ) - elif isinstance(response, CreatePrimaryUserRecipeUserIdAlreadyLinkedError): - return jsonify( - { - "description": response.description, - "primaryUserId": response.primary_user_id, - "status": response.status, - } - ) - else: - return jsonify( - { - "description": response.description, - "primaryUserId": response.primary_user_id, - "status": response.status, - } - ) - except Exception as e: - return jsonify({"error": str(e)}), 500 @app.route("/test/accountlinking/linkaccounts", methods=["POST"]) # type: ignore def link_accounts_api(): # type: ignore - try: - assert request.json is not None - recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) - response = link_accounts( - recipe_user_id, - request.json["primaryUserId"], - request.json.get("userContext"), + assert request.json is not None + recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) + response = link_accounts( + recipe_user_id, + request.json["primaryUserId"], + request.json.get("userContext"), + ) + if isinstance(response, LinkAccountsOkResult): + return jsonify( + { + "status": "OK", + **serialize_user( + response.user, request.headers.get("fdi-version", "") + ), + "accountsAlreadyLinked": response.accounts_already_linked, + } ) - if isinstance(response, LinkAccountsOkResult): - return jsonify( - { - "status": "OK", - **serialize_user( - response.user, request.headers.get("fdi-version", "") - ), - "accountsAlreadyLinked": response.accounts_already_linked, - } - ) - elif isinstance(response, LinkAccountsRecipeUserIdAlreadyLinkedError): - return jsonify( - { - "description": response.description, - "primaryUserId": response.primary_user_id, - "status": response.status, - **serialize_user( - response.user, request.headers.get("fdi-version", "") - ), - } - ) - elif isinstance(response, LinkAccountsAccountInfoAlreadyAssociatedError): - return jsonify( - { - "description": response.description, - "primaryUserId": response.primary_user_id, - "status": response.status, - } - ) - else: - return jsonify( - { - "description": response.description, - "status": response.status, - } - ) - except Exception as e: - return jsonify({"error": str(e)}), 500 - - @app.route("/test/accountlinking/isemailchangeallowed", methods=["POST"]) # type: ignore - def is_email_change_allowed_api(): # type: ignore - try: - assert request.json is not None - recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) - response = is_email_change_allowed( - recipe_user_id, - request.json["newEmail"], - request.json["isVerified"], - request.json["session"], - request.json.get("userContext"), + elif isinstance(response, LinkAccountsRecipeUserIdAlreadyLinkedError): + return jsonify( + { + "description": response.description, + "primaryUserId": response.primary_user_id, + "status": response.status, + **serialize_user( + response.user, request.headers.get("fdi-version", "") + ), + } ) - return jsonify(response) - except Exception as e: - return jsonify({"error": str(e)}), 500 - - @app.route("/test/accountlinking/unlinkaccount", methods=["POST"]) # type: ignore - def unlink_account_api(): # type: ignore - try: - assert request.json is not None - recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) - response = unlink_account( - recipe_user_id, - request.json.get("userContext"), + elif isinstance(response, LinkAccountsAccountInfoAlreadyAssociatedError): + return jsonify( + { + "description": response.description, + "primaryUserId": response.primary_user_id, + "status": response.status, + } ) + else: return jsonify( { + "description": response.description, "status": response.status, - "wasRecipeUserDeleted": response.was_recipe_user_deleted, - "wasLinked": response.was_linked, } ) - except Exception as e: - return jsonify({"error": str(e)}), 500 + + @app.route("/test/accountlinking/isemailchangeallowed", methods=["POST"]) # type: ignore + def is_email_change_allowed_api(): # type: ignore + assert request.json is not None + recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) + session = None + if "session" in request.json: + session = convert_session_to_container(request) + response = is_email_change_allowed( + recipe_user_id, + request.json["newEmail"], + request.json["isVerified"], + session, + request.json.get("userContext"), + ) + return jsonify(response) + + @app.route("/test/accountlinking/unlinkaccount", methods=["POST"]) # type: ignore + def unlink_account_api(): # type: ignore + assert request.json is not None + recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) + response = unlink_account( + recipe_user_id, + request.json.get("userContext"), + ) + return jsonify( + { + "status": response.status, + "wasRecipeUserDeleted": response.was_recipe_user_deleted, + "wasLinked": response.was_linked, + } + ) @app.route("/test/accountlinking/createprimaryuseridorlinkaccounts", methods=["POST"]) # type: ignore def create_primary_user_id_or_link_accounts_api(): # type: ignore - try: - assert request.json is not None - recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) - response = create_primary_user_id_or_link_accounts( - request.json["tenantId"], - recipe_user_id, - request.json.get("session", None), - request.json.get("userContext", None), - ) - return jsonify(response.to_json()) - except Exception as e: - return jsonify({"error": str(e)}), 500 + assert request.json is not None + recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) + session = None + if "session" in request.json: + session = convert_session_to_container(request) + response = create_primary_user_id_or_link_accounts( + request.json["tenantId"], + recipe_user_id, + session, + request.json.get("userContext", None), + ) + return jsonify(response.to_json()) @app.route("/test/accountlinking/getprimaryuserthatcanbelinkedtorecipeuserid", methods=["POST"]) # type: ignore def get_primary_user_that_can_be_linked_to_recipe_user_id_api(): # type: ignore - try: - assert request.json is not None - recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) - response = get_primary_user_that_can_be_linked_to_recipe_user_id( - request.json["tenantId"], - recipe_user_id, - request.json.get("userContext", None), - ) - return jsonify(response.to_json() if response else None) - except Exception as e: - return jsonify({"error": str(e)}), 500 + assert request.json is not None + recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) + response = get_primary_user_that_can_be_linked_to_recipe_user_id( + request.json["tenantId"], + recipe_user_id, + request.json.get("userContext", None), + ) + return jsonify(response.to_json() if response else None) @app.route("/test/accountlinking/issignupallowed", methods=["POST"]) # type: ignore def is_signup_allowed_api(): # type: ignore - try: - assert request.json is not None - response = is_sign_up_allowed( - request.json["tenantId"], - AccountInfoWithRecipeId( - recipe_id=request.json["newUser"]["recipeId"], - email=request.json["newUser"]["email"], - phone_number=request.json["newUser"]["phoneNumber"], - third_party=ThirdPartyInfo( - third_party_user_id=request.json["newUser"]["thirdParty"]["id"], - third_party_id=request.json["newUser"]["thirdParty"][ - "thirdPartyId" - ], - ), + assert request.json is not None + session = None + if "session" in request.json: + session = convert_session_to_container(request) + response = is_sign_up_allowed( + request.json["tenantId"], + AccountInfoWithRecipeId( + recipe_id=request.json["newUser"]["recipeId"], + email=request.json["newUser"]["email"], + phone_number=request.json["newUser"]["phoneNumber"], + third_party=ThirdPartyInfo( + third_party_user_id=request.json["newUser"]["thirdParty"]["id"], + third_party_id=request.json["newUser"]["thirdParty"][ + "thirdPartyId" + ], ), - request.json["isVerified"], - request.json.get("session", None), - request.json.get("userContext", None), - ) - return jsonify(response) - except Exception as e: - return jsonify({"error": str(e)}), 500 + ), + request.json["isVerified"], + session, + request.json.get("userContext", None), + ) + return jsonify(response) @app.route("/test/accountlinking/issigninallowed", methods=["POST"]) # type: ignore def is_signin_allowed_api(): # type: ignore - try: - assert request.json is not None - recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) - response = is_sign_in_allowed( - request.json["tenantId"], - recipe_user_id, - request.json.get("session", None), - request.json.get("userContext", None), - ) - return jsonify(response) - except Exception as e: - return jsonify({"error": str(e)}), 500 + assert request.json is not None + recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) + session = None + if "session" in request.json: + session = convert_session_to_container(request) + response = is_sign_in_allowed( + request.json["tenantId"], + recipe_user_id, + session, + request.json.get("userContext", None), + ) + return jsonify(response) @app.route("/test/accountlinking/verifyemailforrecipeuseriflinkedaccountsareverified", methods=["POST"]) # type: ignore def verify_email_for_recipe_user_if_linked_accounts_are_verified_api(): # type: ignore - try: - assert request.json is not None - recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) - user = User.from_json(request.json["user"]) - async_to_sync_wrapper.sync( - AccountLinkingRecipe.get_instance().verify_email_for_recipe_user_if_linked_accounts_are_verified( - user=user, - recipe_user_id=recipe_user_id, - user_context=request.json.get("userContext"), - ) + assert request.json is not None + recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) + user = User.from_json(request.json["user"]) + async_to_sync_wrapper.sync( + AccountLinkingRecipe.get_instance().verify_email_for_recipe_user_if_linked_accounts_are_verified( + user=user, + recipe_user_id=recipe_user_id, + user_context=request.json.get("userContext"), ) - return jsonify({}) - except Exception as e: - return jsonify({"error": str(e)}), 500 + ) + return jsonify({}) @app.route("/test/accountlinking/cancreateprimaryuser", methods=["POST"]) # type: ignore def can_create_primary_user_api(): # type: ignore - try: - assert request.json is not None - recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) - response = can_create_primary_user( - recipe_user_id, request.json.get("userContext") + assert request.json is not None + recipe_user_id = convert_to_recipe_user_id(request.json["recipeUserId"]) + response = can_create_primary_user( + recipe_user_id, request.json.get("userContext") + ) + if isinstance(response, CanCreatePrimaryUserOkResult): + return jsonify( + { + "status": response.status, + "wasAlreadyAPrimaryUser": response.was_already_a_primary_user, + } + ) + elif isinstance(response, CanCreatePrimaryUserRecipeUserIdAlreadyLinkedError): + return jsonify( + { + "description": response.description, + "primaryUserId": response.primary_user_id, + "status": response.status, + } + ) + else: + return jsonify( + { + "description": response.description, + "status": response.status, + "primaryUserId": response.primary_user_id, + } ) - if isinstance(response, CanCreatePrimaryUserOkResult): - return jsonify( - { - "status": response.status, - "wasAlreadyAPrimaryUser": response.was_already_a_primary_user, - } - ) - elif isinstance( - response, CanCreatePrimaryUserRecipeUserIdAlreadyLinkedError - ): - return jsonify( - { - "description": response.description, - "primaryUserId": response.primary_user_id, - "status": response.status, - } - ) - else: - return jsonify( - { - "description": response.description, - "status": response.status, - "primaryUserId": response.primary_user_id, - } - ) - except Exception as e: - return jsonify({"error": str(e)}), 500 diff --git a/tests/test-server/emailpassword.py b/tests/test-server/emailpassword.py index 9691fa21..55375185 100644 --- a/tests/test-server/emailpassword.py +++ b/tests/test-server/emailpassword.py @@ -10,6 +10,7 @@ ) import supertokens_python.recipe.emailpassword.syncio as emailpassword from session import convert_session_to_container # pylint: disable=import-error +from supertokens_python.types import RecipeUserId from utils import ( # pylint: disable=import-error serialize_user, serialize_recipe_user_id, @@ -26,9 +27,7 @@ def emailpassword_signup(): # type: ignore email = data["email"] password = data["password"] user_context = data.get("userContext") - session = ( - convert_session_to_container(data["session"]) if "session" in data else None - ) + session = convert_session_to_container(data) if "session" in data else None response = emailpassword.sign_up( tenant_id, email, password, session, user_context @@ -66,8 +65,11 @@ def emailpassword_signin(): # type: ignore email = data["email"] password = data["password"] user_context = data.get("userContext") + session = convert_session_to_container(data) if "session" in data else None - response = emailpassword.sign_in(tenant_id, email, password, user_context) + response = emailpassword.sign_in( + tenant_id, email, password, session, user_context + ) if isinstance(response, SignInOkResult): return jsonify( @@ -116,7 +118,7 @@ def emailpassword_update_email_or_password(): # type: ignore if data is None: return jsonify({"status": "MISSING_DATA_ERROR"}) - user_id = data["userId"] + recipe_user_id = RecipeUserId(data["recipeUserId"]) email = data.get("email") password = data.get("password") apply_password_policy = data.get("applyPasswordPolicy") @@ -124,7 +126,7 @@ def emailpassword_update_email_or_password(): # type: ignore user_context = data.get("userContext") response = emailpassword.update_email_or_password( - user_id, + recipe_user_id, email, password, apply_password_policy, @@ -139,7 +141,9 @@ def emailpassword_update_email_or_password(): # type: ignore elif isinstance(response, EmailAlreadyExistsError): return jsonify({"status": "EMAIL_ALREADY_EXISTS_ERROR"}) elif isinstance(response, UpdateEmailOrPasswordEmailChangeNotAllowedError): - return jsonify({"status": "EMAIL_CHANGE_NOT_ALLOWED_ERROR"}) + return jsonify( + {"status": "EMAIL_CHANGE_NOT_ALLOWED_ERROR", "reason": response.reason} + ) else: return jsonify( { diff --git a/tests/test-server/emailverification.py b/tests/test-server/emailverification.py index 9707ec24..791d394f 100644 --- a/tests/test-server/emailverification.py +++ b/tests/test-server/emailverification.py @@ -1,5 +1,7 @@ from flask import Flask, request, jsonify +from supertokens_python import async_to_sync_wrapper +from supertokens_python.framework.flask.flask_request import FlaskRequest from supertokens_python.recipe.emailverification.interfaces import ( CreateEmailVerificationTokenOkResult, VerifyEmailUsingTokenOkResult, @@ -10,6 +12,22 @@ def add_emailverification_routes(app: Flask): + @app.route("/test/emailverification/isemailverified", methods=["POST"]) # type: ignore + def is_email_verified_api(): # type: ignore + from supertokens_python import convert_to_recipe_user_id + from supertokens_python.recipe.emailverification.syncio import is_email_verified + + data = request.json + if data is None: + return jsonify({"status": "MISSING_DATA_ERROR"}) + + recipe_user_id = convert_to_recipe_user_id(data["recipeUserId"]) + email = data.get("email") + user_context = data.get("userContext", {}) + + response = is_email_verified(recipe_user_id, email, user_context) + return jsonify(response) + @app.route("/test/emailverification/createemailverificationtoken", methods=["POST"]) # type: ignore def f(): # type: ignore from supertokens_python import convert_to_recipe_user_id @@ -65,3 +83,51 @@ def f2(): # type: ignore ) else: return jsonify({"status": "EMAIL_VERIFICATION_INVALID_TOKEN_ERROR"}) + + @app.route("/test/emailverification/unverifyemail", methods=["POST"]) # type: ignore + def unverify_email(): # type: ignore + from supertokens_python.recipe.emailverification.syncio import unverify_email + from supertokens_python.types import RecipeUserId + + data = request.json + if data is None: + return jsonify({"status": "MISSING_DATA_ERROR"}) + + recipe_user_id = RecipeUserId(data["recipeUserId"]) + email = data.get("email") + user_context = data.get("userContext", {}) + + unverify_email(recipe_user_id, email, user_context) + return jsonify({"status": "OK"}) + + @app.route("/test/emailverification/updatesessionifrequiredpostemailverification", methods=["POST"]) # type: ignore + def update_session_if_required_post_email_verification(): # type: ignore + from supertokens_python.recipe.emailverification import EmailVerificationRecipe + from supertokens_python.types import RecipeUserId + from session import convert_session_to_container, convert_session_to_json + + data = request.json + if data is None: + return jsonify({"status": "MISSING_DATA_ERROR"}) + + recipe_user_id_whose_email_got_verified = RecipeUserId( + data["recipeUserIdWhoseEmailGotVerified"]["recipeUserId"] + ) + session = ( + convert_session_to_container(data["session"]) if "session" in data else None + ) + + try: + session_resp = async_to_sync_wrapper.sync( + EmailVerificationRecipe.get_instance_or_throw().update_session_if_required_post_email_verification( + recipe_user_id_whose_email_got_verified=recipe_user_id_whose_email_got_verified, + session=session, + req=FlaskRequest(request), + user_context=data.get("userContext", {}), + ) + ) + return jsonify( + None if session_resp is None else convert_session_to_json(session_resp) + ) + except Exception as e: + return jsonify({"status": "ERROR", "message": str(e)}), 500