11from __future__ import annotations
22
3- from functools import partial
4- from typing import Dict , List , Optional
3+ from typing import Any , Dict , List , Optional
4+
5+ from httpx import QueryParams , Response
6+ from pydantic import TypeAdapter
57
68from ..helpers import (
79 is_valid_uuid ,
2123 InviteUserByEmailOptions ,
2224 SignOutScope ,
2325 User ,
26+ UserList ,
2427 UserResponse ,
2528)
2629from .gotrue_admin_mfa_api import AsyncGoTrueAdminMFAAPI
@@ -45,18 +48,19 @@ def __init__(
4548 verify = verify ,
4649 proxy = proxy ,
4750 )
51+ # TODO(@o-santi): why is is this done this way?
4852 self .mfa = AsyncGoTrueAdminMFAAPI ()
49- self .mfa .list_factors = self ._list_factors
50- self .mfa .delete_factor = self ._delete_factor
53+ self .mfa .list_factors = self ._list_factors # type: ignore
54+ self .mfa .delete_factor = self ._delete_factor # type: ignore
5155
5256 async def sign_out (self , jwt : str , scope : SignOutScope = "global" ) -> None :
5357 """
5458 Removes a logged-in session.
5559 """
56- return await self ._request (
60+ await self ._request (
5761 "POST" ,
5862 "logout" ,
59- query = { " scope" : scope } ,
63+ query = QueryParams ( scope = scope ) ,
6064 jwt = jwt ,
6165 no_resolve_json = True ,
6266 )
@@ -69,19 +73,19 @@ async def invite_user_by_email(
6973 """
7074 Sends an invite link to an email address.
7175 """
72- return await self ._request (
76+ response = await self ._request (
7377 "POST" ,
7478 "invite" ,
7579 body = {"email" : email , "data" : options .get ("data" )},
7680 redirect_to = options .get ("redirect_to" ),
77- xform = parse_user_response ,
7881 )
82+ return parse_user_response (response )
7983
8084 async def generate_link (self , params : GenerateLinkParams ) -> GenerateLinkResponse :
8185 """
8286 Generates email links and OTPs to be sent via a custom email provider.
8387 """
84- return await self ._request (
88+ response = await self ._request (
8589 "POST" ,
8690 "admin/generate_link" ,
8791 body = {
@@ -92,9 +96,10 @@ async def generate_link(self, params: GenerateLinkParams) -> GenerateLinkRespons
9296 "data" : params .get ("options" , {}).get ("data" ),
9397 },
9498 redirect_to = params .get ("options" , {}).get ("redirect_to" ),
95- xform = parse_link_response ,
9699 )
97100
101+ return parse_link_response (response )
102+
98103 # User Admin API
99104
100105 async def create_user (self , attributes : AdminUserAttributes ) -> UserResponse :
@@ -104,30 +109,28 @@ async def create_user(self, attributes: AdminUserAttributes) -> UserResponse:
104109 This function should only be called on a server.
105110 Never expose your `service_role` key in the browser.
106111 """
107- return await self ._request (
112+ response = await self ._request (
108113 "POST" ,
109114 "admin/users" ,
110115 body = attributes ,
111- xform = parse_user_response ,
112116 )
117+ return parse_user_response (response )
113118
114- async def list_users (self , page : int = None , per_page : int = None ) -> List [User ]:
119+ async def list_users (
120+ self , page : Optional [int ] = None , per_page : Optional [int ] = None
121+ ) -> List [User ]:
115122 """
116123 Get a list of users.
117124
118125 This function should only be called on a server.
119126 Never expose your `service_role` key in the browser.
120127 """
121- return await self ._request (
128+ response = await self ._request (
122129 "GET" ,
123130 "admin/users" ,
124- query = {"page" : page , "per_page" : per_page },
125- xform = lambda data : (
126- [model_validate (User , user ) for user in data ["users" ]]
127- if "users" in data
128- else []
129- ),
131+ query = QueryParams (page = page , per_page = per_page ),
130132 )
133+ return model_validate (UserList , response .content ).users
131134
132135 async def get_user_by_id (self , uid : str ) -> UserResponse :
133136 """
@@ -138,11 +141,11 @@ async def get_user_by_id(self, uid: str) -> UserResponse:
138141 """
139142 self ._validate_uuid (uid )
140143
141- return await self ._request (
144+ response = await self ._request (
142145 "GET" ,
143146 f"admin/users/{ uid } " ,
144- xform = parse_user_response ,
145147 )
148+ return parse_user_response (response )
146149
147150 async def update_user_by_id (
148151 self ,
@@ -156,12 +159,12 @@ async def update_user_by_id(
156159 Never expose your `service_role` key in the browser.
157160 """
158161 self ._validate_uuid (uid )
159- return await self ._request (
162+ response = await self ._request (
160163 "PUT" ,
161164 f"admin/users/{ uid } " ,
162165 body = attributes ,
163- xform = parse_user_response ,
164166 )
167+ return parse_user_response (response )
165168
166169 async def delete_user (self , id : str , should_soft_delete : bool = False ) -> None :
167170 """
@@ -172,31 +175,33 @@ async def delete_user(self, id: str, should_soft_delete: bool = False) -> None:
172175 """
173176 self ._validate_uuid (id )
174177 body = {"should_soft_delete" : should_soft_delete }
175- return await self ._request ("DELETE" , f"admin/users/{ id } " , body = body )
178+ await self ._request ("DELETE" , f"admin/users/{ id } " , body = body )
176179
177180 async def _list_factors (
178181 self ,
179182 params : AuthMFAAdminListFactorsParams ,
180183 ) -> AuthMFAAdminListFactorsResponse :
181184 self ._validate_uuid (params .get ("user_id" ))
182- return await self ._request (
185+ response = await self ._request (
183186 "GET" ,
184187 f"admin/users/{ params .get ('user_id' )} /factors" ,
185- xform = partial (model_validate , AuthMFAAdminListFactorsResponse ),
186188 )
189+ return model_validate (AuthMFAAdminListFactorsResponse , response .content )
187190
188191 async def _delete_factor (
189192 self ,
190193 params : AuthMFAAdminDeleteFactorParams ,
191194 ) -> AuthMFAAdminDeleteFactorResponse :
192195 self ._validate_uuid (params .get ("user_id" ))
193196 self ._validate_uuid (params .get ("id" ))
194- return await self ._request (
197+ response = await self ._request (
195198 "DELETE" ,
196199 f"admin/users/{ params .get ('user_id' )} /factors/{ params .get ('id' )} " ,
197- xform = partial (model_validate , AuthMFAAdminDeleteFactorResponse ),
198200 )
201+ return model_validate (AuthMFAAdminDeleteFactorResponse , response .content )
199202
200- def _validate_uuid (self , id : str ) -> None :
203+ def _validate_uuid (self , id : str | None ) -> None :
204+ if id is None :
205+ raise ValueError ("Invalid id, id cannot be none" )
201206 if not is_valid_uuid (id ):
202207 raise ValueError (f"Invalid id, '{ id } ' is not a valid uuid" )
0 commit comments