payfrit-api/api/hub/vcgateway/invites/list.php
Mike cd373dd616 Add VC Gateway endpoints for invite links, visitor auth, DM, and rate limiting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:34:52 +00:00

104 lines
2.9 KiB
PHP

<?php
/**
* GET /api/hub/vcgateway/invites/list.php
*
* List invite links. Optionally filter by status.
* Requires agent auth (X-Agent-Address header).
*
* Query params:
* Status string optional "active" | "revoked" | "expired" | "all" (default: "all")
* Limit int optional Max results (default: 50, max: 200)
* Offset int optional Pagination offset (default: 0)
*
* Response:
* OK, Links[], Total
*/
require_once __DIR__ . '/../helpers.php';
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
jsonResponse(['OK' => false, 'ERROR' => 'method_not_allowed'], 405);
}
$agentAddress = requireAgentAuth();
$status = strtolower(trim($_GET['Status'] ?? 'all'));
$limit = min(200, max(1, (int)($_GET['Limit'] ?? 50)));
$offset = max(0, (int)($_GET['Offset'] ?? 0));
// Build WHERE clause
$where = [];
$params = [];
switch ($status) {
case 'active':
$where[] = 'il.IsRevoked = 0';
$where[] = '(il.ExpiresAt IS NULL OR il.ExpiresAt > NOW())';
$where[] = '(il.MaxUses = 0 OR il.UseCount < il.MaxUses)';
break;
case 'revoked':
$where[] = 'il.IsRevoked = 1';
break;
case 'expired':
$where[] = 'il.IsRevoked = 0';
$where[] = 'il.ExpiresAt IS NOT NULL AND il.ExpiresAt <= NOW()';
break;
case 'all':
default:
// No filter
break;
}
$whereClause = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';
// Count total
$countRow = queryOne(
"SELECT COUNT(*) AS cnt FROM Hub_InviteLinks il $whereClause",
$params
);
$total = (int)($countRow['cnt'] ?? 0);
// Fetch links
$rows = queryTimed(
"SELECT il.*,
(SELECT COUNT(*) FROM Hub_Visitors v WHERE v.InviteLinkID = il.ID) AS VisitorCount
FROM Hub_InviteLinks il
$whereClause
ORDER BY il.CreatedAt DESC
LIMIT $limit OFFSET $offset",
$params
);
$links = [];
foreach ($rows as $row) {
// Determine computed status
$computedStatus = 'active';
if ($row['IsRevoked']) {
$computedStatus = 'revoked';
} elseif ($row['ExpiresAt'] && strtotime($row['ExpiresAt']) <= time()) {
$computedStatus = 'expired';
} elseif ($row['MaxUses'] > 0 && $row['UseCount'] >= $row['MaxUses']) {
$computedStatus = 'exhausted';
}
$links[] = [
'ID' => (int)$row['ID'],
'Token' => $row['Token'],
'Label' => $row['Label'],
'AllowedChannels' => json_decode($row['AllowedChannels'], true),
'HostAddress' => $row['HostAddress'],
'ExpiresAt' => $row['ExpiresAt'] ? toISO8601($row['ExpiresAt']) : null,
'MaxUses' => (int)$row['MaxUses'],
'UseCount' => (int)$row['UseCount'],
'VisitorCount' => (int)$row['VisitorCount'],
'Status' => $computedStatus,
'CreatedBy' => $row['CreatedBy'],
'CreatedAt' => toISO8601($row['CreatedAt']),
];
}
jsonResponse([
'OK' => true,
'Links' => $links,
'Total' => $total,
]);