# Scute Python Client

A Python client for the [Scute API](https://docs.scute.io/api-reference/objects/workspace), with built-in support for authentication, users, and tokens.  
Includes ready-to-use integration guide for Django REST Framework.

---

## Table of Contents

- [Quickstart](#quickstart)

- [Error Handling](#-error-handling)
- [Django REST Framework Integration](#-django-rest-framework-integration)
- [Workspace Sessions – Cross-App Login](#workspace-sessions--cross-app-login-solution)

---

# Quickstart

### 🚀 Installation

```bash
pip install scute-client
```

Initialize the client:
```
from scute_client import ScuteClient

scute = ScuteClient(
    app_id=SCUTE_APP_ID,
    app_secret=SCUTE_APP_SECRET,
)
```

## 📖 Usage Examples
### Create a user
```
identifier = "user@example.com"  # or phone number
scute_user = scute.users.create_user(identifier)
print(scute_user)
```

### Get a user by ID
```
user = scute.users.get_user_by_id("scute_user_id")
print(user)
```

### List all users
```
for scute_user in scute.users.list_all_users():
    print(scute_user["id"], scute_user["email"])
```

### Delete a user
```
scute.users.delete_user(user.sid)
```

### 🛠 Error Handling

All API errors raise APIRequestError:

```
from scute_client.exceptions import APIRequestError

try:
    user = scute.users.get_user_by_id("invalid_id")
except APIRequestError as e:
    print(f"Error: {e.status_code} - {e.message}")
```

<br>

---


### 🔑 Django REST Framework Integration

Add your Scute credentials to Django settings.py:
```
SCUTE_APP_ID = "your_app_id"
SCUTE_APP_SECRET = "your_app_secret"
```

 Initialize the client:
```
from django.conf import settings
from scute_client import ScuteClient

scute = ScuteClient(
    app_id=settings.SCUTE_APP_ID,
    app_secret=settings.SCUTE_APP_SECRET,
)
```

First, ensure your User model has a sid (Scute ID) field.
This field is required to link your local users with Scute users.

Example User model:

```
# users/models.py

from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    # Store Scute ID returned from Scute API
    sid = models.CharField(max_length=255, unique=True, null=True, blank=True)

    def __str__(self):
        return self.username
```
Create a custom authentication class:

```
# authentication.py

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from users.models import User


class ScuteAuthentication(BaseAuthentication):
    keyword = "Scute"

    def authenticate(self, request):
        auth_header = request.headers.get("Authorization")
        if not auth_header or not auth_header.startswith(self.keyword):
            return None

        token = auth_header.split(f"{self.keyword} ")[1]

        try:
            user_data = scute.auth.get_current_user(token)
        except Exception as e:
            raise AuthenticationFailed(f"Invalid token: {str(e)}")

        sid = user_data.get("id")
        if not sid:
            raise AuthenticationFailed("No user ID found in Scute response")

        user = User.objects.filter(sid=sid).first()
        if not user:
            raise AuthenticationFailed("User not found")

        if not user.is_active:
            raise AuthenticationFailed("Inactive user")

        return user, token
```

Enable it in settings.py:
```
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "path.to.authentication.ScuteAuthentication",
    ],
}
```

---

## Workspace Sessions – Cross-App Login Solution
Official docs:
https://docs.scute.io/guides/workspace-sessions

Initialize the client:
```
from scute_client import ScuteClient

scute = ScuteClient(
    workspace_id=SCUTE_WORKSPACE_ID,
    workspace_secret=SCUTE_WORKSPACE_SECRET,
    app_id=SCUTE_APP_ID,
    app_secret=SCUTE_APP_SECRET,
)
```
🔐 Important
- workspace_secret → Required for cross-app sessions
- app_secret → Used for app-level operations
- access_token → Comes from currently authenticated user

## 📖 Usage Examples
### Create app
```
name = "New App"
origin = "https://example.com"

scute_app = scute.apps.create_app(name, origin)
print(scute_app)
```

### Get app by ID
```
app = scute.apps.get_app_by_id("scute_app_id")
print(app)
```

### List all apps
```
scute_apps = scute.apps.list_apps()
print(scute_apps)
```

### Delete app
```
scute.apps.delete_app(scute_app_id)
```

### 🔄 Create Workspace App Session (Cross-App Login)

This exchanges a user session from one app to another.
Flow

1. User is authenticated in App A
2. Backend sends request with:
   - User access_token (from App A)
   - workspace_secret
   - Target app_id (App B)

3. Scute returns new session tokens
4. User is authenticated in App B without login
```
access_token = "user_access_token_from_app_A"
target_app_id = "app_B_id"

scute_app_session = scute.apps.create_app_session(
    access_token=access_token,
    app_id=target_app_id
)

print(scute_app_session)
```

⚠️ Important: User CRUD operations automatically use the workspace secret from initialized client, allowing you to create and manage users in the target app without needing the app secret.
