Metadata-Version: 2.4
Name: lars-kluijtmans-admin-sdk
Version: 0.0.3
Summary: Python admin SDK for the Auth Platform Management API
Project-URL: Homepage, https://github.com/LarsKluijtmans/auth
Project-URL: Source, https://github.com/LarsKluijtmans/auth/tree/main/admin-sdk-python
Author: Auth Platform
License: MIT
Keywords: admin,auth,oauth,rbac,sdk
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: build>=1; extra == 'dev'
Requires-Dist: flake8>=7; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: twine>=5; extra == 'dev'
Description-Content-Type: text/markdown

# lars-kluijtmans-admin-sdk

A Python admin SDK for the **Auth Platform** Management API — modelled on the Firebase
Authentication Admin SDK. From a server-side program: read projects, clients and providers,
and read/update users (active state, custom claims, password-reset/verification emails).

```bash
pip install lars-kluijtmans-admin-sdk
```

The import package stays `auth_platform_admin` (`from auth_platform_admin import AdminClient`).
Requires Python 3.10+.

## Authenticating

Two credential modes.

### M2M (recommended for servers)

A **service client** with the `client_credentials` grant. The SDK runs the grant against the
Login API, then caches and refreshes the token for you:

```python
from auth_platform_admin import AdminClient

client = AdminClient.from_client_credentials(
    login_api_url="https://login.example.com",
    management_url="https://manage.example.com",
    client_id="client_xxx",
    client_secret="…",
)
```

### Bring-your-own token

Attach an admin access token you already hold (e.g. from a logged-in session):

```python
client = AdminClient(management_url="https://manage.example.com", token=ACCESS_TOKEN)
```

What a credential may do is governed by RBAC: a **user** token uses that user's role; a **service
client** uses the role assigned to it (see *Setting up a service client* below).

`AdminClient` is a context manager and closes its HTTP connection on exit:

```python
with AdminClient.from_client_credentials(...) as client:
    ...
```

## Using it

```python
# Projects
project  = client.projects.get(project_id)
projects = client.projects.list(company_id)

# Clients & providers
clients   = client.clients.list(project_id)
provider  = client.providers.catalog()            # platform catalog
enabled   = client.providers.list(project_id)      # per-project, with enable state

# Users — read
users = client.users.list(project_id, search="ann", status="active")  # one page
for user in client.users.iter(project_id):                            # all pages
    print(user.email, user.is_active)
user = client.users.get(project_id, user_id)

# Users — update (active state, claims, and profile fields)
client.users.set_active(project_id, user_id, False)
client.users.set_claims(project_id, user_id, {"tier": "gold"})
client.users.set_profile(project_id, user_id, {"display_name": "Ann", "language": "nl"})
# Firebase-style: apply whichever fields you pass (profile fields accept None to clear).
client.users.update(project_id, user_id, active=True, claims={"tier": "silver"},
                    display_name="Ann", language="nl", profile_picture="https://cdn/x.png")

# Users — remediation
client.users.send_password_reset(project_id, user_id)
client.users.resend_verification(project_id, user_id)
client.users.force_logout(project_id, user_id)
```

Every model exposes `.raw` (the full API payload) so new/unknown fields are always reachable.

> The admin can edit **display name, language, and profile picture** (`set_profile` / `update`),
> flip active state, set claims, and trigger the reset/verification emails. **Email and password
> changes remain self-service** on the Login API — they are not part of the admin surface.

## Setting up a service client

1. **Create a client** for the project (Management console → project → Clients, or the API) and
   enable the **`client_credentials`** grant on it. Keep the `client_id` + secret.
2. **Assign it a role** — the permissions an m2m token from this client gets:
   ```http
   PUT /api/v1/projects/{project_id}/clients/{client_id}/service-role
   { "role_id": "<a management role id>" }
   ```
   (Needs `role:manage`.) A client with no service role can mint a token but is denied everything.
3. Use `AdminClient.from_client_credentials(...)` with that client's id + secret.

The service account is always scoped to its own company/project and is never a platform admin.

## Errors

Failures raise typed exceptions — `AuthError` (401), `Forbidden` (403), `NotFound` (404),
`Conflict` (409), `ValidationError` (422), `NetworkError` — all subclasses of `AdminError`
(carrying `.status` and `.detail`):

```python
from auth_platform_admin import NotFound, Forbidden

try:
    client.users.get(project_id, user_id)
except NotFound:
    ...
except Forbidden as exc:
    print(exc.status, exc.detail)
```

See [`examples/`](examples/) for runnable scripts (M2M and bring-your-own-token).
