<?php
// =============================================================================
// api/_common.php — required by every admin AJAX endpoint
// =============================================================================

require_once __DIR__ . '/../includes/bootstrap.php';
auth_require_login();

header('Cache-Control: no-store');

// Set `$allow_viewer = true` from endpoints whose own per-action logic decides
// whether a viewer-role caller may proceed (admin_users self password change,
// twofa self management). Every other endpoint that mutates state should leave
// it false so viewers get a clean 403 before they reach any write code.
function require_csrf_unless_get($allow_viewer = false) {
    $method = $_SERVER['REQUEST_METHOD'] ?? '';
    if ($method === 'GET' || $method === 'HEAD') return;
    // Only POST is supported for mutating actions. Reject PUT/PATCH/DELETE/OPTIONS
    // outright so method-confusion probes don't slip past CSRF expectations.
    if ($method !== 'POST') {
        header('Allow: GET, POST');
        json_error('Method not allowed.', 405);
    }
    csrf_require_post();
    if (!$allow_viewer) {
        auth_require_admin();
    }
}

function read_action() {
    $body = json_request_body();
    $action = '';
    if (isset($body['action'])) {
        $action = $body['action'];
    } elseif (isset($_GET['action'])) {
        $action = $_GET['action'];
    } elseif (isset($_POST['action'])) {
        $action = $_POST['action'];
    }
    return [$action, $body];
}

function next_public_id($table, $where = '1', $params = []) {
    $rows = db_all("SELECT public_id FROM $table WHERE $where", $params);
    $max = 0;
    foreach ($rows as $r) {
        if (ctype_digit((string)$r['public_id'])) {
            $n = (int)$r['public_id'];
            if ($n > $max) { $max = $n; }
        }
    }
    return (string)($max + 1);
}
