/
ncit
/
c4panelmodel
Обзор
Документация
Войти
/
ncit
/
c4panelmodel
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/lib/server/services/technology.ts
134 строки
5 KB
ncit
feat: implement full IcePanel feature clone (Phases 1-8)
09 июн 2026, 11:13
09 июн 2026, 11:13
858c15a
Код
Авторство
О чём код?
import { db } from '$lib/server/db'; /** Technology catalog management. */ export async function listTechnologies(projectId: string) { return db.technology.findMany({ where: { OR: [{ projectId }, { projectId: null }] }, include: { _count: { select: { objects: true } } }, orderBy: [{ category: 'asc' }, { name: 'asc' }] }); } export async function createTechnology(projectId: string, input: { name: string; category: string; description?: string; docUrl?: string; iconUrl?: string; }) { return db.technology.create({ data: { ...input, projectId, isCustom: true } }); } export async function updateTechnology(techId: string, patch: Record<string, unknown>) { return db.technology.update({ where: { id: techId }, data: patch }); } export async function deleteTechnology(techId: string) { await db.technology.delete({ where: { id: techId } }); } /** Analytics: project statistics and activity. */ export async function getProjectAnalytics(projectId: string) { const [objectCount, connectionCount, diagramCount, flowCount, recentActivity] = await Promise.all([ db.modelObject.count({ where: { projectId } }), db.connection.count({ where: { projectId } }), db.diagram.count({ where: { projectId } }), db.flow.count({ where: { projectId } }), db.activity.findMany({ where: { projectId }, include: { user: { select: { name: true, email: true } } }, orderBy: { createdAt: 'desc' }, take: 20 }) ]); return { objectCount, connectionCount, diagramCount, flowCount, recentActivity }; } /** Webhook dispatch. */ export async function dispatchWebhook(workspaceId: string, event: string, payload: Record<string, unknown>) { const webhooks = await db.webhook.findMany({ where: { workspaceId, active: true, events: { has: event } } }); for (const wh of webhooks) { try { await fetch(wh.url, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ event, payload, timestamp: new Date().toISOString() }) }); } catch { // Log failure but don't block. console.error(`Webhook ${wh.id} failed for event ${event}`); } } } /** Audit log recording. */ export async function recordAudit(workspaceId: string, userId: string | undefined, action: string, entity: string, entityId: string, metadata?: Record<string, unknown>, ipAddress?: string) { await db.auditLog.create({ data: { workspaceId, userId: userId ?? null, action, entity, entityId, metadata: metadata as any ?? undefined, ipAddress: ipAddress ?? null } }); } export async function listAuditLogs(workspaceId: string, opts: { limit?: number; offset?: number; userId?: string; action?: string } = {}) { return db.auditLog.findMany({ where: { workspaceId, ...(opts.userId ? { userId: opts.userId } : {}), ...(opts.action ? { action: opts.action } : {}) }, orderBy: { createdAt: 'desc' }, take: opts.limit ?? 50, skip: opts.offset ?? 0 }); } /** API key management. */ export async function createApiKey(workspaceId: string, name: string, scopes: string[]) { const rawKey = `c4p_${crypto.randomUUID().replace(/-/g, '')}`; // Simple hash (in production use bcrypt/argon2). const encoder = new TextEncoder(); const hashBuffer = await crypto.subtle.digest('SHA-256', encoder.encode(rawKey)); const keyHash = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, '0')).join(''); const apiKey = await db.apiKey.create({ data: { workspaceId, name, keyHash, scopes } }); return { ...apiKey, key: rawKey }; // Return raw key only on creation. } export async function validateApiKey(key: string): Promise<{ workspaceId: string; scopes: string[] } | null> { const encoder = new TextEncoder(); const hashBuffer = await crypto.subtle.digest('SHA-256', encoder.encode(key)); const keyHash = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, '0')).join(''); const apiKey = await db.apiKey.findUnique({ where: { keyHash } }); if (!apiKey) return null; if (apiKey.expiresAt && apiKey.expiresAt < new Date()) return null; // Update last used. await db.apiKey.update({ where: { id: apiKey.id }, data: { lastUsedAt: new Date() } }); return { workspaceId: apiKey.workspaceId, scopes: apiKey.scopes }; } export async function listApiKeys(workspaceId: string) { return db.apiKey.findMany({ where: { workspaceId }, select: { id: true, name: true, scopes: true, expiresAt: true, lastUsedAt: true, createdAt: true }, orderBy: { createdAt: 'desc' } }); } export async function revokeApiKey(workspaceId: string, keyId: string) { await db.apiKey.deleteMany({ where: { id: keyId, workspaceId } }); }