mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-02 20:30:10 +00:00
dc7e557694
Introduces a full notification system with support for Discord and Pushover backends, event triggers, and message formatting. Adds backend services, processors, and API endpoints for managing notifications, as well as a new Notifications tab in the admin settings UI. Updates documentation, database schema, and tests to cover notification features and approval workflow improvements. Also changes project license from MIT to AGPL v3.
130 lines
3.8 KiB
TypeScript
130 lines
3.8 KiB
TypeScript
/**
|
|
* Component: Notification Backend API
|
|
* Documentation: documentation/backend/services/notifications.md
|
|
*/
|
|
|
|
import { NextRequest, NextResponse } from 'next/server';
|
|
import { requireAuth, requireAdmin, AuthenticatedRequest } from '@/lib/middleware/auth';
|
|
import { prisma } from '@/lib/db';
|
|
import { getNotificationService, NotificationBackendType } from '@/lib/services/notification.service';
|
|
import { RMABLogger } from '@/lib/utils/logger';
|
|
import { z } from 'zod';
|
|
|
|
const logger = RMABLogger.create('API.Admin.Notifications');
|
|
|
|
const CreateBackendSchema = z.object({
|
|
type: z.enum(['discord', 'pushover', 'email', 'slack', 'telegram', 'webhook']),
|
|
name: z.string().min(1),
|
|
config: z.record(z.any()),
|
|
events: z.array(z.enum(['request_pending_approval', 'request_approved', 'request_available', 'request_error'])).min(1),
|
|
enabled: z.boolean().default(true),
|
|
});
|
|
|
|
/**
|
|
* GET /api/admin/notifications
|
|
* List all notification backends (sensitive values masked)
|
|
*/
|
|
export async function GET(request: NextRequest) {
|
|
return requireAuth(request, async (req: AuthenticatedRequest) => {
|
|
return requireAdmin(req, async () => {
|
|
try {
|
|
const backends = await prisma.notificationBackend.findMany({
|
|
orderBy: { createdAt: 'desc' },
|
|
});
|
|
|
|
const notificationService = getNotificationService();
|
|
|
|
// Mask sensitive config values
|
|
const maskedBackends = backends.map((backend) => ({
|
|
...backend,
|
|
config: notificationService.maskConfig(backend.type as NotificationBackendType, backend.config),
|
|
}));
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
backends: maskedBackends,
|
|
});
|
|
} catch (error) {
|
|
logger.error('Failed to fetch notification backends', {
|
|
error: error instanceof Error ? error.message : String(error),
|
|
});
|
|
|
|
return NextResponse.json(
|
|
{
|
|
error: 'FetchError',
|
|
message: 'Failed to fetch notification backends',
|
|
},
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* POST /api/admin/notifications
|
|
* Create new notification backend
|
|
*/
|
|
export async function POST(request: NextRequest) {
|
|
return requireAuth(request, async (req: AuthenticatedRequest) => {
|
|
return requireAdmin(req, async () => {
|
|
try {
|
|
const body = await request.json();
|
|
const { type, name, config, events, enabled } = CreateBackendSchema.parse(body);
|
|
|
|
const notificationService = getNotificationService();
|
|
|
|
// Encrypt sensitive config values
|
|
const encryptedConfig = notificationService.encryptConfig(type, config);
|
|
|
|
// Create backend
|
|
const backend = await prisma.notificationBackend.create({
|
|
data: {
|
|
type,
|
|
name,
|
|
config: encryptedConfig,
|
|
events,
|
|
enabled,
|
|
},
|
|
});
|
|
|
|
logger.info(`Created notification backend: ${name} (${type})`, {
|
|
backendId: backend.id,
|
|
adminId: req.user?.sub,
|
|
});
|
|
|
|
// Return with masked values
|
|
return NextResponse.json({
|
|
success: true,
|
|
backend: {
|
|
...backend,
|
|
config: notificationService.maskConfig(type, backend.config),
|
|
},
|
|
}, { status: 201 });
|
|
} catch (error) {
|
|
logger.error('Failed to create notification backend', {
|
|
error: error instanceof Error ? error.message : String(error),
|
|
});
|
|
|
|
if (error instanceof z.ZodError) {
|
|
return NextResponse.json(
|
|
{
|
|
error: 'ValidationError',
|
|
details: error.errors,
|
|
},
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
return NextResponse.json(
|
|
{
|
|
error: 'CreateError',
|
|
message: 'Failed to create notification backend',
|
|
},
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
});
|
|
});
|
|
}
|