Metadata-Version: 2.4
Name: user-auth-client
Version: 0.1.0
Summary: Python client for user authentication: signup, login, reset password, and profile.
Author-email: Your Name <your.email@example.com>
License: MIT
Project-URL: Homepage, https://github.com/yourusername/user-auth-client
Project-URL: Documentation, https://github.com/yourusername/user-auth-client#readme
Project-URL: Repository, https://github.com/yourusername/user-auth-client
Keywords: auth,login,signup,password-reset,profile,api-client
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Provides-Extra: django
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.100.0; extra == "fastapi"
Provides-Extra: flask
Requires-Dist: flask>=2.0.0; extra == "flask"
Provides-Extra: all
Requires-Dist: fastapi>=0.100.0; extra == "all"
Requires-Dist: flask>=2.0.0; extra == "all"
Dynamic: license-file

# User Auth Client

Python client for user authentication: **signup**, **login**, **reset password**, and **get profile**. Designed to work with any REST auth API and ready to publish on PyPI.

## Installation

```bash
pip install user-auth-client
```

For framework integrations (optional):

```bash
pip install user-auth-client[django]   # Django
pip install user-auth-client[fastapi]  # FastAPI
pip install user-auth-client[flask]    # Flask
pip install user-auth-client[all]      # FastAPI + Flask
```

## Quick start

```python
from user_auth_client import AuthClient, SignupData, LoginData

client = AuthClient(base_url="https://your-api.example.com")

# Sign up
client.signup(SignupData(email="user@example.com", password="secret", username="jane"))

# Log in (stores token automatically if API returns access_token)
client.login(LoginData(email="user@example.com", password="secret"))

# Get profile (uses stored token)
profile = client.get_profile()
print(profile.email, profile.username)

# Reset password
client.reset_password("user@example.com")
```

---

## Django

Use the client in views with the request's `Authorization: Bearer <token>` header.

```bash
pip install user-auth-client[django]
```

**settings.py:**
```python
AUTH_API_URL = "https://your-auth-api.com"
```

**views.py:**
```python
from django.http import JsonResponse
from django.conf import settings
from user_auth_client.django import get_client_from_request, get_current_user

def login_view(request):
    from user_auth_client import AuthClient, LoginData
    client = AuthClient(base_url=settings.AUTH_API_URL)
    data = client.login(LoginData(email=request.POST["email"], password=request.POST["password"]))
    return JsonResponse(data)

def profile_view(request):
    user = get_current_user(request, settings.AUTH_API_URL)
    if not user:
        return JsonResponse({"error": "Unauthorized"}, status=401)
    return JsonResponse({"email": user.email, "username": user.username})
```

---

## FastAPI

Use dependency injection to get an `AuthClient` and the current user.

```bash
pip install user-auth-client[fastapi]
```

```python
from fastapi import Depends
from user_auth_client import AuthClient
from user_auth_client.fastapi import auth_client_depends, get_current_user_depends
from user_auth_client.models import UserProfile

BASE_URL = "https://your-auth-api.com"
get_client = auth_client_depends(BASE_URL)
get_user = get_current_user_depends(BASE_URL)

@app.post("/auth/signup")
def signup(client: AuthClient = Depends(get_client)):
    return {"ok": True}

@app.get("/profile")
def profile(user: UserProfile = Depends(get_user)):
    return {"email": user.email, "id": user.id}
```

---

## Flask

Attach the client and current user with `init_app`, or use helpers per view.

```bash
pip install user-auth-client[flask]
```

**Option A – init_app (g.auth_client, g.current_user):**
```python
from flask import Flask, g
from user_auth_client.flask import init_app

app = Flask(__name__)
app.config["AUTH_API_URL"] = "https://your-auth-api.com"
init_app(app)

@app.route("/profile")
def profile():
    if g.current_user is None:
        return {"error": "Unauthorized"}, 401
    return {"email": g.current_user.email}
```

**Option B – per-view helper:**
```python
from user_auth_client.flask import get_current_user

@app.route("/me")
def me():
    user = get_current_user(app.config["AUTH_API_URL"])
    if not user:
        return {"error": "Unauthorized"}, 401
    return {"email": user.email}
```

---

## API reference

### `AuthClient(base_url, timeout=30.0, headers=None)`

- **base_url** – Base URL of your auth API (e.g. `https://api.example.com`).
- **timeout** – Request timeout in seconds.
- **headers** – Optional default headers for every request.

### Methods

| Method | Description |
|--------|-------------|
| `signup(data: SignupData)` | Register a new user. Returns API response dict. |
| `login(data: LoginData)` | Log in with email/password. Sets token if response contains `access_token`. |
| `reset_password(email: str)` | Request password reset for the given email. |
| `get_profile() -> UserProfile` | Get current user profile (requires token). |
| `set_token(token: str)` | Set bearer token manually. |
| `clear_token()` | Clear stored token. |

### Models

- **SignupData** – `email`, `password`, optional `username`, optional `extra` dict.
- **LoginData** – `email`, `password`.
- **UserProfile** – `id`, `email`, `username`, `raw` (full response dict).

### Exceptions

- `AuthClientError` – Base error; has `message` and optional `status_code`.
- `AuthClientConnectionError` – Network/connection failure.
- `AuthClientAuthError` – Auth failure (401/403).

### Example with custom token

```python
# If your login endpoint returns a different key:
resp = client.login(LoginData(email="u@x.com", password="pwd"))
client.set_token(resp["token"])  # or resp["jwt"], etc.

profile = client.get_profile()
```

## Expected API shape

The client assumes your backend exposes REST endpoints like:

| Action | Method | Path | Body (JSON) |
|--------|--------|------|--------------|
| Signup | POST | `/auth/signup` | `email`, `password`, optional `username` |
| Login | POST | `/auth/login` | `email`, `password` |
| Reset password | POST | `/auth/reset-password` | `email` |
| Get profile | GET | `/auth/profile` | — (Bearer token) |

Login response may include `access_token`; if present, the client stores it for `get_profile()`. You can also call `set_token()` after login with a different key.

## Development

```bash
git clone https://github.com/yourusername/user-auth-client
cd user-auth-client
pip install -e ".[dev]"
pytest
```

## Publishing to PyPI

1. Install build and twine:  
   `pip install build twine`
2. Build:  
   `python -m build`
3. Upload (use PyPI token):  
   `twine upload dist/*`

Update `pyproject.toml` (version, `authors`, `urls`) and `README` links before publishing.

## License

MIT
