init: kovakemlak-crm project scaffold
- Next.js 16 + Appwrite multi-tenant emlak CRM - Database: kovakemlak-db (properties, customers, customer_searches, property_matches, presentations, investors, activities, tenant_settings) - Same stack as isletmem-kovakcrm (shadcn/ui template base) - Modules: portföy, müşteri takibi, arama kriterleri, otomatik eşleştirme, sunum linki, yatırımcı portalı
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import "server-only";
|
||||
|
||||
import { headers } from "next/headers";
|
||||
import { ID, Permission, Role } from "node-appwrite";
|
||||
|
||||
import { createAdminClient } from "./server";
|
||||
import { DATABASE_ID, TABLES, type AuditAction } from "./schema";
|
||||
|
||||
export async function logAudit(args: {
|
||||
tenantId: string;
|
||||
userId: string;
|
||||
action: AuditAction;
|
||||
entityType: string;
|
||||
entityId: string;
|
||||
changes?: Record<string, unknown>;
|
||||
}) {
|
||||
try {
|
||||
const h = await headers();
|
||||
const ipAddress =
|
||||
h.get("x-forwarded-for")?.split(",")[0]?.trim() || h.get("x-real-ip") || undefined;
|
||||
const userAgent = h.get("user-agent")?.slice(0, 500) || undefined;
|
||||
|
||||
const { tablesDB } = createAdminClient();
|
||||
await tablesDB.createRow(
|
||||
DATABASE_ID,
|
||||
TABLES.auditLogs,
|
||||
ID.unique(),
|
||||
{
|
||||
tenantId: args.tenantId,
|
||||
userId: args.userId,
|
||||
action: args.action,
|
||||
entityType: args.entityType,
|
||||
entityId: args.entityId,
|
||||
changes: args.changes ? JSON.stringify(args.changes).slice(0, 10000) : undefined,
|
||||
ipAddress,
|
||||
userAgent,
|
||||
},
|
||||
[Permission.read(Role.team(args.tenantId))],
|
||||
);
|
||||
} catch {
|
||||
// audit failures must never block the user-facing operation
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user