Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions src/auth/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ select = [
# pyupgrade
"UP",
# flake8-bugbear
# "B",
"B",
# flake8-simplify
# "SIM",
# isort
"I",
"ANN2"
]
ignore = ["F401", "F403", "F841", "E712", "E501", "E402", "E722", "E731", "UP006", "UP035"]
# isort.required-imports = ["from __future__ import annotations"]
ignore = ["F403", "E501", "E402", "UP006", "UP035"]

[tool.ruff.lint.pyupgrade]
# Preserve types, even if a file imports `from __future__ import annotations`.
Expand Down
4 changes: 2 additions & 2 deletions src/auth/scripts/gh-download.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,14 @@ def download_directory(repository: Repository, sha: str, server_path: str) -> No
print("Error processing %s: %s", content.path, exc)


def usage():
def usage() -> None:
"""
Prints the usage command lines
"""
print("usage: gh-download --repo=repo --branch=branch --folder=folder")


def main(argv):
def main(argv) -> None:
"""
Main function block
"""
Expand Down
18 changes: 9 additions & 9 deletions src/auth/src/supabase_auth/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
from __future__ import annotations

from ._async.gotrue_admin_api import AsyncGoTrueAdminAPI
from ._async.gotrue_client import AsyncGoTrueClient
from ._async.gotrue_admin_api import AsyncGoTrueAdminAPI # noqa
from ._async.gotrue_client import AsyncGoTrueClient # noqa
from ._async.storage import (
AsyncMemoryStorage,
AsyncSupportedStorage,
AsyncMemoryStorage, # noqa
AsyncSupportedStorage, # noqa
)
from ._sync.gotrue_admin_api import SyncGoTrueAdminAPI
from ._sync.gotrue_client import SyncGoTrueClient
from ._sync.gotrue_admin_api import SyncGoTrueAdminAPI # noqa
from ._sync.gotrue_client import SyncGoTrueClient # noqa
from ._sync.storage import (
SyncMemoryStorage,
SyncSupportedStorage,
SyncMemoryStorage, # noqa
SyncSupportedStorage, # noqa
)
from .types import *
from .version import __version__
from .version import __version__ # noqa
17 changes: 9 additions & 8 deletions src/auth/src/supabase_auth/_async/gotrue_admin_api.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from __future__ import annotations

from typing import Any, Dict, List, Optional
from typing import Dict, List, Optional

from httpx import QueryParams, Response
from pydantic import TypeAdapter
from httpx import QueryParams

from ..helpers import (
model_validate,
Expand Down Expand Up @@ -42,15 +41,16 @@ def __init__(
self,
*,
url: str = "",
headers: Dict[str, str] = {},
headers: Optional[Dict[str, str]] = None,
http_client: Optional[AsyncClient] = None,
verify: bool = True,
proxy: Optional[str] = None,
) -> None:
http_headers = headers or {}
AsyncGoTrueBaseAPI.__init__(
self,
url=url,
headers=headers,
headers=http_headers,
http_client=http_client,
verify=verify,
proxy=proxy,
Expand Down Expand Up @@ -82,16 +82,17 @@ async def sign_out(self, jwt: str, scope: SignOutScope = "global") -> None:
async def invite_user_by_email(
self,
email: str,
options: InviteUserByEmailOptions = {},
options: Optional[InviteUserByEmailOptions] = None,
) -> UserResponse:
"""
Sends an invite link to an email address.
"""
email_options = options or {}
response = await self._request(
"POST",
"invite",
body={"email": email, "data": options.get("data")},
redirect_to=options.get("redirect_to"),
body={"email": email, "data": email_options.get("data")},
redirect_to=email_options.get("redirect_to"),
)
return parse_user_response(response)

Expand Down
6 changes: 3 additions & 3 deletions src/auth/src/supabase_auth/_async/gotrue_base_api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import Any, Callable, Dict, Optional, TypeVar, overload
from typing import Any, Dict, Optional

from httpx import HTTPStatusError, QueryParams, Response
from pydantic import BaseModel
Expand All @@ -20,7 +20,7 @@ def __init__(
http_client: Optional[AsyncClient],
verify: bool = True,
proxy: Optional[str] = None,
):
) -> None:
self._url = url
self._headers = headers
self._http_client = http_client or AsyncClient(
Expand Down Expand Up @@ -74,4 +74,4 @@ async def _request(
response.raise_for_status()
return response
except (HTTPStatusError, RuntimeError) as e:
raise handle_exception(e)
raise handle_exception(e) # noqa
49 changes: 27 additions & 22 deletions src/auth/src/supabase_auth/_async/gotrue_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@

import time
from contextlib import suppress
from functools import partial
from json import loads
from typing import Callable, Dict, List, Mapping, Optional, Tuple, Union
from urllib.parse import parse_qs, urlencode, urlparse
from typing import Callable, Dict, List, Optional, Tuple
from urllib.parse import parse_qs, urlparse
from uuid import uuid4

from httpx import QueryParams
from httpx import QueryParams, Response
from jwt import get_algorithm_by_name
from typing_extensions import cast

Expand All @@ -33,7 +31,6 @@
decode_jwt,
generate_pkce_challenge,
generate_pkce_verifier,
model_dump,
model_dump_json,
model_validate,
parse_auth_otp_response,
Expand All @@ -50,7 +47,6 @@
JWK,
AMREntry,
AuthChangeEvent,
AuthenticatorAssuranceLevels,
AuthFlowType,
AuthMFAChallengeResponse,
AuthMFAEnrollResponse,
Expand Down Expand Up @@ -86,6 +82,7 @@
SignUpWithEmailAndPasswordCredentialsOptions,
SignUpWithPasswordCredentials,
SignUpWithPhoneAndPasswordCredentialsOptions,
SSOResponse,
Subscription,
UpdateUserOptions,
UserAttributes,
Expand Down Expand Up @@ -361,7 +358,9 @@ async def sign_in_with_id_token(
self._notify_all_subscribers("SIGNED_IN", auth_response.session)
return auth_response

async def sign_in_with_sso(self, credentials: SignInWithSSOCredentials):
async def sign_in_with_sso(
self, credentials: SignInWithSSOCredentials
) -> SSOResponse:
"""
Attempts a single-sign on using an enterprise Identity Provider. A
successful SSO attempt will redirect the current page to the identity
Expand Down Expand Up @@ -476,7 +475,7 @@ async def get_user_identities(self) -> IdentitiesResponse:
return IdentitiesResponse(identities=response.user.identities or [])
raise AuthSessionMissingError()

async def unlink_identity(self, identity: UserIdentity):
async def unlink_identity(self, identity: UserIdentity) -> Response:
session = await self.get_session()
if not session:
raise AuthSessionMissingError()
Expand Down Expand Up @@ -621,7 +620,7 @@ async def reauthenticate(self) -> AuthResponse:
if not session:
raise AuthSessionMissingError()

response = await self._request(
await self._request(
"GET",
"reauthenticate",
jwt=session.access_token,
Expand Down Expand Up @@ -674,19 +673,20 @@ async def get_user(self, jwt: Optional[str] = None) -> Optional[UserResponse]:
return parse_user_response(await self._request("GET", "user", jwt=jwt))

async def update_user(
self, attributes: UserAttributes, options: UpdateUserOptions = {}
self, attributes: UserAttributes, options: Optional[UpdateUserOptions] = None
) -> UserResponse:
"""
Updates user data, if there is a logged in user.
"""
session = await self.get_session()
if not session:
raise AuthSessionMissingError()
update_options = options or {}
response = await self._request(
"PUT",
"user",
body=attributes,
redirect_to=options.get("email_redirect_to"),
redirect_to=update_options.get("email_redirect_to"),
jwt=session.access_token,
)
user_response = parse_user_response(response)
Expand Down Expand Up @@ -762,7 +762,7 @@ async def refresh_session(
session = await self._call_refresh_token(refresh_token)
return AuthResponse(session=session, user=session.user)

async def sign_out(self, options: SignOutOptions = {"scope": "global"}) -> None:
async def sign_out(self, options: Optional[SignOutOptions] = None) -> None:
"""
`sign_out` will remove the logged in user from the
current session and log them out - removing all items from storage and then trigger a `"SIGNED_OUT"` event.
Expand All @@ -772,13 +772,14 @@ async def sign_out(self, options: SignOutOptions = {"scope": "global"}) -> None:
There is no way to revoke a user's access token jwt until it expires.
It is recommended to set a shorter expiry on the jwt for this reason.
"""
signout_options = options or {"scope": "global"}
with suppress(AuthApiError):
session = await self.get_session()
access_token = session.access_token if session else None
if access_token:
await self.admin.sign_out(access_token, options["scope"])
await self.admin.sign_out(access_token, signout_options["scope"])

if options["scope"] != "others":
if signout_options["scope"] != "others":
await self._remove_session()
self._notify_all_subscribers("SIGNED_OUT", None)

Expand All @@ -802,31 +803,35 @@ def _unsubscribe() -> None:
self._state_change_emitters[unique_id] = subscription
return subscription

async def reset_password_for_email(self, email: str, options: Options = {}) -> None:
async def reset_password_for_email(
self, email: str, options: Optional[Options] = None
) -> None:
"""
Sends a password reset request to an email address.
"""
reset_options = options or {}
await self._request(
"POST",
"recover",
body={
"email": email,
"gotrue_meta_security": {
"captcha_token": options.get("captcha_token"),
"captcha_token": reset_options.get("captcha_token"),
},
},
redirect_to=options.get("redirect_to"),
redirect_to=reset_options.get("redirect_to"),
)

async def reset_password_email(
self,
email: str,
options: Options = {},
options: Optional[Options] = None,
) -> None:
"""
Sends a password reset request to an email address.
"""
await self.reset_password_for_email(email, options)

await self.reset_password_for_email(email, options or {})

# MFA methods

Expand Down Expand Up @@ -1090,7 +1095,7 @@ async def _start_auto_refresh_token(self, value: float) -> None:
if value <= 0 or not self._auto_refresh_token:
return

async def refresh_token_function():
async def refresh_token_function() -> None:
self._network_retries += 1
try:
session = await self.get_session()
Expand Down Expand Up @@ -1275,7 +1280,7 @@ def __del__(self) -> None:
try:
# Try to cancel the timer
self._refresh_token_timer.cancel()
except:
except Exception:
# Ignore errors if event loop is closed or selector is not registered
pass
finally:
Expand Down
17 changes: 9 additions & 8 deletions src/auth/src/supabase_auth/_sync/gotrue_admin_api.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from __future__ import annotations

from typing import Any, Dict, List, Optional
from typing import Dict, List, Optional

from httpx import QueryParams, Response
from pydantic import TypeAdapter
from httpx import QueryParams

from ..helpers import (
model_validate,
Expand Down Expand Up @@ -42,15 +41,16 @@ def __init__(
self,
*,
url: str = "",
headers: Dict[str, str] = {},
headers: Optional[Dict[str, str]] = None,
http_client: Optional[SyncClient] = None,
verify: bool = True,
proxy: Optional[str] = None,
) -> None:
http_headers = headers or {}
SyncGoTrueBaseAPI.__init__(
self,
url=url,
headers=headers,
headers=http_headers,
http_client=http_client,
verify=verify,
proxy=proxy,
Expand Down Expand Up @@ -82,16 +82,17 @@ def sign_out(self, jwt: str, scope: SignOutScope = "global") -> None:
def invite_user_by_email(
self,
email: str,
options: InviteUserByEmailOptions = {},
options: Optional[InviteUserByEmailOptions] = None,
) -> UserResponse:
"""
Sends an invite link to an email address.
"""
email_options = options or {}
response = self._request(
"POST",
"invite",
body={"email": email, "data": options.get("data")},
redirect_to=options.get("redirect_to"),
body={"email": email, "data": email_options.get("data")},
redirect_to=email_options.get("redirect_to"),
)
return parse_user_response(response)

Expand Down
6 changes: 3 additions & 3 deletions src/auth/src/supabase_auth/_sync/gotrue_base_api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import Any, Callable, Dict, Optional, TypeVar, overload
from typing import Any, Dict, Optional

from httpx import HTTPStatusError, QueryParams, Response
from pydantic import BaseModel
Expand All @@ -20,7 +20,7 @@ def __init__(
http_client: Optional[SyncClient],
verify: bool = True,
proxy: Optional[str] = None,
):
) -> None:
self._url = url
self._headers = headers
self._http_client = http_client or SyncClient(
Expand Down Expand Up @@ -74,4 +74,4 @@ def _request(
response.raise_for_status()
return response
except (HTTPStatusError, RuntimeError) as e:
raise handle_exception(e)
raise handle_exception(e) # noqa
Loading