Metadata-Version: 2.4
Name: fastpluggy-auth-user
Version: 0.2.1
Summary: User Authentication plugin for Fastpluggy
Author: FastPluggy Team
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: FastPluggy>=0.4.10
Requires-Dist: bcrypt
Requires-Dist: click
Requires-Dist: passlib
Requires-Dist: pyotp
Requires-Dist: python-jose
Requires-Dist: python-multipart
Requires-Dist: qrcode[svg]
Provides-Extra: tests
Requires-Dist: pytest>=7.0; extra == "tests"
Requires-Dist: pytest-cov>=4.0; extra == "tests"
Requires-Dist: pytest-asyncio>=0.21; extra == "tests"
Provides-Extra: e2e
Requires-Dist: fastpluggy-cli; extra == "e2e"
Requires-Dist: uvicorn[standard]; extra == "e2e"

# Auth User Plugin

![Auth User](https://img.shields.io/badge/FastPluggy-Auth%20User-blue)
[![Release](https://gitlab.ggcorp.fr/open/fastpluggy/plugins/auth_user/-/badges/release.svg)](https://gitlab.ggcorp.fr/open/fastpluggy/plugins/auth_user/-/releases)
[![Pipeline Status](https://gitlab.ggcorp.fr/open/fastpluggy/plugins/auth_user/badges/main/pipeline.svg?key_text=CI)](https://gitlab.ggcorp.fr/open/fastpluggy/plugins/auth_user/-/pipelines?ignore_skipped=true)
[![Coverage](https://gitlab.ggcorp.fr/open/fastpluggy/plugins/auth_user/badges/main/coverage.svg)](https://gitlab.ggcorp.fr/open/fastpluggy/plugins/auth_user/-/pipelines)

The Auth User plugin provides comprehensive user authentication and management functionality for FastPluggy applications.

## 📊 Current Status

**✅ PRODUCTION READY FEATURES:**
- Complete admin interface for user management (CRUD operations)
- User authentication with secure password hashing
- Session management with configurable expiration
- User profile pages with authentication protection
- Automatic admin user creation on first install
- Menu integration for user functions

**⚠️ PARTIALLY IMPLEMENTED:**
- Login routes (exist but commented out - ready for activation)

**📋 ROADMAP:** See [Implementation Roadmap](docs/fastpluggy-auth-roadmap.md) for detailed development plan.

## Features

- **User Authentication**: Secure username/password authentication with BCrypt hashing
- **Admin Interface**: Complete user management with list, add, edit functionality
- **Session Management**: Configurable session handling with JSON data storage
- **User Profiles**: Protected profile pages for authenticated users
- **Menu Integration**: Automatic menu items for profile and logout
- **Template System**: Jinja2 templates for login and profile pages
- **Database Integration**: SQLAlchemy models with FastPluggy core

## Models

### FastPluggyBaseUser
The main user model with the following fields:
- `username`: Unique username (String, 255 chars)
- `hashed_password`: Securely hashed password (String, 255 chars)
- `is_admin`: Boolean flag indicating admin privileges (default: False)

### Session
Session management model for user authentication:
- `session_id`: Unique session identifier (String, 255 chars)
- `session_data`: JSON data stored in the session
- `session_lifetime`: Session expiration timestamp
- `session_time`: Session creation timestamp

## Configuration

The plugin uses `AuthUserConfig` class with the following settings:

```python
from fastpluggy.core.config import BaseDatabaseSettings
from typing import Optional, Literal

class AuthUserConfig(BaseDatabaseSettings):
    # Set to None to enable UI-based setup on first install
    # If None, admin user creation will be handled via setup UI
    default_admin_username: Optional[str] = None
    default_admin_password: Optional[str] = None

    # Auth backend: "session" (cookies + tokens + login redirect) or "basic" (HTTP Basic popup)
    auth_backend: Literal["session", "basic"] = "session"

    login_template: str = 'auth_user/login.html'
    collect_login_ip: bool = True
    allow_api_tokens: bool = True  # set to False to disable personal access tokens globally
```

### Auth backends

| Backend | `auth_backend` | How it works |
|---------|---------------|-------------|
| **Session** (default) | `"session"` | Cookie-based sessions + Bearer tokens + HTTP Basic with `__token__` (pip/twine). Redirects to login page on auth failure. |
| **Basic** | `"basic"` | HTTP Basic authentication only. Triggers browser popup on auth failure. |

The auth backend is configurable via environment variable or database settings:

```bash
AUTH_USER_AUTH_BACKEND=basic  # or "session" (default)
```

## Admin User Setup

The plugin provides **intelligent admin user setup** with two approaches:

### 🎯 **Recommended: UI-Based Setup (Default)**
By default, `default_admin_username` and `default_admin_password` are set to `None`, which enables the setup UI:

1. **First Install**: When no users exist, visit `/setup/` to create the first admin user
2. **Secure**: No hardcoded credentials - you choose the username and password
3. **User-Friendly**: Clean web interface with validation and error handling
4. **Automatic Detection**: The system automatically detects when setup is needed

### 🔧 **Alternative: Automatic Creation with Configured Credentials**
If you prefer automatic admin creation, configure default credentials:

```python
# In your environment or config
default_admin_username = "your_admin_username"
default_admin_password = "your_secure_password"
```

When configured, the plugin will automatically create the admin user on first startup.

### 📋 **Setup Process**
1. **Plugin Load**: System checks if any users exist
2. **If No Users**:
   - **With configured credentials**: Automatically creates admin user
   - **Without credentials (default)**: Logs message to visit `/setup/`
3. **Setup UI**: Visit `/setup/` to create admin user with custom credentials
4. **Redirect**: After successful setup, redirects to login page

### 🔍 **Setup Status Check**
You can check if setup is needed programmatically:

```python
from fastpluggy_plugin.auth_user.src.repository import needs_initial_setup
from fastpluggy.core.database import get_db

if needs_initial_setup(get_db()):
    print("Setup required - visit /setup/")
else:
    print("Admin user exists")
```

## Routes

### Setup Routes
- `GET /setup/` - Initial admin user setup page (only accessible when no users exist)
- `POST /setup/` - Process admin user creation form
- `GET /setup/check` - API endpoint to check if setup is needed

### Authentication Routes
- `GET /logout` - Logout user and clear session

### Profile Routes
- `GET /profile/` - User profile page (requires authentication)

## Menu Integration

The plugin automatically adds the following menu items:
- **Profile** (`/profile/`) - User profile page
- **Logout** (`/logout`) - Logout functionality

## Templates

The plugin expects the following Jinja2 templates:
- `auth_user/profile.html.j2` - User profile page template
- `auth_user/login.html.j2` - Login page template (referenced in config)

## Usage

1. **Install** the plugin — it is auto-discovered via the `fastpluggy.plugins` entry point
2. **Auth is auto-wired** — the plugin calls `fast_pluggy.set_auth_manager()` during `on_load_complete`, so you do **not** need to pass `auth_manager=` to `FastPluggy()`. Just `FastPluggy(app)` is enough.
3. **First run** — visit `/setup/` to create the first admin user (or set `default_admin_username` / `default_admin_password` in config for automatic creation)
4. **Profile** — authenticated users can manage their profile at `/profile/`

> If you pass `auth_manager=` explicitly to `FastPluggy()`, the plugin respects it and does not override.

## Personal Access Tokens

Users can create long-lived API tokens for programmatic access (CI/CD, pip, twine, scripts).

### Managing tokens

Tokens are managed via the UI at `/tokens/`:
- Create a token with a name and optional expiry (in days)
- The raw token value is shown **once** — copy it immediately
- Revoke any token at any time

### Using tokens — API clients (Bearer)

```http
Authorization: Bearer <your-token>
```

Any endpoint protected by `require_authentication` accepts this header.

### Using tokens — pip / twine (HTTP Basic)

pip and twine use HTTP Basic auth. Use `__token__` as the username and your token as the password:

```bash
# pip install
pip install --index-url https://__token__:<your-token>@registry.fastpluggy.xyz/pypi/simple/ my-package

# twine upload
twine upload --repository-url https://registry.fastpluggy.xyz/pypi/ \
  -u __token__ -p <your-token> dist/*
```

Or configure `~/.pypirc`:

```ini
[fastpluggy]
repository = https://registry.fastpluggy.xyz/pypi/
username = __token__
password = <your-token>
```

`SessionAuthManager` detects the `__token__` username in Basic auth headers and validates the password as a personal access token (SHA256 hash lookup), so no separate auth scheme is needed for pip/twine.

### Token model

| Field | Description |
|-------|-------------|
| `name` | User-friendly label |
| `token_hash` | SHA256 of the raw token (never stored in plaintext) |
| `expires_at` | Optional expiry timestamp |
| `last_used_at` | Updated on every successful use |

## Security Notes

- Passwords are securely hashed using BCrypt (`BasicAuthManager.hash_password()`)
- Sessions are managed with configurable lifetime (default: 1 hour)
- Admin privileges are controlled via the `is_admin` boolean field
- API tokens are stored as SHA256 hashes (never in plaintext)
- **Important**: Change the default admin password after first login for security
