Files
kovakemlak-crm/src/lib/appwrite/tenant-actions.ts
T

167 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use server";
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
import { AppwriteException, ID, Permission, Role, Query } from "node-appwrite";
import { createAdminClient, createSessionClient } from "./server";
import { DATABASE_ID, TABLES } from "./schema";
import { ACTIVE_TENANT_COOKIE, type WorkspaceState } from "./tenant-types";
function appwriteError(e: unknown): string {
if (e instanceof AppwriteException) {
if (e.type === "team_already_exists") return "Bu isimde bir çalışma alanı zaten var.";
if (e.type === "general_unauthorized_scope") return "Yetki hatası. Tekrar giriş yapın.";
return e.message || "Beklenmeyen bir hata oluştu.";
}
return "Bağlantı hatası. Tekrar deneyin.";
}
async function setActiveTenantCookie(tenantId: string) {
(await cookies()).set(ACTIVE_TENANT_COOKIE, tenantId, {
path: "/",
httpOnly: true,
sameSite: "strict",
secure: process.env.NODE_ENV === "production",
maxAge: 60 * 60 * 24 * 365,
});
}
export async function createWorkspaceAction(
_prev: WorkspaceState,
formData: FormData,
): Promise<WorkspaceState> {
const companyName = String(formData.get("companyName") ?? "").trim();
const companyPhone = String(formData.get("companyPhone") ?? "").trim() || undefined;
if (!companyName) {
return { ok: false, error: "Ofis adı zorunlu." };
}
let teamId: string | null = null;
const admin = createAdminClient();
try {
const session = await createSessionClient();
const user = await session.account.get();
const team = await session.teams.create(ID.unique(), companyName, ["owner"]);
teamId = team.$id;
await admin.tablesDB.createRow(
DATABASE_ID,
TABLES.tenantSettings,
ID.unique(),
{
tenantId: teamId,
officeName: companyName,
phone: companyPhone,
createdBy: user.$id,
},
[
Permission.read(Role.team(teamId)),
Permission.update(Role.team(teamId, "owner")),
Permission.update(Role.team(teamId, "admin")),
Permission.delete(Role.team(teamId, "owner")),
],
);
await session.account.updatePrefs({
...(user.prefs ?? {}),
activeTenant: teamId,
});
await setActiveTenantCookie(teamId);
} catch (e) {
if (teamId) {
try {
await admin.teams.delete(teamId);
} catch {
// best-effort cleanup; original error is what we surface
}
}
return { ok: false, error: appwriteError(e) };
}
redirect("/dashboard");
}
export async function importWorkspaceAction(
_prev: WorkspaceState,
formData: FormData,
): Promise<WorkspaceState> {
const teamId = String(formData.get("teamId") ?? "").trim();
if (!teamId) return { ok: false, error: "Geçersiz istek." };
try {
const { account, teams, tablesDB } = await createSessionClient();
const user = await account.get();
const allTeams = await teams.list();
const team = allTeams.teams.find((t) => t.$id === teamId);
if (!team) return { ok: false, error: "Çalışma alanı bulunamadı." };
const existing = await tablesDB.listRows({
databaseId: DATABASE_ID,
tableId: TABLES.tenantSettings,
queries: [Query.equal("tenantId", teamId), Query.limit(1)],
});
if (existing.total > 0) return { ok: false, error: "Bu çalışma alanı zaten mevcut." };
const admin = createAdminClient();
await admin.tablesDB.createRow(
DATABASE_ID,
TABLES.tenantSettings,
ID.unique(),
{
tenantId: teamId,
officeName: team.name,
createdBy: user.$id,
defaultCurrency: "TRY",
},
[
Permission.read(Role.team(teamId)),
Permission.update(Role.team(teamId, "owner")),
Permission.update(Role.team(teamId, "admin")),
Permission.delete(Role.team(teamId, "owner")),
],
);
await account.updatePrefs({ ...(user.prefs ?? {}), activeTenant: teamId });
await setActiveTenantCookie(teamId);
} catch (e) {
return { ok: false, error: appwriteError(e) };
}
redirect("/dashboard");
}
export async function setActiveTenantAction(tenantId: string) {
try {
const { account, teams, tablesDB } = await createSessionClient();
const user = await account.get();
const allTeams = await teams.list();
const isMember = allTeams.teams.some((t) => t.$id === tenantId);
if (!isMember) {
return { ok: false, error: "Bu çalışma alanına erişiminiz yok." };
}
// Verify this team belongs to this app (not a team from another KovakSoft product)
const settingsCheck = await tablesDB.listRows({
databaseId: DATABASE_ID,
tableId: TABLES.tenantSettings,
queries: [Query.equal("tenantId", tenantId), Query.limit(1)],
});
if (settingsCheck.total === 0) {
return { ok: false, error: "Bu çalışma alanına erişiminiz yok." };
}
await account.updatePrefs({ ...(user.prefs ?? {}), activeTenant: tenantId });
await setActiveTenantCookie(tenantId);
return { ok: true };
} catch (e) {
return { ok: false, error: appwriteError(e) };
}
}