mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-06-27 06:05:54 +08:00
128 lines
4.6 KiB
TypeScript
128 lines
4.6 KiB
TypeScript
import express from 'express';
|
|
|
|
import { notificationChannelEndpointsDb, notificationPreferencesDb } from '@/modules/database/index.js';
|
|
|
|
const router = express.Router();
|
|
|
|
function readText(value: unknown): string {
|
|
return typeof value === 'string' ? value.trim() : '';
|
|
}
|
|
|
|
function sanitizeEndpoint(endpoint: any) {
|
|
return {
|
|
id: endpoint.id,
|
|
channel: endpoint.channel,
|
|
endpointId: endpoint.endpoint_id,
|
|
label: endpoint.label,
|
|
metadata: notificationChannelEndpointsDb.parseMetadata(endpoint.metadata_json),
|
|
enabled: Boolean(endpoint.enabled),
|
|
lastSeenAt: endpoint.last_seen_at,
|
|
createdAt: endpoint.created_at,
|
|
updatedAt: endpoint.updated_at,
|
|
};
|
|
}
|
|
|
|
function readUserId(req: express.Request): number {
|
|
const userId = Number((req as any).user?.id);
|
|
if (!Number.isInteger(userId) || userId <= 0) {
|
|
throw new Error('Authenticated user is missing');
|
|
}
|
|
return userId;
|
|
}
|
|
|
|
function updateChannelPreference(userId: number, channel: string): unknown {
|
|
const currentPrefs = notificationPreferencesDb.getPreferences(userId);
|
|
const hasEnabledEndpoint = notificationChannelEndpointsDb.getEnabledEndpoints(userId, channel).length > 0;
|
|
return notificationPreferencesDb.updatePreferences(userId, {
|
|
...currentPrefs,
|
|
channels: { ...currentPrefs.channels, [channel]: hasEnabledEndpoint },
|
|
});
|
|
}
|
|
|
|
router.get('/endpoints', (req, res) => {
|
|
try {
|
|
const channel = readText(req.query.channel);
|
|
if (!channel) {
|
|
return res.status(400).json({ error: 'channel is required' });
|
|
}
|
|
|
|
const userId = readUserId(req);
|
|
const endpoints = notificationChannelEndpointsDb
|
|
.getEndpoints(userId, channel)
|
|
.map(sanitizeEndpoint);
|
|
return res.json({ success: true, endpoints });
|
|
} catch (error) {
|
|
console.error('Error fetching notification endpoints:', error);
|
|
return res.status(500).json({ error: 'Failed to fetch notification endpoints' });
|
|
}
|
|
});
|
|
|
|
router.post('/endpoints/current', (req, res) => {
|
|
try {
|
|
const { channel, endpointId, label, metadata = {}, enabled = true } = req.body || {};
|
|
const normalizedChannel = readText(channel);
|
|
const normalizedEndpointId = readText(endpointId);
|
|
if (!normalizedChannel || !normalizedEndpointId) {
|
|
return res.status(400).json({ error: 'channel and endpointId are required' });
|
|
}
|
|
|
|
const userId = readUserId(req);
|
|
const endpoint = notificationChannelEndpointsDb.upsertEndpoint({
|
|
userId,
|
|
channel: normalizedChannel,
|
|
endpointId: normalizedEndpointId,
|
|
label,
|
|
metadata: metadata && typeof metadata === 'object' ? metadata : {},
|
|
enabled: enabled !== false,
|
|
});
|
|
|
|
const preferences = updateChannelPreference(userId, normalizedChannel);
|
|
return res.json({ success: true, endpoint: sanitizeEndpoint(endpoint), preferences });
|
|
} catch (error) {
|
|
console.error('Error registering notification endpoint:', error);
|
|
return res.status(500).json({ error: 'Failed to register notification endpoint' });
|
|
}
|
|
});
|
|
|
|
router.patch('/endpoints/:channel/:endpointId', (req, res) => {
|
|
try {
|
|
const { channel, endpointId } = req.params;
|
|
const { enabled } = req.body || {};
|
|
if (typeof enabled !== 'boolean') {
|
|
return res.status(400).json({ error: 'enabled must be a boolean' });
|
|
}
|
|
|
|
const userId = readUserId(req);
|
|
const updated = notificationChannelEndpointsDb.setEndpointEnabled(userId, channel, endpointId, enabled);
|
|
if (!updated) {
|
|
return res.status(404).json({ error: 'Notification endpoint not found' });
|
|
}
|
|
|
|
const endpoint = notificationChannelEndpointsDb.getEndpoint(userId, channel, endpointId);
|
|
const preferences = updateChannelPreference(userId, channel);
|
|
return res.json({ success: true, endpoint: endpoint ? sanitizeEndpoint(endpoint) : null, preferences });
|
|
} catch (error) {
|
|
console.error('Error updating notification endpoint:', error);
|
|
return res.status(500).json({ error: 'Failed to update notification endpoint' });
|
|
}
|
|
});
|
|
|
|
router.delete('/endpoints/:channel/:endpointId', (req, res) => {
|
|
try {
|
|
const { channel, endpointId } = req.params;
|
|
const userId = readUserId(req);
|
|
const removed = notificationChannelEndpointsDb.removeEndpoint(userId, channel, endpointId);
|
|
if (!removed) {
|
|
return res.status(404).json({ error: 'Notification endpoint not found' });
|
|
}
|
|
|
|
const preferences = updateChannelPreference(userId, channel);
|
|
return res.json({ success: true, preferences });
|
|
} catch (error) {
|
|
console.error('Error removing notification endpoint:', error);
|
|
return res.status(500).json({ error: 'Failed to remove notification endpoint' });
|
|
}
|
|
});
|
|
|
|
export default router;
|