Skip to content

feat!: appinfo refactor #459

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 43 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5d388af
WIP: appInfo refactor
IamMayankThakur Nov 1, 2023
ae2c821
fix: linting errrs
IamMayankThakur Nov 10, 2023
08dad5d
Merge branch 'master' into feat/appinfo-refactor
IamMayankThakur Nov 10, 2023
4fd944c
feat: add session recipe changes for appInfo refactor
IamMayankThakur Nov 14, 2023
29f92dc
fix: unaligned types in session recipe
IamMayankThakur Nov 14, 2023
6cb1f31
fixed errors
IamMayankThakur Nov 14, 2023
e70fc0d
more fixes
IamMayankThakur Nov 14, 2023
d34492d
more fixes
IamMayankThakur Nov 14, 2023
9ac3158
feat: removed request arg from consume_code functions
IamMayankThakur Nov 20, 2023
bb2f5ff
added tests got appInfo refactor
IamMayankThakur Nov 22, 2023
171afdb
Merge branch 'master' into feat/appinfo-refactor
IamMayankThakur Nov 22, 2023
26de060
fixed old breaking tests
IamMayankThakur Nov 24, 2023
017cff3
fixed linting errors
IamMayankThakur Nov 24, 2023
36e61a5
refactor: removed unused variables
IamMayankThakur Nov 24, 2023
6e9737b
test: add test for session changes
IamMayankThakur Nov 27, 2023
d3c1771
updates changelog and bumps version
IamMayankThakur Nov 27, 2023
a40c42f
Merge branch '0.18' into feat/appinfo-refactor
IamMayankThakur Nov 27, 2023
cc2b051
fixes to supertokens.py file
rishabhpoddar Nov 27, 2023
e90d13f
fixes middleware code
rishabhpoddar Nov 27, 2023
f330300
more changes
rishabhpoddar Nov 27, 2023
cb8c21f
more fixes
rishabhpoddar Nov 27, 2023
f781326
more fixes
rishabhpoddar Nov 27, 2023
6decb79
more fixes
rishabhpoddar Nov 27, 2023
c156354
more fixes
rishabhpoddar Nov 27, 2023
a2a4e7b
more fixes
rishabhpoddar Nov 27, 2023
8434d63
more fixes
rishabhpoddar Nov 27, 2023
8fb9707
more fixes
rishabhpoddar Nov 27, 2023
391df9e
more fixes
rishabhpoddar Nov 27, 2023
2d07c5e
more fixes
rishabhpoddar Nov 27, 2023
08bc4c6
more fixes
rishabhpoddar Nov 27, 2023
d5e35ee
more fixes
rishabhpoddar Nov 27, 2023
233f2bc
more fixes
rishabhpoddar Nov 27, 2023
7614fc1
more fixes
rishabhpoddar Nov 27, 2023
09d9064
more fixes
rishabhpoddar Nov 27, 2023
a4dc546
more fixes
rishabhpoddar Nov 27, 2023
ca26b7c
fixes non test linting and formatting
rishabhpoddar Nov 27, 2023
dc8c897
fixes linting and formatting in tests
rishabhpoddar Nov 27, 2023
8c871c3
test fixes
rishabhpoddar Nov 28, 2023
9c47ec7
fixes debug logging issue
rishabhpoddar Nov 28, 2023
d211b55
changes permission of script
rishabhpoddar Nov 28, 2023
440b3db
makes example scripts exec
rishabhpoddar Nov 28, 2023
eaa2fa8
updates changelog
rishabhpoddar Nov 28, 2023
b9d007c
fixes a few tests
rishabhpoddar Nov 28, 2023
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
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
},
"python.analysis.typeCheckingMode": "strict",
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
"python.testing.pytestEnabled": true,
"python.analysis.autoImportCompletions": true
}
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [unreleased]

## [0.18.0] - 2023-11-25

### Added

- Adds support for configuring multiple frontend domains to be used with the same backend
- Added new `origin` property to `InputAppInfo`, this can be configured to allow you to conditionally return the value of the frontend domain. This property will replace `website_domain`
- `website_domain` inside `InputAppInfo` is now optional. Using `origin` recommended over using `website_domain`. Using `website_domain` will continue to work.

### Breaking Change
- The order or arguments in the `InputAppInfo`

## [0.17.0] - 2023-11-14
- Fixes `create_reset_password_link` in the emailpassword recipe wherein we passed the `rid` instead of the token in the link

Expand Down
2 changes: 1 addition & 1 deletion dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pycparser==2.21
pycryptodome==3.10.4
pydantic==1.9.0
PyJWT==2.6.0
pylint==2.12.2
pylint==2.14.0
pyparsing==3.0.7
pyright==1.1.236
pyrsistent==0.18.1
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@

setup(
name="supertokens_python",
version="0.17.0",
version="0.18.0",
author="SuperTokens",
license="Apache 2.0",
author_email="[email protected]",
Expand Down
2 changes: 1 addition & 1 deletion supertokens_python/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from __future__ import annotations

SUPPORTED_CDI_VERSIONS = ["3.0"]
VERSION = "0.17.0"
VERSION = "0.18.0"
TELEMETRY = "/telemetry"
USER_COUNT = "/users/count"
USER_DELETE = "/user/remove"
Expand Down
8 changes: 4 additions & 4 deletions supertokens_python/framework/django/django_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ async def __asyncMiddleware(request: HttpRequest):
request.supertokens, SessionContainer # type: ignore
):
manage_session_post_response(
request.supertokens, result # type: ignore
request.supertokens, result, user_context # type: ignore
)
if isinstance(result, DjangoResponse):
return result.response
except SuperTokensError as e:
response = DjangoResponse(HttpResponse())
result = await st.handle_supertokens_error(
DjangoRequest(request), e, response
DjangoRequest(request), e, response, user_context
)
if isinstance(result, DjangoResponse):
return result.response
Expand Down Expand Up @@ -85,15 +85,15 @@ def __syncMiddleware(request: HttpRequest):
request.supertokens, SessionContainer # type: ignore
):
manage_session_post_response(
request.supertokens, result # type: ignore
request.supertokens, result, user_context # type: ignore
)
return result.response

except SuperTokensError as e:
response = DjangoResponse(HttpResponse())
result: Union[DjangoResponse, None] = async_to_sync(
st.handle_supertokens_error
)(DjangoRequest(request), e, response)
)(DjangoRequest(request), e, response, user_context)
if result is not None:
return result.response
raise Exception("Should never come here")
Expand Down
13 changes: 8 additions & 5 deletions supertokens_python/framework/fastapi/fastapi_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ async def dispatch(self, request: Request, call_next: RequestResponseEndpoint):
st = Supertokens.get_instance()
from fastapi.responses import Response

custom_request = FastApiRequest(request)
response = FastApiResponse(Response())
user_context = default_user_context(custom_request)

try:
custom_request = FastApiRequest(request)
response = FastApiResponse(Response())
user_context = default_user_context(custom_request)
result: Union[BaseResponse, None] = await st.middleware(
custom_request, response, user_context
)
Expand All @@ -58,13 +59,15 @@ async def dispatch(self, request: Request, call_next: RequestResponseEndpoint):
if hasattr(request.state, "supertokens") and isinstance(
request.state.supertokens, SessionContainer
):
manage_session_post_response(request.state.supertokens, result)
manage_session_post_response(
request.state.supertokens, result, user_context
)
if isinstance(result, FastApiResponse):
return result.response
except SuperTokensError as e:
response = FastApiResponse(Response())
result: Union[BaseResponse, None] = await st.handle_supertokens_error(
FastApiRequest(request), e, response
FastApiRequest(request), e, response, user_context
)
if isinstance(result, FastApiResponse):
return result.response
Expand Down
10 changes: 8 additions & 2 deletions supertokens_python/framework/flask/flask_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def _(response: Response):

response_ = FlaskResponse(response)
if hasattr(g, "supertokens") and g.supertokens is not None:
manage_session_post_response(g.supertokens, response_)
manage_session_post_response(g.supertokens, response_, {})

return response_.response

Expand All @@ -84,15 +84,21 @@ def _(error: Exception):
from supertokens_python import Supertokens
from supertokens_python.framework.flask.flask_request import FlaskRequest
from supertokens_python.framework.flask.flask_response import FlaskResponse
from supertokens_python.utils import default_user_context

from flask.wrappers import Response

st = Supertokens.get_instance()
response = Response(json.dumps({}), mimetype="application/json", status=200)
base_request = FlaskRequest(request)
user_context = default_user_context(base_request)

result: BaseResponse = sync(
st.handle_supertokens_error(
FlaskRequest(request), error, FlaskResponse(response)
base_request,
error,
FlaskResponse(response),
user_context,
)
)
if isinstance(result, FlaskResponse):
Expand Down
11 changes: 3 additions & 8 deletions supertokens_python/recipe/dashboard/api/analytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,8 @@ async def handle_analytics_post(
None,
_user_context,
)
if response is not None:
if (
"exists" in response
and response["exists"]
and "telemetryId" in response
):
telemetry_id = response["telemetryId"]
if "exists" in response and response["exists"] and "telemetryId" in response:
telemetry_id = response["telemetryId"]

number_of_users = await Supertokens.get_instance().get_user_count(
include_recipe_ids=None
Expand All @@ -79,7 +74,7 @@ async def handle_analytics_post(

apiDomain, websiteDomain, appName = (
api_options.app_info.api_domain,
api_options.app_info.website_domain,
api_options.app_info.get_origin(api_options.request, {}),
api_options.app_info.app_name,
)

Expand Down
6 changes: 5 additions & 1 deletion supertokens_python/recipe/dashboard/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,11 @@ async def handle_api_request(
return None

async def handle_error(
self, request: BaseRequest, err: SuperTokensError, response: BaseResponse
self,
request: BaseRequest,
err: SuperTokensError,
response: BaseResponse,
user_context: Dict[str, Any],
) -> BaseResponse:
raise err

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,12 @@ async def generate_password_reset_token_post(
return GeneratePasswordResetTokenPostOkResult()

password_reset_link = get_password_reset_link(
api_options.app_info, token_result.token, api_options.recipe_id, tenant_id
api_options.app_info,
token_result.token,
api_options.recipe_id,
tenant_id,
api_options.request,
user_context,
)

log_debug_message("Sending password reset email to %s", email)
Expand Down
6 changes: 6 additions & 0 deletions supertokens_python/recipe/emailpassword/asyncio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from typing import Any, Dict, Union, Optional
from supertokens_python import get_request_from_user_context

from supertokens_python.recipe.emailpassword import EmailPasswordRecipe

Expand Down Expand Up @@ -137,17 +138,22 @@ async def send_email(
async def create_reset_password_link(
tenant_id: str, user_id: str, user_context: Optional[Dict[str, Any]] = None
):
if user_context is None:
user_context = {}
token = await create_reset_password_token(tenant_id, user_id, user_context)
if isinstance(token, CreateResetPasswordWrongUserIdError):
return CreateResetPasswordLinkUnknownUserIdError()

recipe_instance = EmailPasswordRecipe.get_instance()
request = get_request_from_user_context(user_context)
return CreateResetPasswordLinkOkResult(
link=get_password_reset_link(
recipe_instance.get_app_info(),
token.token,
recipe_instance.get_recipe_id(),
tenant_id,
request,
user_context,
)
)

Expand Down
6 changes: 5 additions & 1 deletion supertokens_python/recipe/emailpassword/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,11 @@ async def handle_api_request(
return None

async def handle_error(
self, request: BaseRequest, err: SuperTokensError, response: BaseResponse
self,
request: BaseRequest,
err: SuperTokensError,
response: BaseResponse,
user_context: Dict[str, Any],
) -> BaseResponse:
if isinstance(err, SuperTokensEmailPasswordError):
if isinstance(err, FieldError):
Expand Down
12 changes: 9 additions & 3 deletions supertokens_python/recipe/emailpassword/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
from __future__ import annotations

from re import fullmatch
from typing import TYPE_CHECKING, Any, Callable, List, Union
from typing import TYPE_CHECKING, Any, Callable, List, Optional, Union, Dict
from supertokens_python.framework import BaseRequest

from supertokens_python.ingredients.emaildelivery.types import (
EmailDeliveryConfig,
Expand Down Expand Up @@ -300,10 +301,15 @@ def get_email_delivery_config(


def get_password_reset_link(
app_info: AppInfo, token: str, recipe_id: str, tenant_id: str
app_info: AppInfo,
token: str,
recipe_id: str,
tenant_id: str,
request: Optional[BaseRequest],
user_context: Dict[str, Any],
) -> str:
return (
app_info.website_domain.get_as_string_dangerous()
app_info.get_origin(request, user_context).get_as_string_dangerous()
+ app_info.website_base_path.get_as_string_dangerous()
+ "/reset-password?token="
+ token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# under the License.
from typing import Any, Dict, Union, Optional

from supertokens_python import get_request_from_user_context

from supertokens_python.recipe.emailverification.interfaces import (
GetEmailForUserIdOkResult,
EmailDoesNotExistError,
Expand Down Expand Up @@ -176,12 +178,15 @@ async def create_email_verification_link(
):
return CreateEmailVerificationLinkEmailAlreadyVerifiedError()

request = get_request_from_user_context(user_context)
return CreateEmailVerificationLinkOkResult(
link=get_email_verify_link(
app_info,
email_verification_token.token,
recipe_instance.get_recipe_id(),
tenant_id,
request,
user_context,
)
)

Expand Down
13 changes: 11 additions & 2 deletions supertokens_python/recipe/emailverification/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,11 @@ async def handle_api_request(
)

async def handle_error(
self, request: BaseRequest, err: SuperTokensError, response: BaseResponse
self,
request: BaseRequest,
err: SuperTokensError,
response: BaseResponse,
user_context: Dict[str, Any],
) -> BaseResponse:
if isinstance(err, EmailVerificationInvalidTokenError):
response.set_json_content(
Expand Down Expand Up @@ -444,7 +448,12 @@ async def generate_email_verify_token_post(
await session.fetch_and_set_claim(EmailVerificationClaim, user_context)

email_verify_link = get_email_verify_link(
api_options.app_info, response.token, api_options.recipe_id, tenant_id
api_options.app_info,
response.token,
api_options.recipe_id,
tenant_id,
api_options.request,
user_context,
)

log_debug_message("Sending email verification email to %s", email_info)
Expand Down
12 changes: 9 additions & 3 deletions supertokens_python/recipe/emailverification/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@

from __future__ import annotations

from typing import TYPE_CHECKING, Optional
from typing import TYPE_CHECKING, Any, Dict, Optional
from supertokens_python.framework import BaseRequest

from supertokens_python.ingredients.emaildelivery.types import (
EmailDeliveryConfig,
Expand Down Expand Up @@ -103,10 +104,15 @@ def get_email_delivery_config() -> EmailDeliveryConfigWithService[


def get_email_verify_link(
app_info: AppInfo, token: str, recipe_id: str, tenant_id: str
app_info: AppInfo,
token: str,
recipe_id: str,
tenant_id: str,
request: Optional[BaseRequest],
user_context: Dict[str, Any],
) -> str:
return (
app_info.website_domain.get_as_string_dangerous()
app_info.get_origin(request, user_context).get_as_string_dangerous()
+ app_info.website_base_path.get_as_string_dangerous()
+ "/verify-email"
+ "?token="
Expand Down
6 changes: 5 additions & 1 deletion supertokens_python/recipe/jwt/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,11 @@ async def handle_api_request(
return None

async def handle_error(
self, request: BaseRequest, err: SuperTokensError, response: BaseResponse
self,
request: BaseRequest,
err: SuperTokensError,
response: BaseResponse,
user_context: Dict[str, Any],
):
raise err

Expand Down
6 changes: 5 additions & 1 deletion supertokens_python/recipe/multitenancy/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,11 @@ async def handle_api_request(
)

async def handle_error(
self, request: BaseRequest, err: SuperTokensError, response: BaseResponse
self,
request: BaseRequest,
err: SuperTokensError,
response: BaseResponse,
user_context: Dict[str, Any],
) -> BaseResponse:
raise err

Expand Down
Loading