Skip to content

Commit cef5435

Browse files
committed
update: servers to be consistent with auth-react
1 parent e753c37 commit cef5435

File tree

6 files changed

+323
-277
lines changed

6 files changed

+323
-277
lines changed

.github/workflows/auth-react-test.yml

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,6 @@ jobs:
8080
export PYTHONPATH="${PYTHONPATH}:$(pwd)"
8181
cd tests/auth-react/django3x
8282
83-
set -a
84-
source ../auth-react.env
85-
set +a
86-
8783
uvicorn mysite.asgi:application --port 8083 &
8884
8985
- name: Start Server (fastapi)
@@ -94,10 +90,6 @@ jobs:
9490
export PYTHONPATH="${PYTHONPATH}:$(pwd)"
9591
cd tests/auth-react/fastapi-server
9692
97-
set -a
98-
source ../auth-react.env
99-
set +a
100-
10193
uvicorn app:app --host 0.0.0.0 --port 8083 &
10294
10395
- name: Start Server (flask)
@@ -108,10 +100,6 @@ jobs:
108100
export PYTHONPATH="${PYTHONPATH}:$(pwd)"
109101
cd tests/auth-react/flask-server
110102
111-
set -a
112-
source ../auth-react.env
113-
set +a
114-
115103
python3 app.py --port 8083 &
116104
117105
- uses: supertokens/auth-react-testing-action@main

tests/auth-react/django3x/mysite/utils.py

Lines changed: 74 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
from typing import Any, Awaitable, Callable, Dict, List, Optional, Union
33

4+
import requests
45
from dotenv import load_dotenv
56
from supertokens_python import InputAppInfo, Supertokens, SupertokensConfig, init
67
from supertokens_python.framework.request import BaseRequest
@@ -85,7 +86,7 @@
8586

8687
from .store import save_code, save_url_with_token
8788

88-
load_dotenv()
89+
load_dotenv("../auth-react.env")
8990

9091

9192
def get_api_port():
@@ -296,8 +297,56 @@ async def exchange_auth_code_for_oauth_tokens(
296297
return oi
297298

298299

299-
def custom_init():
300-
import mysite.store
300+
def get_core_url():
301+
host = os.environ.get("SUPERTOKENS_CORE_HOST", "localhost")
302+
port = os.environ.get("SUPERTOKENS_CORE_PORT", "3567")
303+
304+
return f"http://localhost:{host}:{port}"
305+
306+
307+
def setup_core_app(
308+
*, appId: Optional[str] = None, coreConfig: Optional[Dict[str, Any]] = None
309+
):
310+
core_url = get_core_url()
311+
312+
if appId is None:
313+
appId = ""
314+
315+
if coreConfig is None:
316+
coreConfig = {}
317+
318+
response = requests.put(
319+
f"{core_url}/recipe/multitenancy/app/v2",
320+
headers={
321+
"Content-Type": "application/json",
322+
},
323+
data={
324+
"appId": appId,
325+
"coreConfig": coreConfig,
326+
},
327+
)
328+
329+
response_body = response.json()
330+
assert response_body["status"] == "OK"
331+
332+
return f"{core_url}/appid-{appId}"
333+
334+
335+
def custom_init(
336+
*,
337+
coreUrl: str = get_core_url(),
338+
accountLinkingConfig: Optional[Dict[str, Any]] = None,
339+
enabledRecipes: Optional[List[str]] = None,
340+
enabledProviders: Optional[List[str]] = None,
341+
passwordlessFlowType: Optional[str] = "USER_INPUT_CODE_AND_MAGIC_LINK",
342+
passwordlessContactMethod: Optional[str] = "EMAIL_OR_PHONE",
343+
mfaInfo: Optional[Dict[str, Any]] = None,
344+
):
345+
if accountLinkingConfig is None:
346+
accountLinkingConfig = {}
347+
348+
if mfaInfo is None:
349+
mfaInfo = {}
301350

302351
AccountLinkingRecipe.reset()
303352
UserRolesRecipe.reset()
@@ -706,27 +755,27 @@ async def resend_code_post(
706755
),
707756
]
708757

709-
if mysite.store.enabled_providers is not None:
758+
if enabledProviders is not None:
710759
providers_list = [
711760
provider
712761
for provider in providers_list
713-
if provider.config.third_party_id in mysite.store.enabled_providers
762+
if provider.config.third_party_id in enabledProviders
714763
]
715764

716-
if mysite.store.contact_method is not None and mysite.store.flow_type is not None:
717-
if mysite.store.contact_method == "PHONE":
765+
if passwordlessContactMethod is not None and passwordlessFlowType is not None:
766+
if passwordlessContactMethod == "PHONE":
718767
passwordless_init = passwordless.init(
719768
contact_config=ContactPhoneOnlyConfig(),
720-
flow_type=mysite.store.flow_type,
769+
flow_type=passwordlessFlowType, # type: ignore - type expects only certain literals
721770
sms_delivery=passwordless.SMSDeliveryConfig(CustomSMSService()),
722771
override=passwordless.InputOverrideConfig(
723772
apis=override_passwordless_apis
724773
),
725774
)
726-
elif mysite.store.contact_method == "EMAIL":
775+
elif passwordlessContactMethod == "EMAIL":
727776
passwordless_init = passwordless.init(
728777
contact_config=ContactEmailOnlyConfig(),
729-
flow_type=mysite.store.flow_type,
778+
flow_type=passwordlessFlowType, # type: ignore - type expects only certain literals
730779
email_delivery=passwordless.EmailDeliveryConfig(
731780
CustomPlessEmailService()
732781
),
@@ -737,7 +786,7 @@ async def resend_code_post(
737786
else:
738787
passwordless_init = passwordless.init(
739788
contact_config=ContactEmailOrPhoneConfig(),
740-
flow_type=mysite.store.flow_type,
789+
flow_type=passwordlessFlowType, # type: ignore - type expects only certain literals
741790
email_delivery=passwordless.EmailDeliveryConfig(
742791
CustomPlessEmailService()
743792
),
@@ -780,8 +829,8 @@ async def get_factors_setup_for_user(
780829
user_context: Dict[str, Any],
781830
):
782831
res = await og_get_factors_setup_for_user(user, user_context)
783-
if "alreadySetup" in mysite.store.mfa_info:
784-
return mysite.store.mfa_info["alreadySetup"]
832+
if "alreadySetup" in mfaInfo:
833+
return mfaInfo["alreadySetup"]
785834
return res
786835

787836
og_assert_allowed_to_setup_factor = original_implementation.assert_allowed_to_setup_factor_else_throw_invalid_claim_error
@@ -793,8 +842,8 @@ async def assert_allowed_to_setup_factor_else_throw_invalid_claim_error(
793842
factors_set_up_for_user: Callable[[], Awaitable[List[str]]],
794843
user_context: Dict[str, Any],
795844
):
796-
if "allowedToSetup" in mysite.store.mfa_info:
797-
if factor_id not in mysite.store.mfa_info["allowedToSetup"]:
845+
if "allowedToSetup" in mfaInfo:
846+
if factor_id not in mfaInfo["allowedToSetup"]:
798847
raise InvalidClaimsError(
799848
msg="INVALID_CLAIMS",
800849
payload=[
@@ -834,8 +883,8 @@ async def get_mfa_requirements_for_auth(
834883
required_secondary_factors_for_tenant,
835884
user_context,
836885
)
837-
if "requirements" in mysite.store.mfa_info:
838-
return mysite.store.mfa_info["requirements"]
886+
if "requirements" in mfaInfo:
887+
return mfaInfo["requirements"]
839888
return res
840889

841890
original_implementation.get_mfa_requirements_for_auth = (
@@ -862,10 +911,10 @@ async def resync_session_and_fetch_mfa_info_put(
862911
)
863912

864913
if isinstance(res, ResyncSessionAndFetchMFAInfoPUTOkResult):
865-
if "alreadySetup" in mysite.store.mfa_info:
866-
res.factors.already_setup = mysite.store.mfa_info["alreadySetup"][:]
914+
if "alreadySetup" in mfaInfo:
915+
res.factors.already_setup = mfaInfo["alreadySetup"][:]
867916

868-
if "noContacts" in mysite.store.mfa_info:
917+
if "noContacts" in mfaInfo:
869918
res.emails = {}
870919
res.phone_numbers = {}
871920

@@ -926,7 +975,7 @@ async def resync_session_and_fetch_mfa_info_put(
926975
{
927976
"id": "multifactorauth",
928977
"init": multifactorauth.init(
929-
first_factors=mysite.store.mfa_info.get("firstFactors", None),
978+
first_factors=mfaInfo.get("firstFactors", None),
930979
override=multifactorauth.OverrideConfig(
931980
functions=override_mfa_functions,
932981
apis=override_mfa_apis,
@@ -954,7 +1003,7 @@ async def resync_session_and_fetch_mfa_info_put(
9541003
"shouldAutomaticallyLink": True,
9551004
"shouldRequireVerification": True,
9561005
},
957-
**mysite.store.accountlinking_config,
1006+
**accountLinkingConfig,
9581007
}
9591008

9601009
async def should_do_automatic_account_linking(
@@ -989,10 +1038,10 @@ async def should_do_automatic_account_linking(
9891038
}
9901039
)
9911040

992-
if mysite.store.enabled_recipes is not None:
1041+
if enabledRecipes is not None:
9931042
new_recipe_list = []
9941043
for item in recipe_list:
995-
for recipe_id in mysite.store.enabled_recipes:
1044+
for recipe_id in enabledRecipes:
9961045
if item["id"] in recipe_id:
9971046
new_recipe_list.append(item["init"]) # type: ignore
9981047
break
@@ -1003,7 +1052,7 @@ async def should_do_automatic_account_linking(
10031052
recipe_list = [item["init"] for item in recipe_list]
10041053

10051054
init(
1006-
supertokens_config=SupertokensConfig("http://localhost:9000"),
1055+
supertokens_config=SupertokensConfig(coreUrl),
10071056
app_info=InputAppInfo(
10081057
app_name="SuperTokens Demo",
10091058
api_domain="localhost:" + get_api_port(),

tests/auth-react/django3x/polls/urls.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,11 @@
1717
name="removeUserFromTenant",
1818
), # type: ignore
1919
path("addUserToTenant", views.add_user_to_tenant, name="addUserToTenant"), # type: ignore
20-
path("test/setFlow", views.test_set_flow, name="setFlow"), # type: ignore
21-
path(
22-
"test/setAccountLinkingConfig",
23-
views.test_set_account_linking_config, # type: ignore
24-
name="setAccountLinkingConfig",
25-
), # type: ignore
26-
path("setMFAInfo", views.set_mfa_info, name="setMfaInfo"), # type: ignore
2720
path(
2821
"addRequiredFactor",
2922
views.add_required_factor, # type: ignore
3023
name="addRequiredFactor",
3124
), # type: ignore
32-
path(
33-
"test/setEnabledRecipes",
34-
views.test_set_enabled_recipes, # type: ignore
35-
name="setEnabledRecipes",
36-
),
3725
path("test/getTOTPCode", views.test_get_totp_code, name="getTotpCode"), # type: ignore
3826
path(
3927
"test/create-oauth2-client",
@@ -42,7 +30,12 @@
4230
), # type: ignore
4331
path("test/getDevice", views.test_get_device, name="getDevice"), # type: ignore
4432
path("test/featureFlags", views.test_feature_flags, name="featureFlags"), # type: ignore
45-
path("beforeeach", views.before_each, name="beforeeach"), # type: ignore
33+
path("/test/before", views.before, name="before"),
34+
path("/test/beforeEach", views.before_each, name="beforeeach"),
35+
path("/test/after", views.after, name="after"),
36+
path("/test/afterEach", views.after_each, name="afterEach"),
37+
path("/test/setup/app", views.setup_core_app),
38+
path("/test/setup/st", views.setup_st),
4639
]
4740

4841
mode = os.environ.get("APP_MODE", "asgi")

tests/auth-react/django3x/polls/views.py

Lines changed: 33 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from django.http import HttpRequest, HttpResponse, JsonResponse
1919
from mysite.store import get_codes, get_url_with_token
2020
from mysite.utils import custom_init
21+
from mysite.utils import setup_core_app as setup_core_app_impl
2122
from supertokens_python import convert_to_recipe_user_id
2223
from supertokens_python.asyncio import get_user
2324
from supertokens_python.auth_utils import LinkingToSessionUserFailedError
@@ -387,37 +388,6 @@ async def remove_tenant(request: HttpRequest):
387388
return JsonResponse({"status": "OK", "didExist": core_resp.did_exist})
388389

389390

390-
async def test_set_flow(request: HttpRequest):
391-
body = json.loads(request.body)
392-
import mysite.store
393-
394-
mysite.store.contact_method = body["contactMethod"]
395-
mysite.store.flow_type = body["flowType"]
396-
custom_init()
397-
return HttpResponse("")
398-
399-
400-
async def test_set_account_linking_config(request: HttpRequest):
401-
import mysite.store
402-
403-
body = json.loads(request.body)
404-
if body is None:
405-
raise Exception("Invalid request body")
406-
mysite.store.accountlinking_config = body
407-
custom_init()
408-
return HttpResponse("")
409-
410-
411-
async def set_mfa_info(request: HttpRequest):
412-
import mysite.store
413-
414-
body = json.loads(request.body)
415-
if body is None:
416-
return JsonResponse({"error": "Invalid request body"}, status_code=400)
417-
mysite.store.mfa_info = body
418-
return JsonResponse({"status": "OK"})
419-
420-
421391
@verify_session()
422392
async def add_required_factor(request: HttpRequest):
423393
session_: SessionContainer = request.supertokens # type: ignore
@@ -433,18 +403,6 @@ async def add_required_factor(request: HttpRequest):
433403
return JsonResponse({"status": "OK"})
434404

435405

436-
def test_set_enabled_recipes(request: HttpRequest):
437-
import mysite.store
438-
439-
body = json.loads(request.body)
440-
if body is None:
441-
raise Exception("Invalid request body")
442-
mysite.store.enabled_recipes = body.get("enabledRecipes")
443-
mysite.store.enabled_providers = body.get("enabledProviders")
444-
custom_init()
445-
return HttpResponse("")
446-
447-
448406
def test_get_totp_code(request: HttpRequest):
449407
from pyotp import TOTP
450408

@@ -467,18 +425,24 @@ def test_create_oauth2_client(request: HttpRequest):
467425
return JsonResponse(client.to_json())
468426

469427

428+
def before(request: HttpRequest):
429+
return HttpResponse("")
430+
431+
470432
def before_each(request: HttpRequest):
471433
import mysite.store
472434

473-
mysite.store.contact_method = "EMAIL_OR_PHONE"
474-
mysite.store.flow_type = "USER_INPUT_CODE_AND_MAGIC_LINK"
475435
mysite.store.latest_url_with_token = ""
476436
mysite.store.code_store = dict()
477-
mysite.store.accountlinking_config = {}
478-
mysite.store.enabled_providers = None
479-
mysite.store.enabled_recipes = None
480-
mysite.store.mfa_info = {}
481-
custom_init()
437+
438+
return HttpResponse("")
439+
440+
441+
def after_each(request: HttpRequest):
442+
return HttpResponse("")
443+
444+
445+
def after(request: HttpRequest):
482446
return HttpResponse("")
483447

484448

@@ -500,3 +464,22 @@ def test_feature_flags(request: HttpRequest):
500464
]
501465
}
502466
)
467+
468+
469+
def setup_core_app(request: HttpRequest):
470+
body = json.loads(request.body)
471+
if body is None:
472+
raise Exception("Invalid request body")
473+
474+
url = setup_core_app_impl(**body)
475+
476+
return HttpResponse(url)
477+
478+
479+
def setup_st(request: HttpRequest):
480+
body = json.loads(request.body)
481+
if body is None:
482+
raise Exception("Invalid request body")
483+
484+
custom_init(**body)
485+
return HttpResponse("")

0 commit comments

Comments
 (0)