113 lines
3.2 KiB
PHP
113 lines
3.2 KiB
PHP
<?php
|
|
/**
|
|
* POST /api/hub/vcgateway/visitor/auth.php
|
|
*
|
|
* Authenticate as a visitor using an invite link token.
|
|
* Creates a visitor session and returns a VisitorToken for subsequent API calls.
|
|
* No user account or Sprinter agent required.
|
|
*
|
|
* Body:
|
|
* InviteToken string required The invite link token from the URL
|
|
* DisplayName string optional Visitor's display name (default: "Visitor")
|
|
*
|
|
* Response:
|
|
* OK, VisitorToken, VisitorID, DisplayName, AllowedChannels[], HostAddress
|
|
*/
|
|
|
|
require_once __DIR__ . '/../helpers.php';
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'method_not_allowed'], 405);
|
|
}
|
|
|
|
$body = readJsonBody();
|
|
|
|
$inviteToken = trim($body['InviteToken'] ?? '');
|
|
if (empty($inviteToken)) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'invite_token_required'], 400);
|
|
}
|
|
|
|
// Look up the invite link
|
|
$link = queryOne(
|
|
"SELECT * FROM Hub_InviteLinks WHERE Token = ? LIMIT 1",
|
|
[$inviteToken]
|
|
);
|
|
|
|
if (!$link) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'invalid_invite_token'], 404);
|
|
}
|
|
|
|
// Check if revoked
|
|
if ($link['IsRevoked']) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'invite_revoked'], 403);
|
|
}
|
|
|
|
// Check expiration
|
|
if ($link['ExpiresAt'] && strtotime($link['ExpiresAt']) < time()) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'invite_expired'], 403);
|
|
}
|
|
|
|
// Check max uses
|
|
if ($link['MaxUses'] > 0 && $link['UseCount'] >= $link['MaxUses']) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'invite_exhausted'], 403);
|
|
}
|
|
|
|
// Sanitize display name
|
|
$displayName = trim($body['DisplayName'] ?? '');
|
|
if (empty($displayName)) {
|
|
$displayName = 'Visitor';
|
|
}
|
|
$displayName = substr($displayName, 0, 100);
|
|
// Strip any HTML/script
|
|
$displayName = htmlspecialchars($displayName, ENT_QUOTES, 'UTF-8');
|
|
|
|
// Generate visitor token
|
|
$visitorToken = bin2hex(random_bytes(24));
|
|
|
|
// Create the visitor session
|
|
queryTimed(
|
|
"INSERT INTO Hub_Visitors (InviteLinkID, VisitorToken, DisplayName)
|
|
VALUES (?, ?, ?)",
|
|
[(int)$link['ID'], $visitorToken, $displayName]
|
|
);
|
|
|
|
$visitorId = (int)lastInsertId();
|
|
|
|
// Increment use count on the invite link
|
|
queryTimed(
|
|
"UPDATE Hub_InviteLinks SET UseCount = UseCount + 1 WHERE ID = ?",
|
|
[(int)$link['ID']]
|
|
);
|
|
|
|
// Return the session info
|
|
$allowedChannels = json_decode($link['AllowedChannels'], true);
|
|
|
|
// Fetch channel details for the allowed channels
|
|
$channelDetails = [];
|
|
if (!empty($allowedChannels)) {
|
|
$placeholders = implode(',', array_fill(0, count($allowedChannels), '?'));
|
|
$channels = queryTimed(
|
|
"SELECT ID, Name, DisplayName, Purpose, ChannelType
|
|
FROM Hub_Channels
|
|
WHERE ID IN ($placeholders) AND IsArchived = 0",
|
|
array_map('intval', $allowedChannels)
|
|
);
|
|
foreach ($channels as $ch) {
|
|
$channelDetails[] = [
|
|
'ID' => (int)$ch['ID'],
|
|
'Name' => $ch['Name'],
|
|
'DisplayName' => $ch['DisplayName'],
|
|
'Purpose' => $ch['Purpose'],
|
|
'ChannelType' => $ch['ChannelType'],
|
|
];
|
|
}
|
|
}
|
|
|
|
jsonResponse([
|
|
'OK' => true,
|
|
'VisitorToken' => $visitorToken,
|
|
'VisitorID' => $visitorId,
|
|
'DisplayName' => $displayName,
|
|
'AllowedChannels' => $channelDetails,
|
|
'HostAddress' => $link['HostAddress'],
|
|
]);
|