Merged in feature/eula.part1 (pull request #206)

eula support

* eula support

* docs
This commit is contained in:
Jay Brown
2026-01-22 18:17:27 +00:00
parent c10fa98d0a
commit 63c12a2f44
38 changed files with 15646 additions and 230 deletions
+297 -8
View File
@@ -28,6 +28,7 @@ The API is organized into the following service groups:
| ExportService | Operations related to exports |
| AuthService | Operations related to authentication |
| AdminService | Operations related to user management and administration |
| EulaService | Operations related to End User License Agreement management and tracking |
## Authentication and Authorization
@@ -1247,6 +1248,281 @@ Re-enables a previously disabled user in AWS Cognito. Restores authentication ca
---
## EULA Operations (EulaService)
The EULA (End User License Agreement) service manages EULA versions and tracks user consent. It provides both public endpoints for retrieving and agreeing to EULAs, and administrative endpoints for managing EULA versions and viewing compliance reports.
### Public Endpoints
#### `GET /eula`
Returns the current active EULA version. This endpoint is public and does not require authentication.
**Security**: Public (no authentication required)
**Response** (`EulaPublicResponse`):
```json
{
"id": "019580df-ef65-7676-8de9-94435a93337a",
"version": "1.0",
"title": "Terms of Service",
"content": "# Terms of Service\n\nThis is the full EULA content in Markdown format...",
"effective_date": "2025-01-01T00:00:00Z"
}
```
**Responses**:
- `200`: Current EULA version retrieved successfully
- `404`: No current EULA version configured
- `500`: Internal server error
#### `GET /eula/status`
Returns the current user's agreement status for the current EULA version. Used by the frontend to determine if the user needs to be prompted to agree.
**Security**: Requires JWT authentication
**Response** (`EulaStatusResponse`):
```json
{
"has_agreed": true,
"current_version": "1.0",
"current_version_id": "019580df-ef65-7676-8de9-94435a93337a",
"agreed_at": "2025-01-15T10:30:00Z",
"agreed_version": "1.0"
}
```
**Responses**:
- `200`: EULA status retrieved successfully
- `401`: Authentication required
- `404`: No current EULA version configured
- `500`: Internal server error
#### `POST /eula/agree`
Records the user's agreement to the current EULA version. This operation is idempotent - calling it multiple times will not create duplicate records. The IP address is automatically captured from the request.
**Security**: Requires JWT authentication
**Response** (`EulaAgreementResponse`):
```json
{
"id": "019580df-ef65-7676-8de9-94435a93337b",
"eula_version_id": "019580df-ef65-7676-8de9-94435a93337a",
"eula_version": "1.0",
"agreed_at": "2025-01-15T10:30:00Z"
}
```
**Responses**:
- `201`: Agreement recorded successfully (first agreement)
- `200`: User already agreed to current version (returns existing agreement)
- `400`: No current EULA version configured
- `401`: Authentication required
- `500`: Internal server error
### Administrative Endpoints
#### `GET /admin/eula`
Returns a paginated list of all EULA versions.
**Security**: Requires JWT authentication
**Query Parameters**:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| page | integer | 1 | Page number (1-10000) |
| page_size | integer | 20 | Results per page (1-100) |
**Response** (`EulaVersionList`):
```json
{
"versions": [
{
"id": "019580df-ef65-7676-8de9-94435a93337a",
"version": "1.0",
"title": "Terms of Service",
"content": "# Terms of Service...",
"effective_date": "2025-01-01T00:00:00Z",
"is_current": true,
"created_at": "2024-12-01T00:00:00Z",
"created_by": "admin@example.com",
"activated_at": "2025-01-01T00:00:00Z",
"activated_by": "admin@example.com"
}
],
"total": 3,
"has_more": false
}
```
#### `POST /admin/eula`
Creates a new EULA version. The content should be in Markdown format.
**Security**: Requires JWT authentication
**Request Body** (`EulaVersionCreate`):
```json
{
"version": "2.0",
"title": "Updated Terms of Service",
"content": "# Updated Terms of Service\n\nThis is the new EULA content...",
"effective_date": "2025-06-01T00:00:00Z"
}
```
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| version | string | Yes | Unique version identifier (max 50 chars) |
| title | string | Yes | Human-readable title |
| content | string | Yes | Full EULA text in Markdown format |
| effective_date | datetime | Yes | When this version becomes effective |
**Response** (`201 Created`): `EulaVersion` object
**Error Responses**:
- `400`: Invalid request data
- `401`: Authentication required
- `403`: Insufficient permissions
- `409`: Version string already exists
#### `GET /admin/eula/{version_id}`
Retrieves a specific EULA version by its ID.
**Security**: Requires JWT authentication
**Path Parameters**:
- `version_id`: EULA version UUID
**Response** (`EulaVersion`): Full EULA version object
#### `PATCH /admin/eula/{version_id}`
Updates only the metadata (title and effective date) of an EULA version. Content cannot be modified to maintain audit integrity.
**Security**: Requires JWT authentication
**Request Body** (`EulaVersionUpdate`):
```json
{
"title": "Updated Title",
"effective_date": "2025-07-01T00:00:00Z"
}
```
**Response** (`200 OK`): Updated `EulaVersion` object
#### `POST /admin/eula/{version_id}/activate`
Sets this version as the current active EULA. Uses a database transaction to atomically clear the previous current flag and set the new one.
**Security**: Requires JWT authentication
**Path Parameters**:
- `version_id`: EULA version UUID to activate
**Response** (`200 OK`): Activated `EulaVersion` object with `is_current=true`
**Error Responses**:
- `404`: Version not found
- `409`: Concurrent activation conflict (another admin activated a different version)
#### `GET /admin/eula/agreements`
Returns a paginated list of user agreements. Use filters to view agreements for specific EULA versions or users.
**Security**: Requires JWT authentication
**Query Parameters**:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| page | integer | 1 | Page number (1-10000) |
| page_size | integer | 20 | Results per page (1-100) |
| version_id | uuid | - | Filter by specific EULA version |
| user_id | string | - | Filter by Cognito subject ID |
**Response** (`EulaAgreementList`):
```json
{
"agreements": [
{
"id": "019580df-ef65-7676-8de9-94435a93337b",
"cognito_subject_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"user_email": "user@example.com",
"eula_version_id": "019580df-ef65-7676-8de9-94435a93337a",
"eula_version": "1.0",
"agreed_at": "2025-01-15T10:30:00Z",
"agreed_from_ip": "192.168.1.1"
}
],
"total": 150,
"has_more": true
}
```
#### `GET /admin/eula/compliance`
Returns a comprehensive compliance report showing which users have and have not agreed to a specific EULA version. Defaults to the current active version if no version_id is provided.
**Security**: Requires JWT authentication
**Query Parameters**:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| page | integer | 1 | Page number (1-10000) |
| page_size | integer | 50 | Results per page (1-100) |
| version_id | uuid | - | Specific EULA version (defaults to current) |
| agreed | boolean | - | Filter by agreement status |
**Response** (`EulaComplianceReport`):
```json
{
"version_id": "019580df-ef65-7676-8de9-94435a93337a",
"version": "1.0",
"total_users": 200,
"agreed_count": 150,
"not_agreed_count": 50,
"compliance_percentage": 75.0,
"users": [
{
"cognito_subject_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "user@example.com",
"first_name": "John",
"last_name": "Doe",
"has_agreed": true,
"agreed_at": "2025-01-15T10:30:00Z"
}
],
"page": 1,
"page_size": 50,
"has_more": true
}
```
---
## Request/Response Schemas
### Standard Response Headers
@@ -1330,13 +1606,14 @@ The API uses Permit.io for fine-grained authorization. This section documents wh
The following endpoints skip authentication and Permit.io authorization entirely:
| Endpoint | Purpose |
| ---------------- | ------------------------ |
| `GET /home` | Public home/menu page |
| `GET /logout` | Session termination |
| `GET /health` | Health check endpoint |
| `GET /swagger/*` | Swagger UI documentation |
| `GET /metrics` | Prometheus metrics |
| Endpoint | Purpose |
| ---------------- | --------------------------------- |
| `GET /home` | Public home/menu page |
| `GET /logout` | Session termination |
| `GET /health` | Health check endpoint |
| `GET /swagger/*` | Swagger UI documentation |
| `GET /metrics` | Prometheus metrics |
| `GET /eula` | Public EULA version retrieval |
### Special Authentication Endpoints
@@ -1404,6 +1681,17 @@ The following table shows what data is passed to Permit.io for each protected en
| `DELETE` | `/admin/users/{email}` | `admin` | `delete` | Delete user |
| `POST` | `/admin/users/{email}/disable` | `admin` | `post` | Disable user |
| `POST` | `/admin/users/{email}/enable` | `admin` | `post` | Enable user |
| **EULA Operations** |
| `GET` | `/eula` | - | - | Public (no auth) |
| `GET` | `/eula/status` | `eula` | `get` | Get user's EULA status |
| `POST` | `/eula/agree` | `eula` | `post` | Record EULA agreement |
| `GET` | `/admin/eula` | `admin` | `get` | List EULA versions |
| `POST` | `/admin/eula` | `admin` | `post` | Create EULA version |
| `GET` | `/admin/eula/{version_id}` | `admin` | `get` | Get EULA version |
| `PATCH` | `/admin/eula/{version_id}` | `admin` | `patch` | Update EULA metadata |
| `POST` | `/admin/eula/{version_id}/activate` | `admin` | `post` | Activate EULA version |
| `GET` | `/admin/eula/agreements` | `admin` | `get` | List EULA agreements |
| `GET` | `/admin/eula/compliance` | `admin` | `get` | Get compliance report |
### Permit.io Configuration Requirements
@@ -1422,7 +1710,8 @@ To configure Permit.io to work with this API, administrators must create:
| `field-extractions` | Field extraction operations |
| `query` | Query definition management |
| `export` | Export operations |
| `admin` | User administration |
| `admin` | User administration and EULA admin operations |
| `eula` | EULA status and agreement operations |
#### Actions