Files
ReadMeABook/documentation/admin-features/request-approval.md
T
kikootwo 3a9ae4a439 Add request approval system and audiobook path template
Implements admin approval workflow for user requests with global and per-user auto-approve controls. Adds new request statuses ('awaiting_approval', 'denied'), related API endpoints, and UI for pending approvals. Introduces configurable audiobook organization path template with validation and preview in settings, updates database schema and migrations for new fields.
2026-01-28 11:41:59 -05:00

5.4 KiB

Request Approval System

Status: Implemented | Admin approval workflow for user requests with global & per-user auto-approve controls

Overview

Allows admins to review and approve/deny user requests before they are processed. Supports global auto-approve toggle and per-user auto-approve overrides.

Key Details

Request Statuses

  • awaiting_approval - New status for requests pending admin approval
  • denied - New status for requests rejected by admin
  • pending - Status after approval (triggers search job)
  • Applies to all existing statuses: pending, searching, downloading, processing, downloaded, available, failed, cancelled, awaiting_search, awaiting_import, warn

Configuration Keys

  • auto_approve_requests (Configuration table) - Global setting (true/false string)
  • User.autoApproveRequests (User table) - Per-user override (boolean, nullable)
    • null = Use global setting
    • true = Always auto-approve for this user
    • false = Always require approval for this user

Approval Logic

When user creates request:

  1. Check User.autoApproveRequests:
    • If true → Set status to 'pending', trigger search job
    • If false → Set status to 'awaiting_approval', wait for admin
    • If null → Check global auto_approve_requests setting
      • If 'true' → Auto-approve (status: 'pending')
      • Otherwise → Require approval (status: 'awaiting_approval')

Admin approval actions:

  • Approve → Change status to 'pending', trigger search job
  • Deny → Change status to 'denied', no further processing

API Endpoints

GET /api/admin/requests/pending-approval

Fetch all requests with status 'awaiting_approval'

Auth: Admin only

Response:

{
  "success": true,
  "requests": [
    {
      "id": "uuid",
      "createdAt": "2026-01-15T12:00:00Z",
      "audiobook": {
        "title": "Book Title",
        "author": "Author Name",
        "coverArtUrl": "https://..."
      },
      "user": {
        "id": "uuid",
        "plexUsername": "username",
        "avatarUrl": "https://..."
      }
    }
  ],
  "count": 5
}

POST /api/admin/requests/[id]/approve

Approve or deny a specific request

Auth: Admin only

Request:

{
  "action": "approve" | "deny"
}

Response (approve):

{
  "success": true,
  "message": "Request approved and search job triggered",
  "request": { /* full request object */ }
}

Response (deny):

{
  "success": true,
  "message": "Request denied",
  "request": { /* full request object */ }
}

Errors:

  • 404 - Request not found
  • 400 - Request not in 'awaiting_approval' status
  • 400 - Invalid action (must be 'approve' or 'deny')

GET /api/admin/settings/auto-approve

Get global auto-approve setting

Auth: Admin only

Response:

{
  "autoApproveRequests": true
}

PATCH /api/admin/settings/auto-approve

Update global auto-approve setting

Auth: Admin only

Request:

{
  "autoApproveRequests": true
}

Response:

{
  "autoApproveRequests": true
}

PUT /api/admin/users/[id]

Update user (includes autoApproveRequests field)

Auth: Admin only

Request:

{
  "autoApproveRequests": true | false | null
}

UI Features

Admin Dashboard (/admin)

Requests Awaiting Approval Section:

  • Shows only when pending approval requests exist
  • Grid layout with book cards (3 columns on desktop)
  • Each card displays:
    • Book cover image
    • Title and author
    • User avatar and username
    • Request timestamp (relative: "2 hours ago")
    • Approve button (green, checkmark icon)
    • Deny button (red, X icon)
  • Auto-refreshes every 10 seconds (SWR)
  • Loading states on buttons during approval/denial
  • Success/error toast notifications
  • Mutates multiple caches on action: pending-approval, recent requests, metrics

Admin Users Page (/admin/users)

Global Auto-Approve Toggle:

  • Checkbox at top of page
  • Label: "Auto-approve all requests by default"
  • Updates auto_approve_requests configuration
  • Optimistic UI update with revert on error
  • Toast notification on success/error

Per-User Auto-Approve Control:

  • Each user row has toggle dropdown:
    • "Use Global Setting" (null, default)
    • "Always Auto-Approve" (true)
    • "Always Require Approval" (false)
  • Updates User.autoApproveRequests field
  • Shows current effective setting (considers global + per-user)
  • Optimistic UI update

User Request Flow

When creating request (POST /api/requests):

  • System checks approval logic (see above)
  • If awaiting approval → User sees status "Awaiting Approval" on request card
  • If auto-approved → User sees status "Pending" and processing begins

Request Status Badges

  • awaiting_approval → Amber badge with warning icon
  • denied → Red badge with X icon
  • All other statuses → Existing badge colors

Database Schema

User Table

autoApproveRequests: Boolean (nullable, default null)
- null: Use global setting
- true: Always auto-approve
- false: Always require approval

Request Table

status: Enum (includes 'awaiting_approval', 'denied')

Configuration Table

key: 'auto_approve_requests'
value: 'true' | 'false' (string)