# VQ-Django-Auth

A robust Django REST framework authentication solution providing ready-to-use endpoints for authentication flows.

## Features

- **Authentication APIs**: Login, logout, and user information endpoints
- **Password Management**: Change password, reset password via email
- **Token Authentication**: Built-in token-based authentication support
- **Customizable**: Highly configurable serializers, views, and endpoints
- **Simple Integration**: Designed to work smoothly with Django and Django REST Framework

## Requirements

- Python 3.8+
- Django 4.2+ or 5.2+
- Django REST Framework 3.15+

## Installation

```bash
pip install vq-django-auth
```

Or using uv:

```bash
uv pip install vq-django-auth
```

## Quick Setup

1. **Add to INSTALLED_APPS**:

```python
INSTALLED_APPS = [
    # Django apps
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    # ...

    # Required for Token Authentication
    "rest_framework",
    "rest_framework.authtoken",

    # VQ Django Auth
    "vq_django_auth",
]
```

2. **Configure authentication method**:

```python
from vq_django_auth.choices import AuthMethod

VQ_REST_AUTH = {
    "AUTH_METHOD": AuthMethod.TOKEN,  # Use AuthMethod.SESSION for session-based auth
}
```

3. **Add to URLs**:

```python
from django.urls import path, include

urlpatterns = [
    # ...
    path("api/auth/", include("vq_django_auth.urls")),
    # ...
]
```

4. **Configure REST Framework settings**:

```python
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework.authentication.TokenAuthentication",
        "rest_framework.authentication.SessionAuthentication",
    ],
    # ...
}
```

## API Endpoints

| Endpoint | Method | Description |
| --- | --- | --- |
| `/login/` | POST | Login and obtain token |
| `/logout/` | POST | Logout and invalidate token |
| `/user/` | GET, PUT, PATCH | Retrieve/update user details |
| `/password/change/` | POST | Change user password |
| `/password/reset/` | POST | Request password reset email |
| `/password/reset/confirm/` | POST | Confirm password reset |

### Login

**Request**:
```json
{
  "username": "yourusername",
  "password": "yourpassword"
}
```

**Response** (200 OK):
```json
{
  "key": "your-auth-token"
}
```

### User Details

**Request** (with Authorization header):
```
GET /user/
Authorization: Token your-auth-token
```

**Response** (200 OK):
```json
{
  "pk": 1,
  "username": "yourusername",
  "email": "user@example.com",
  "first_name": "First",
  "last_name": "Last"
}
```

## Authentication Methods

### Token Authentication
When `AUTH_METHOD` is set to `AuthMethod.TOKEN`, the login endpoint returns an authentication token:

```python
from vq_django_auth.choices import AuthMethod

VQ_REST_AUTH = {
    "AUTH_METHOD": AuthMethod.TOKEN,
}
```

### Session Authentication
When `AUTH_METHOD` is set to `AuthMethod.SESSION`, login uses Django sessions:

```python
from vq_django_auth.choices import AuthMethod

VQ_REST_AUTH = {
    "AUTH_METHOD": AuthMethod.SESSION,
}
```

**Note**: The `AUTH_METHOD` setting is required and must be set to either `AuthMethod.SESSION` or `AuthMethod.TOKEN`.

## Configuration

You can customize the behavior by adding a `VQ_REST_AUTH` dictionary in your Django settings:

```python
from vq_django_auth.choices import AuthMethod

VQ_REST_AUTH = {
    # Custom serializers
    "LOGIN_SERIALIZER": "yourapp.serializers.CustomLoginSerializer",
    "USER_DETAILS_SERIALIZER": "yourapp.serializers.CustomUserDetailsSerializer",

    # Token configuration
    "TOKEN_CREATOR": "yourapp.utils.custom_token_creator",

    # Password reset settings
    "PASSWORD_RESET_USE_SITES_DOMAIN": True,

    # Authentication method (required)
    "AUTH_METHOD": AuthMethod.SESSION,  # or AuthMethod.TOKEN
}
```

## Available Settings

| Setting | Default | Description |
| --- | --- | --- |
| `AUTH_METHOD` | `None` (required) | Authentication method: `AuthMethod.SESSION` or `AuthMethod.TOKEN` |
| `LOGIN_SERIALIZER` | `"vq_django_auth.serializers.LoginSerializer"` | Serializer used for login |
| `TOKEN_SERIALIZER` | `"vq_django_auth.serializers.TokenSerializer"` | Token serializer |
| `USER_DETAILS_SERIALIZER` | `"vq_django_auth.serializers.UserDetailsSerializer"` | User details serializer |
| `PASSWORD_RESET_SEND_MAIL` | `"vq_django_auth.usecases.password_reset_send_mail"` | Function to send password reset emails |
| `FRONT_URL_RESET_EMAIL` | `None` | Base URL for password reset links in emails |

## Custom Serializers

To create a custom serializer, extend the base serializer and override its methods:

```python
from vq_django_auth.serializers import LoginSerializer

class CustomLoginSerializer(LoginSerializer):
    def validate(self, attrs):
        attrs = super().validate(attrs)
        # Add custom validation here
        return attrs
```

## Customize password reset

### Frontend URL for Reset Emails

Use `FRONT_URL_RESET_EMAIL` to specify the base URL for password reset links. This is useful when your frontend application handles password resets separately from your Django backend:

```python
VQ_REST_AUTH = {
    "FRONT_URL_RESET_EMAIL": "/reset-password",
    # Other settings...
}
```

The reset email templates will receive this URL in the context as `front_url`. You can use it to construct the complete reset URL like:
`{{ front_url }}/{{ uid }}/{{ token }}/`

This allows users to be directed to your frontend application where you can then send the verification data to your API endpoint.

### Custom Password Reset Email

To customize the password reset email, you can create your own email sending function and configure it in your settings:

```python
# yourapp/email_utils.py
from django.template import loader
from django.core.mail import EmailMultiAlternatives

def custom_password_reset_email(
    context,
    subject_template_name="emails/custom_password_reset_subject.txt",
    email_template_name="emails/custom_password_reset.html",
):
    """
    Send a custom password reset email.

    Args:
        context: Dictionary containing email context variables:
            - email: User's email address
            - domain: Site domain
            - site_name: Name of the site
            - uid: Base64 encoded user ID
            - user: User object
            - front_url: URL fragment from settings
            - token: Password reset token
            - protocol: 'http' or 'https'
        subject_template_name: Path to subject template
        email_template_name: Path to email body template
    """
    subject = loader.render_to_string(subject_template_name, context)
    # Email subject *must not* contain newlines
    subject = "".join(subject.splitlines())
    body = loader.render_to_string(email_template_name, context)

    email_message = EmailMultiAlternatives(
        subject=subject,
        body=body,
        from_email="support@yoursite.com",  # Or use settings.DEFAULT_FROM_EMAIL
        to=[context["email"]],
    )

    # Add HTML content if needed
    # email_message.attach_alternative(html_content, "text/html")

    email_message.send()
```

Then configure your settings:

```python
VQ_REST_AUTH = {
    "PASSWORD_RESET_SEND_MAIL": "yourapp.email_utils.custom_password_reset_email",
    # Other settings...
}
```

## Development Setup

This project uses [uv](https://github.com/astral-sh/uv) and tox for development.

```bash
# Install dependencies
uv tool install tox --with tox-uv

# Run tests
tox
```

## License

MIT
