feat(all): add organisation, api updates with organisation check

Now calling run endpoints with GET, POST will check against the API key, whether there is org_id or not, if the operation workflow doesnt match with the user org or user id, will return with workflow not found, run not found
This commit is contained in:
BennyKok
2024-01-01 23:13:01 +08:00
parent 75776e6d8f
commit c66de45522
19 changed files with 907 additions and 59 deletions
+62 -16
View File
@@ -25,26 +25,57 @@ async function checkToken(request: Request) {
const token = request.headers.get("Authorization")?.split(" ")?.[1]; // Assuming token is sent as "Bearer your_token"
const userData = token ? parseJWT(token) : undefined;
if (!userData || token === undefined) {
return new NextResponse("Invalid or expired token", {
status: 401,
});
return {
error: new NextResponse("Invalid or expired token", {
status: 401,
}),
};
} else {
const revokedKey = await isKeyRevoked(token);
if (revokedKey)
return new NextResponse("Revoked token", {
status: 401,
});
return {
error: new NextResponse("Revoked token", {
status: 401,
}),
};
}
return {
data: userData,
};
}
export async function GET(request: Request) {
const invalidRequest = await checkToken(request);
if (invalidRequest) return invalidRequest;
const apiKeyTokenData = await checkToken(request);
if (apiKeyTokenData.error) return apiKeyTokenData.error;
const [data, error] = await parseDataSafe(Request2, request);
if (!data || error) return error;
const run = await getRunsData(data.run_id);
// return NextResponse.json(
// await db
// .select()
// .from(workflowTable)
// .innerJoin(
// workflowRunsTable,
// eq(workflowTable.id, workflowRunsTable.workflow_id)
// )
// .where(
// and(
// eq(workflowTable.id, workflowRunsTable.workflow_id),
// apiKeyTokenData.data.org_id
// ? eq(workflowTable.org_id, apiKeyTokenData.data.org_id)
// : eq(workflowTable.user_id, apiKeyTokenData.data.user_id!)
// )
// ),
// {
// status: 200,
// }
// );
const run = await getRunsData(apiKeyTokenData.data, data.run_id);
if (!run) return new NextResponse("Run not found", { status: 404 });
if (run?.status === "success" && run?.outputs?.length > 0) {
for (let i = 0; i < run.outputs.length; i++) {
@@ -74,8 +105,8 @@ export async function GET(request: Request) {
}
export async function POST(request: Request) {
const invalidRequest = await checkToken(request);
if (invalidRequest) return invalidRequest;
const apiKeyTokenData = await checkToken(request);
if (apiKeyTokenData.error) return apiKeyTokenData.error;
const [data, error] = await parseDataSafe(Request, request);
if (!data || error) return error;
@@ -87,16 +118,31 @@ export async function POST(request: Request) {
try {
const deploymentData = await db.query.deploymentsTable.findFirst({
where: eq(deploymentsTable.id, deployment_id),
with: {
machine: true,
version: {
with: {
workflow: {
columns: {
org_id: true,
user_id: true,
},
},
},
},
},
});
if (!deploymentData) throw new Error("Deployment not found");
const run_id = await createRun(
const run_id = await createRun({
origin,
deploymentData.workflow_version_id,
deploymentData.machine_id,
inputs
);
workflow_version_id: deploymentData.version,
machine_id: deploymentData.machine,
inputs,
isManualRun: false,
apiUser: apiKeyTokenData.data,
});
if ("error" in run_id) throw new Error(run_id.error);
+1
View File
@@ -79,6 +79,7 @@ export async function POST(request: Request) {
.values({
user_id,
name: workflow_name,
org_id: org_id,
})
.returning();
+10 -3
View File
@@ -1,8 +1,8 @@
import "./globals.css";
import { NavbarRight } from "@/components/NavbarRight";
import { NavbarMenu } from "@/components/NavbarMenu";
import { Button } from "@/components/ui/button";
import { TooltipProvider } from "@/components/ui/tooltip";
import { ClerkProvider, UserButton } from "@clerk/nextjs";
import { ClerkProvider, OrganizationSwitcher, UserButton } from "@clerk/nextjs";
import { Github } from "lucide-react";
import type { Metadata } from "next";
import meta from "next-gen/config";
@@ -54,9 +54,16 @@ export default function RootLayout({
>
{meta.name}
</a>
<NavbarRight />
<OrganizationSwitcher
appearance={{
elements: {
rootBox: "flex items-center justify-center",
},
}}
/>
</div>
<div className="flex flex-row items-center gap-2">
<NavbarMenu />
<Button
asChild
variant="link"
+6 -3
View File
@@ -2,14 +2,14 @@ import { MachineList } from "@/components/MachineList";
import { db } from "@/db/db";
import { machinesTable } from "@/db/schema";
import { auth } from "@clerk/nextjs";
import { desc, eq } from "drizzle-orm";
import { desc, eq, isNull, and } from "drizzle-orm";
export default function Page() {
return <MachineListServer />;
}
async function MachineListServer() {
const { userId } = await auth();
const { userId, orgId } = await auth();
if (!userId) {
return <div>No auth</div>;
@@ -17,7 +17,10 @@ async function MachineListServer() {
const machines = await db.query.machinesTable.findMany({
orderBy: desc(machinesTable.updated_at),
where: eq(machinesTable.user_id, userId),
where:
orgId != undefined
? eq(machinesTable.org_id, orgId)
: and(eq(machinesTable.user_id, userId), isNull(machinesTable.org_id)),
});
return (
+6 -3
View File
@@ -2,14 +2,14 @@ import { WorkflowList } from "@/components/WorkflowList";
import { db } from "@/db/db";
import { usersTable, workflowTable, workflowVersionTable } from "@/db/schema";
import { auth, clerkClient } from "@clerk/nextjs";
import { desc, eq } from "drizzle-orm";
import { and, desc, eq, isNull } from "drizzle-orm";
export default function Home() {
return <WorkflowServer />;
}
async function WorkflowServer() {
const { userId } = await auth();
const { userId, orgId } = await auth();
if (!userId) {
return <div>No auth</div>;
@@ -36,7 +36,10 @@ async function WorkflowServer() {
},
},
orderBy: desc(workflowTable.updated_at),
where: eq(workflowTable.user_id, userId),
where:
orgId != undefined
? eq(workflowTable.org_id, orgId)
: and(eq(workflowTable.user_id, userId), isNull(workflowTable.org_id)),
});
return (