From 3e14e33f7c2d0ec634a5a519852e64cc3dee6c29 Mon Sep 17 00:00:00 2001 From: Andrew Smith Date: Fri, 30 Aug 2024 13:40:58 +0000 Subject: [PATCH 1/2] feat: add resend method --- supabase_auth/_async/gotrue_client.py | 45 +++++++++++++++++++++++++++ supabase_auth/_sync/gotrue_client.py | 45 +++++++++++++++++++++++++++ supabase_auth/types.py | 24 ++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/supabase_auth/_async/gotrue_client.py b/supabase_auth/_async/gotrue_client.py index 739abaa5..a0a60526 100644 --- a/supabase_auth/_async/gotrue_client.py +++ b/supabase_auth/_async/gotrue_client.py @@ -61,6 +61,7 @@ OAuthResponse, Options, Provider, + ResendCredentials, Session, SignInAnonymouslyCredentials, SignInWithIdTokenCredentials, @@ -519,6 +520,50 @@ async def sign_in_with_otp( "You must provide either an email or phone number" ) + async def resend( + self, + credentials: ResendCredentials, + ) -> AuthOtpResponse: + """ + Log in a user using magiclink or a one-time password (OTP). + + If the `{{ .ConfirmationURL }}` variable is specified in + the email template, a magiclink will be sent. + + If the `{{ .Token }}` variable is specified in the email + template, an OTP will be sent. + + If you're using phone sign-ins, only an OTP will be sent. + You won't be able to send a magiclink for phone sign-ins. + """ + email = credentials.get("email") + phone = credentials.get("phone") + type = credentials.get("type") + options = credentials.get("options", {}) + email_redirect_to = options.get("email_redirect_to") + captcha_token = options.get("captcha_token") + body = { + "type": type, + "gotrue_meta_security": { + "captcha_token": captcha_token, + }, + } + + if email is None and phone is None: + raise AuthInvalidCredentialsError( + "You must provide either an email or phone number" + ) + + body.update({"email": email} if email else {"phone": phone}) + print(f"BODY: {body}") + return await self._request( + "POST", + "resend", + body=body, + redirect_to=email_redirect_to if email else None, + xform=parse_auth_otp_response, + ) + async def verify_otp(self, params: VerifyOtpParams) -> AuthResponse: """ Log in a user given a User supplied OTP received via mobile. diff --git a/supabase_auth/_sync/gotrue_client.py b/supabase_auth/_sync/gotrue_client.py index dc52c85d..4b3824b0 100644 --- a/supabase_auth/_sync/gotrue_client.py +++ b/supabase_auth/_sync/gotrue_client.py @@ -61,6 +61,7 @@ OAuthResponse, Options, Provider, + ResendCredentials, Session, SignInAnonymouslyCredentials, SignInWithIdTokenCredentials, @@ -513,6 +514,50 @@ def sign_in_with_otp( "You must provide either an email or phone number" ) + def resend( + self, + credentials: ResendCredentials, + ) -> AuthOtpResponse: + """ + Log in a user using magiclink or a one-time password (OTP). + + If the `{{ .ConfirmationURL }}` variable is specified in + the email template, a magiclink will be sent. + + If the `{{ .Token }}` variable is specified in the email + template, an OTP will be sent. + + If you're using phone sign-ins, only an OTP will be sent. + You won't be able to send a magiclink for phone sign-ins. + """ + email = credentials.get("email") + phone = credentials.get("phone") + type = credentials.get("type") + options = credentials.get("options", {}) + email_redirect_to = options.get("email_redirect_to") + captcha_token = options.get("captcha_token") + body = { + "type": type, + "gotrue_meta_security": { + "captcha_token": captcha_token, + }, + } + + if email is None and phone is None: + raise AuthInvalidCredentialsError( + "You must provide either an email or phone number" + ) + + body.update({"email": email} if email else {"phone": phone}) + print(f"BODY: {body}") + return self._request( + "POST", + "resend", + body=body, + redirect_to=email_redirect_to if email else None, + xform=parse_auth_otp_response, + ) + def verify_otp(self, params: VerifyOtpParams) -> AuthResponse: """ Log in a user given a User supplied OTP received via mobile. diff --git a/supabase_auth/types.py b/supabase_auth/types.py index 5db169b0..5ecd23cf 100644 --- a/supabase_auth/types.py +++ b/supabase_auth/types.py @@ -376,6 +376,30 @@ class SignInWithPhoneAndPasswordlessCredentials(TypedDict): ] +class ResendEmailCredentialsOptions(TypedDict): + email_redirect_to: NotRequired[str] + captcha_token: NotRequired[str] + + +class ResendEmailCredentials(TypedDict): + type: Literal["signup", "email_change"] + email: str + options: NotRequired[ResendEmailCredentialsOptions] + + +class ResendPhoneCredentialsOptions(TypedDict): + captcha_token: NotRequired[str] + + +class ResendPhoneCredentials(TypedDict): + type: Literal["sms", "phone_change"] + phone: str + options: NotRequired[ResendPhoneCredentialsOptions] + + +ResendCredentials = Union[ResendEmailCredentials, ResendPhoneCredentials] + + class SignInWithOAuthCredentialsOptions(TypedDict): redirect_to: NotRequired[str] scopes: NotRequired[str] From 3699916a66ba3c70a22dbe97d121e5b844bf18a2 Mon Sep 17 00:00:00 2001 From: Andrew Smith Date: Fri, 30 Aug 2024 13:44:50 +0000 Subject: [PATCH 2/2] chore: correct pydoc description and remove debugging statement --- supabase_auth/_async/gotrue_client.py | 13 ++----------- supabase_auth/_sync/gotrue_client.py | 13 ++----------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/supabase_auth/_async/gotrue_client.py b/supabase_auth/_async/gotrue_client.py index a0a60526..d039b414 100644 --- a/supabase_auth/_async/gotrue_client.py +++ b/supabase_auth/_async/gotrue_client.py @@ -525,16 +525,7 @@ async def resend( credentials: ResendCredentials, ) -> AuthOtpResponse: """ - Log in a user using magiclink or a one-time password (OTP). - - If the `{{ .ConfirmationURL }}` variable is specified in - the email template, a magiclink will be sent. - - If the `{{ .Token }}` variable is specified in the email - template, an OTP will be sent. - - If you're using phone sign-ins, only an OTP will be sent. - You won't be able to send a magiclink for phone sign-ins. + Resends an existing signup confirmation email, email change email, SMS OTP or phone change OTP. """ email = credentials.get("email") phone = credentials.get("phone") @@ -555,7 +546,7 @@ async def resend( ) body.update({"email": email} if email else {"phone": phone}) - print(f"BODY: {body}") + return await self._request( "POST", "resend", diff --git a/supabase_auth/_sync/gotrue_client.py b/supabase_auth/_sync/gotrue_client.py index 4b3824b0..a7cf9144 100644 --- a/supabase_auth/_sync/gotrue_client.py +++ b/supabase_auth/_sync/gotrue_client.py @@ -519,16 +519,7 @@ def resend( credentials: ResendCredentials, ) -> AuthOtpResponse: """ - Log in a user using magiclink or a one-time password (OTP). - - If the `{{ .ConfirmationURL }}` variable is specified in - the email template, a magiclink will be sent. - - If the `{{ .Token }}` variable is specified in the email - template, an OTP will be sent. - - If you're using phone sign-ins, only an OTP will be sent. - You won't be able to send a magiclink for phone sign-ins. + Resends an existing signup confirmation email, email change email, SMS OTP or phone change OTP. """ email = credentials.get("email") phone = credentials.get("phone") @@ -549,7 +540,7 @@ def resend( ) body.update({"email": email} if email else {"phone": phone}) - print(f"BODY: {body}") + return self._request( "POST", "resend",