feat(sase): user management Phase 7a — listing + detail (RO)
Adım 1 — User listesi sayfası - Extend Sase RO Prisma schema: Plan, Brand, UserBrand, BankAccount, Payment, QueryLog - listUsers() + listPlans() repo with filter/sort/page in apps/web/src/lib/sase/users.ts - /projects/sase/users — TanStack-free server-rendered table with URL-param filters (plan multi-select, status, activity preset, search) + pager - Sase landing "Users →" link Adım 2 — User detay 360° - /projects/sase/users/[id] — header (masked email + audit-logged reveal button) + 5 tabs: Özet · Subscription & Billing · Kullanım · Aktivite · Audit - Usage stats: 30d/90d/lifetime queries, success rate, avg response, daily sparkline, brand/source distribution, top VINs - Timeline: merged signup + subscriptions + payments + recent queries - User-scoped audit trail (AuditLog endpoint LIKE filter) - POST /api/sase/users/[id]/reveal-email — audit-logged full email reveal teknikborc.md — Phase 7 PRD vs Sase.tr şeması gap'leri kaydedildi (EFT yok, B2B yok, API keys/webhooks yok, vb.) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
41
apps/web/src/app/api/sase/users/[id]/reveal-email/route.ts
Normal file
41
apps/web/src/app/api/sase/users/[id]/reveal-email/route.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { headers } from "next/headers";
|
||||
import { auth } from "@/lib/auth";
|
||||
import { saseDb } from "@/lib/db-sase";
|
||||
import { writeAudit } from "@/lib/audit";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export async function POST(
|
||||
_req: Request,
|
||||
ctx: { params: Promise<{ id: string }> },
|
||||
) {
|
||||
const session = await auth.api.getSession({ headers: await headers() });
|
||||
if (!session) {
|
||||
return NextResponse.json({ ok: false, error: "unauthenticated" }, { status: 401 });
|
||||
}
|
||||
const { id } = await ctx.params;
|
||||
|
||||
const user = await saseDb.user.findUnique({
|
||||
where: { id },
|
||||
select: { email: true },
|
||||
});
|
||||
if (!user) {
|
||||
await writeAudit({
|
||||
projectKey: "sase",
|
||||
endpoint: `/api/sase/users/${id}/reveal-email`,
|
||||
method: "POST",
|
||||
responseStatus: 404,
|
||||
});
|
||||
return NextResponse.json({ ok: false, error: "not_found" }, { status: 404 });
|
||||
}
|
||||
|
||||
await writeAudit({
|
||||
projectKey: "sase",
|
||||
endpoint: `/api/sase/users/${id}/reveal-email`,
|
||||
method: "POST",
|
||||
responseStatus: 200,
|
||||
});
|
||||
|
||||
return NextResponse.json({ ok: true, email: user.email });
|
||||
}
|
||||
Reference in New Issue
Block a user