core/apps/webapp/app/routes/api.oauth.clients.$clientId.tsx
2025-08-21 18:44:10 +05:30

205 lines
5.4 KiB
TypeScript

import {
type ActionFunctionArgs,
type LoaderFunctionArgs,
json,
} from "@remix-run/node";
import { requireAuth } from "~/utils/auth-helper";
import crypto from "crypto";
import { prisma } from "~/db.server";
// GET /api/oauth/clients/:clientId - Get specific OAuth client
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
const user = await requireAuth(request);
const { clientId } = params;
if (!clientId) {
return json({ error: "Client ID is required" }, { status: 400 });
}
try {
// Get user's workspace
const userRecord = await prisma.user.findUnique({
where: { id: user.id },
include: { Workspace: true },
});
if (!userRecord?.Workspace) {
return json({ error: "No workspace found" }, { status: 404 });
}
const client = await prisma.oAuthClient.findFirst({
where: {
id: clientId,
workspaceId: userRecord.Workspace.id,
},
select: {
id: true,
clientId: true,
name: true,
description: true,
redirectUris: true,
allowedScopes: true,
requirePkce: true,
logoUrl: true,
homepageUrl: true,
isActive: true,
createdAt: true,
updatedAt: true,
createdBy: {
select: {
id: true,
email: true,
name: true,
},
},
},
});
if (!client) {
return json({ error: "OAuth client not found" }, { status: 404 });
}
return json({ client });
} catch (error) {
console.error("Error fetching OAuth client:", error);
return json({ error: "Internal server error" }, { status: 500 });
}
};
export const action = async ({ request, params }: ActionFunctionArgs) => {
const user = await requireAuth(request);
const { clientId } = params;
const method = request.method;
if (!clientId) {
return json({ error: "Client ID is required" }, { status: 400 });
}
try {
// Get user's workspace
const userRecord = await prisma.user.findUnique({
where: { id: user.id },
include: { Workspace: true },
});
if (!userRecord?.Workspace) {
return json({ error: "No workspace found" }, { status: 404 });
}
// Verify client exists and belongs to user's workspace
const existingClient = await prisma.oAuthClient.findFirst({
where: {
id: clientId,
workspaceId: userRecord.Workspace.id,
},
});
if (!existingClient) {
return json({ error: "OAuth client not found" }, { status: 404 });
}
// PATCH - Update OAuth client
if (method === "PATCH") {
const body = await request.json();
const {
name,
description,
redirectUris,
allowedScopes,
requirePkce,
logoUrl,
homepageUrl,
isActive,
} = body;
const updateData: any = {};
if (name !== undefined) updateData.name = name;
if (description !== undefined) updateData.description = description;
if (redirectUris !== undefined) {
updateData.redirectUris = Array.isArray(redirectUris)
? redirectUris.join(",")
: redirectUris;
}
if (allowedScopes !== undefined) {
updateData.allowedScopes = Array.isArray(allowedScopes)
? allowedScopes.join(",")
: allowedScopes;
}
if (requirePkce !== undefined) updateData.requirePkce = requirePkce;
if (logoUrl !== undefined) updateData.logoUrl = logoUrl;
if (homepageUrl !== undefined) updateData.homepageUrl = homepageUrl;
if (isActive !== undefined) updateData.isActive = isActive;
const updatedClient = await prisma.oAuthClient.update({
where: { id: clientId },
data: updateData,
select: {
id: true,
clientId: true,
name: true,
description: true,
redirectUris: true,
allowedScopes: true,
requirePkce: true,
logoUrl: true,
homepageUrl: true,
isActive: true,
createdAt: true,
updatedAt: true,
},
});
return json({ success: true, client: updatedClient });
}
// POST - Regenerate client secret
if (method === "POST") {
const body = await request.json();
const { action } = body;
if (action === "regenerate_secret") {
const newClientSecret = crypto.randomBytes(32).toString("hex");
const updatedClient = await prisma.oAuthClient.update({
where: { id: clientId },
data: { clientSecret: newClientSecret },
select: {
id: true,
clientId: true,
clientSecret: true,
name: true,
},
});
return json({
success: true,
client: updatedClient,
message:
"Client secret regenerated successfully. Save it securely - it won't be shown again.",
});
}
return json({ error: "Invalid action" }, { status: 400 });
}
// DELETE - Delete OAuth client
if (method === "DELETE") {
await prisma.oAuthClient.delete({
where: { id: clientId },
});
return json({
success: true,
message: "OAuth client deleted successfully",
});
}
return json({ error: "Method not allowed" }, { status: 405 });
} catch (error) {
console.error("Error managing OAuth client:", error);
return json({ error: "Internal server error" }, { status: 500 });
}
};