123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- from __future__ import annotations # for Python 3.10+
- from typing import Optional
- from uuid import UUID
- from typing_extensions import deprecated
- from shared.api.models.auth.responses import WrappedTokenResponse
- from shared.api.models.base import (
- WrappedBooleanResponse,
- WrappedGenericMessageResponse,
- )
- from shared.api.models.management.responses import (
- WrappedCollectionsResponse,
- WrappedUserResponse,
- WrappedUsersResponse,
- )
- from ..models import Token
- class UsersSDK:
- def __init__(self, client):
- self.client = client
- async def create(
- self,
- email: str,
- password: str,
- name: Optional[str] = None,
- bio: Optional[str] = None,
- profile_picture: Optional[str] = None,
- ) -> WrappedUserResponse:
- """
- Register a new user.
- Args:
- email (str): User's email address
- password (str): User's password
- name (Optional[str]): The name for the new user
- bio (Optional[str]): The bio for the new user
- profile_picture (Optional[str]): New user profile picture
- Returns:
- UserResponse: New user information
- """
- data: dict = {"email": email, "password": password}
- if name is not None:
- data["name"] = name
- if bio is not None:
- data["bio"] = bio
- if profile_picture is not None:
- data["profile_picture"] = profile_picture
- return await self.client._make_request(
- "POST",
- "users",
- json=data,
- version="v3",
- )
- # @deprecated("Use client.users.create() instead")
- async def register(self, email: str, password: str) -> WrappedUserResponse:
- """
- Register a new user.
- Args:
- email (str): User's email address
- password (str): User's password
- Returns:
- UserResponse: New user information
- """
- data = {"email": email, "password": password}
- return await self.client._make_request(
- "POST",
- "users/register",
- json=data,
- version="v3",
- )
- async def delete(
- self, id: str | UUID, password: str
- ) -> WrappedBooleanResponse:
- """
- Delete a specific user.
- Users can only delete their own account unless they are superusers.
- Args:
- id (str | UUID): User ID to delete
- password (str): User's password
- Returns:
- dict: Deletion result
- """
- data = {"password": password}
- return await self.client._make_request(
- "DELETE",
- f"users/{str(id)}",
- json=data,
- version="v3",
- )
- async def verify_email(
- self, email: str, verification_code: str
- ) -> WrappedGenericMessageResponse:
- """
- Verify a user's email address.
- Args:
- email (str): User's email address
- verification_code (str): Verification code sent to the user's email
- Returns:
- dict: Verification result
- """
- data = {"email": email, "verification_code": verification_code}
- return await self.client._make_request(
- "POST",
- "users/verify-email",
- json=data,
- version="v3",
- )
- async def login(self, email: str, password: str) -> dict[str, Token]:
- """
- Log in a user.
- Args:
- email (str): User's email address
- password (str): User's password
- Returns:
- dict[str, Token]: Access and refresh tokens
- """
- data = {"username": email, "password": password}
- response = await self.client._make_request(
- "POST",
- "users/login",
- data=data,
- version="v3",
- )
- self.client.access_token = response["results"]["access_token"]["token"]
- self.client._refresh_token = response["results"]["refresh_token"][
- "token"
- ]
- return response
- # FIXME: What is going on here...
- async def login_with_token(self, access_token: str) -> dict[str, Token]:
- """
- Log in using an existing access token.
- Args:
- access_token (str): Existing access token
- Returns:
- dict[str, Token]: Token information
- """
- self.client.access_token = access_token
- try:
- await self.client._make_request(
- "GET",
- "users/me",
- version="v3",
- )
- return {
- "access_token": Token(
- token=access_token, token_type="access_token"
- ),
- }
- except Exception:
- self.access_token = None
- self.client._refresh_token = None
- raise ValueError("Invalid token provided")
- async def logout(self) -> WrappedGenericMessageResponse:
- """Log out the current user."""
- response = await self.client._make_request(
- "POST",
- "users/logout",
- version="v3",
- )
- self.client.access_token = None
- self.client._refresh_token = None
- return response
- async def refresh_token(self) -> WrappedTokenResponse:
- """Refresh the access token using the refresh token."""
- response = await self.client._make_request(
- "POST",
- "users/refresh-token",
- json=self.client._refresh_token,
- version="v3",
- )
- self.client.access_token = response["results"]["access_token"]["token"]
- self.client._refresh_token = response["results"]["refresh_token"][
- "token"
- ]
- return response
- async def change_password(
- self, current_password: str, new_password: str
- ) -> WrappedGenericMessageResponse:
- """
- Change the user's password.
- Args:
- current_password (str): User's current password
- new_password (str): User's new password
- Returns:
- dict: Change password result
- """
- data = {
- "current_password": current_password,
- "new_password": new_password,
- }
- return await self.client._make_request(
- "POST",
- "users/change-password",
- json=data,
- version="v3",
- )
- async def request_password_reset(
- self, email: str
- ) -> WrappedGenericMessageResponse:
- """
- Request a password reset.
- Args:
- email (str): User's email address
- Returns:
- dict: Password reset request result
- """
- return await self.client._make_request(
- "POST",
- "users/request-password-reset",
- json=email,
- version="v3",
- )
- async def reset_password(
- self, reset_token: str, new_password: str
- ) -> WrappedGenericMessageResponse:
- """
- Reset password using a reset token.
- Args:
- reset_token (str): Password reset token
- new_password (str): New password
- Returns:
- dict: Password reset result
- """
- data = {"reset_token": reset_token, "new_password": new_password}
- return await self.client._make_request(
- "POST",
- "users/reset-password",
- json=data,
- version="v3",
- )
- async def list(
- self,
- ids: Optional[list[str | UUID]] = None,
- offset: Optional[int] = 0,
- limit: Optional[int] = 100,
- ) -> WrappedUsersResponse:
- """
- List users with pagination and filtering options.
- Args:
- offset (int, optional): Specifies the number of objects to skip. Defaults to 0.
- limit (int, optional): Specifies a limit on the number of objects to return, ranging between 1 and 100. Defaults to 100.
- Returns:
- dict: List of users and pagination information
- """
- params = {
- "offset": offset,
- "limit": limit,
- }
- if ids:
- params["ids"] = [str(user_id) for user_id in ids] # type: ignore
- return await self.client._make_request(
- "GET",
- "users",
- params=params,
- version="v3",
- )
- async def retrieve(
- self,
- id: str | UUID,
- ) -> WrappedUserResponse:
- """
- Get a specific user.
- Args:
- id (str | UUID): User ID to retrieve
- Returns:
- dict: Detailed user information
- """
- return await self.client._make_request(
- "GET",
- f"users/{str(id)}",
- version="v3",
- )
- async def me(
- self,
- ) -> WrappedUserResponse:
- """
- Get detailed information about the currently authenticated user.
- Returns:
- dict: Detailed user information
- """
- return await self.client._make_request(
- "GET",
- "users/me",
- version="v3",
- )
- async def update(
- self,
- id: str | UUID,
- email: Optional[str] = None,
- is_superuser: Optional[bool] = None,
- name: Optional[str] = None,
- bio: Optional[str] = None,
- profile_picture: Optional[str] = None,
- ) -> WrappedUserResponse:
- """
- Update user information.
- Args:
- id (str | UUID): User ID to update
- username (Optional[str]): New username
- is_superuser (Optional[bool]): Update superuser status
- name (Optional[str]): New name
- bio (Optional[str]): New bio
- profile_picture (Optional[str]): New profile picture
- Returns:
- dict: Updated user information
- """
- data: dict = {}
- if email is not None:
- data["email"] = email
- if is_superuser is not None:
- data["is_superuser"] = is_superuser
- if name is not None:
- data["name"] = name
- if bio is not None:
- data["bio"] = bio
- if profile_picture is not None:
- data["profile_picture"] = profile_picture
- return await self.client._make_request(
- "POST",
- f"users/{str(id)}",
- json=data, # if len(data.keys()) != 1 else list(data.values())[0]
- version="v3",
- )
- async def list_collections(
- self,
- id: str | UUID,
- offset: Optional[int] = 0,
- limit: Optional[int] = 100,
- ) -> WrappedCollectionsResponse:
- """
- Get all collections associated with a specific user.
- Args:
- id (str | UUID): User ID to get collections for
- offset (int, optional): Specifies the number of objects to skip. Defaults to 0.
- limit (int, optional): Specifies a limit on the number of objects to return, ranging between 1 and 100. Defaults to 100.
- Returns:
- dict: List of collections and pagination information
- """
- params = {
- "offset": offset,
- "limit": limit,
- }
- return await self.client._make_request(
- "GET",
- f"users/{str(id)}/collections",
- params=params,
- version="v3",
- )
- async def add_to_collection(
- self,
- id: str | UUID,
- collection_id: str | UUID,
- ) -> WrappedBooleanResponse:
- """
- Add a user to a collection.
- Args:
- id (str | UUID): User ID to add
- collection_id (str | UUID): Collection ID to add user to
- """
- return await self.client._make_request(
- "POST",
- f"users/{str(id)}/collections/{str(collection_id)}",
- version="v3",
- )
- async def remove_from_collection(
- self,
- id: str | UUID,
- collection_id: str | UUID,
- ) -> WrappedBooleanResponse:
- """
- Remove a user from a collection.
- Args:
- id (str | UUID): User ID to remove
- collection_id (str | UUID): Collection ID to remove user from
- Returns:
- bool: True if successful
- """
- return await self.client._make_request(
- "DELETE",
- f"users/{str(id)}/collections/{str(collection_id)}",
- version="v3",
- )
|