New endpoints under /api/hub/channels/: - create.php: Create channel with type (public/private/direct), auto-add creator as owner - list.php: List channels with filters (type, agent membership, archived, pagination) - get.php: Get channel by ID or Name, includes member list - update.php: Update display name, purpose, archive status (admin/owner only) - delete.php: Hard-delete channel (owner only), FK cascade removes members - members.php: List channel members with agent info - join.php: Join public channels (private requires invite) - leave.php: Leave channel (owners blocked from leaving) Database: Hub_Channels + Hub_ChannelMembers tables with FK cascade. Task #59 (T51-Sub1) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
98 lines
2.7 KiB
PHP
98 lines
2.7 KiB
PHP
<?php
|
|
/**
|
|
* POST /api/hub/channels/update.php
|
|
*
|
|
* Update a channel's metadata.
|
|
*
|
|
* Body:
|
|
* ID int REQUIRED
|
|
* DisplayName string optional
|
|
* Purpose string optional
|
|
* IsArchived bool optional
|
|
* Agent string REQUIRED requesting agent (must be admin/owner)
|
|
*
|
|
* Response: { OK: true, Channel: { ... } }
|
|
*/
|
|
|
|
require_once __DIR__ . '/../../helpers.php';
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'method_not_allowed'], 405);
|
|
}
|
|
|
|
$body = readJsonBody();
|
|
|
|
$id = (int) ($body['ID'] ?? 0);
|
|
$agent = trim($body['Agent'] ?? '');
|
|
|
|
if ($id <= 0) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'id_required']);
|
|
}
|
|
if ($agent === '') {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'agent_required']);
|
|
}
|
|
|
|
// Verify channel exists
|
|
$channel = queryOne("SELECT * FROM Hub_Channels WHERE ID = ?", [$id]);
|
|
if (!$channel) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'channel_not_found'], 404);
|
|
}
|
|
|
|
// Check permissions: must be admin or owner
|
|
$membership = queryOne(
|
|
"SELECT Role FROM Hub_ChannelMembers WHERE ChannelID = ? AND AgentAddress = ?",
|
|
[$id, $agent]
|
|
);
|
|
if (!$membership || !in_array($membership['Role'], ['admin', 'owner'], true)) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'not_authorized'], 403);
|
|
}
|
|
|
|
// Build update fields
|
|
$sets = [];
|
|
$params = [];
|
|
|
|
if (isset($body['DisplayName'])) {
|
|
$val = trim($body['DisplayName']);
|
|
if (strlen($val) > 200) $val = substr($val, 0, 200);
|
|
$sets[] = 'DisplayName = ?';
|
|
$params[] = $val;
|
|
}
|
|
|
|
if (isset($body['Purpose'])) {
|
|
$val = trim($body['Purpose']);
|
|
if (strlen($val) > 500) $val = substr($val, 0, 500);
|
|
$sets[] = 'Purpose = ?';
|
|
$params[] = $val;
|
|
}
|
|
|
|
if (isset($body['IsArchived'])) {
|
|
$sets[] = 'IsArchived = ?';
|
|
$params[] = $body['IsArchived'] ? 1 : 0;
|
|
}
|
|
|
|
if (count($sets) === 0) {
|
|
jsonResponse(['OK' => false, 'ERROR' => 'nothing_to_update']);
|
|
}
|
|
|
|
$params[] = $id;
|
|
queryTimed("UPDATE Hub_Channels SET " . implode(', ', $sets) . " WHERE ID = ?", $params);
|
|
|
|
// Fetch updated
|
|
$channel = queryOne("SELECT * FROM Hub_Channels WHERE ID = ?", [$id]);
|
|
$memberCount = queryOne("SELECT COUNT(*) AS cnt FROM Hub_ChannelMembers WHERE ChannelID = ?", [$id]);
|
|
|
|
jsonResponse([
|
|
'OK' => true,
|
|
'Channel' => [
|
|
'ID' => (int) $channel['ID'],
|
|
'Name' => $channel['Name'],
|
|
'DisplayName' => $channel['DisplayName'],
|
|
'Purpose' => $channel['Purpose'],
|
|
'ChannelType' => $channel['ChannelType'],
|
|
'CreatedBy' => $channel['CreatedBy'],
|
|
'IsArchived' => (bool) $channel['IsArchived'],
|
|
'CreatedAt' => toISO8601($channel['CreatedAt']),
|
|
'UpdatedAt' => toISO8601($channel['UpdatedAt']),
|
|
'MemberCount' => (int) ($memberCount['cnt'] ?? 0),
|
|
],
|
|
]);
|