Skip to content

Commit

Permalink
#10 Refactoring to support Global keys
Browse files Browse the repository at this point in the history
  • Loading branch information
santthosh committed Feb 5, 2024
1 parent ef14228 commit a9c2806
Show file tree
Hide file tree
Showing 17 changed files with 255 additions and 180 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
Warnings:
- You are about to drop the column `credentialsOwner` on the `Assistant` table. All the data in the column will be lost.
- You are about to drop the column `credentialsOwnerType` on the `Assistant` table. All the data in the column will be lost.
- You are about to drop the `Credentials` table. If the table is not empty, all the data it contains will be lost.
- Added the required column `limitRunsPerDay` to the `Assistant` table without a default value. This is not possible if the table is not empty.
- Added the required column `limitThreadsPerDay` to the `Assistant` table without a default value. This is not possible if the table is not empty.
*/
-- DropForeignKey
ALTER TABLE "Assistant" DROP CONSTRAINT "Assistant_credentialsOwner_credentialsOwnerType_fkey";

-- AlterTable
ALTER TABLE "Assistant" DROP COLUMN "credentialsOwner",
DROP COLUMN "credentialsOwnerType",
ADD COLUMN "accountOwner" TEXT,
ADD COLUMN "accountOwnerType" TEXT,
ADD COLUMN "extendedAssistant" JSONB,
ADD COLUMN "limitRunsPerDay" INTEGER NOT NULL,
ADD COLUMN "limitThreadsPerDay" INTEGER NOT NULL;

-- DropTable
DROP TABLE "Credentials";

-- CreateTable
CREATE TABLE "Account" (
"owner" TEXT NOT NULL,
"ownerType" TEXT NOT NULL DEFAULT 'personal',
"openAIApiKey" TEXT NOT NULL,
"assistantsPerAccount" INTEGER NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL,

CONSTRAINT "Account_pkey" PRIMARY KEY ("owner","ownerType")
);

-- AddForeignKey
ALTER TABLE "Assistant" ADD CONSTRAINT "Assistant_accountOwner_accountOwnerType_fkey" FOREIGN KEY ("accountOwner", "accountOwnerType") REFERENCES "Account"("owner", "ownerType") ON DELETE SET NULL ON UPDATE CASCADE;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
Warnings:
- You are about to drop the column `assistantsPerAccount` on the `Account` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "Account" DROP COLUMN "assistantsPerAccount",
ADD COLUMN "limitAssistants" INTEGER NOT NULL DEFAULT 2;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
Warnings:
- You are about to drop the column `extendedAssistant` on the `Assistant` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "Assistant" DROP COLUMN "extendedAssistant",
ADD COLUMN "object" JSONB;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
Warnings:
- You are about to drop the column `limitRunsPerDay` on the `Assistant` table. All the data in the column will be lost.
- You are about to drop the column `limitThreadsPerDay` on the `Assistant` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "Assistant" DROP COLUMN "limitRunsPerDay",
DROP COLUMN "limitThreadsPerDay";
28 changes: 15 additions & 13 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,24 @@ datasource db {
url = env("POSTGRES_PRISMA_URL")
}

model Credentials {
owner String
ownerType String @default("personal")
openAIApiKey String
created_at DateTime @default(now())
updated_at DateTime @updatedAt
Assistant Assistant[]
model Account {
owner String
ownerType String @default("personal")
openAIApiKey String
limitAssistants Int @default(2)
created_at DateTime @default(now())
updated_at DateTime @updatedAt
Assistant Assistant[]
@@id([owner, ownerType])
}

model Assistant {
id String @id
credentialsOwner String?
credentialsOwnerType String?
credentials Credentials? @relation(fields: [credentialsOwner, credentialsOwnerType], references: [owner, ownerType])
created_at DateTime @default(now())
updated_at DateTime @updatedAt
id String @id
object Json?
accountOwner String?
accountOwnerType String?
account Account? @relation(fields: [accountOwner, accountOwnerType], references: [owner, ownerType])
created_at DateTime @default(now())
updated_at DateTime @updatedAt
}
12 changes: 8 additions & 4 deletions src/app/api/credentials/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ export async function GET(req: NextRequest, res: NextResponse) {
const token = await getToken({ req });
if (token) {
// Signed in
let credentials = await prisma.credentials.findFirst({
let account = await prisma.account.findFirst({
where: {
owner: token.sub,
},
});

if (!credentials) {
if (!account) {
return Response.json([]);
} else {
return Response.json([credentials]);
return Response.json([{ hasCredentials: account.openAIApiKey !== null }]);
}
} else {
// Not Signed in
Expand All @@ -32,6 +32,10 @@ export async function POST(req: NextRequest, res: NextResponse) {
const body = await req.json();

if (body.openAiApiKey) {
if (body.openAiApiKey.toLowerCase() === 'use-default') {
body.openAiApiKey = process.env.OPENAI_API_KEY;
}

// Validate the Open API Key
let models = null;
try {
Expand All @@ -45,7 +49,7 @@ export async function POST(req: NextRequest, res: NextResponse) {
}

// Signed in
let credential = await prisma.credentials.upsert({
await prisma.account.upsert({
where: {
owner_ownerType: {
owner: token.sub,
Expand Down
36 changes: 16 additions & 20 deletions src/app/api/openai/assistants/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,32 @@ const getId = (req: Request) => {
return url.pathname.split('/').splice(-1, 1)[0];
};

// TODO: Use local DB instead of OpenAI API
export async function GET(req: NextRequest, res: NextResponse) {
const token = await getToken({ req });

const id = getId(req);

if (token) {
let credential = await prisma.credentials.findFirst({
let assistant = await prisma.assistant.findFirst({
where: {
owner: token.sub,
ownerType: 'personal',
id: id,
accountOwner: token.sub,
accountOwnerType: 'personal',
},
select: {
id: true,
object: true,
},
});

if (credential) {
const openai = new OpenAI({
apiKey: credential.openAIApiKey,
});

try {
const listResponse = await openai.beta.assistants.retrieve(id);
return Response.json(listResponse, { status: 200 });
} catch (err: any) {
return Response.json({ message: err.message }, { status: err.status });
}
} else {
if (!assistant) {
return Response.json(
{ message: 'OpenAI API Key does not exist' },
{ status: 400 }
{ message: 'Assistant does not exist' },
{ status: 404 }
);
}
return Response.json(assistant.object, { status: 200 });
} else {
// Not Signed in
return Response.json({ message: 'Unauthenticated' }, { status: 401 });
Expand All @@ -52,16 +48,16 @@ export async function DELETE(req: NextRequest, res: NextResponse) {
const id = getId(req);

if (token) {
let credential = await prisma.credentials.findFirst({
let account = await prisma.account.findFirst({
where: {
owner: token.sub,
ownerType: 'personal',
},
});

if (credential) {
if (account) {
const openai = new OpenAI({
apiKey: credential.openAIApiKey,
apiKey: account.openAIApiKey,
});

try {
Expand Down
49 changes: 21 additions & 28 deletions src/app/api/openai/assistants/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ export async function POST(req: NextRequest, res: NextResponse) {
const token = await getToken({ req });

if (token) {
let credential = await prisma.credentials.findFirst({
let account = await prisma.account.findFirst({
where: {
owner: token.sub,
ownerType: 'personal',
},
});

if (credential) {
if (account) {
const openai = new OpenAI({
apiKey: credential.openAIApiKey,
apiKey: account.openAIApiKey,
});

const body = await req.json();
Expand All @@ -33,18 +33,21 @@ export async function POST(req: NextRequest, res: NextResponse) {
},
update: {
id: createResponse.id,
credentialsOwner: token.sub,
credentialsOwnerType: 'personal',
accountOwner: token.sub,
accountOwnerType: 'personal',
object: createResponse as any,
},
create: {
id: createResponse.id,
credentialsOwner: token.sub,
credentialsOwnerType: 'personal',
accountOwner: token.sub,
accountOwnerType: 'personal',
object: createResponse as any,
},
});

return Response.json(createResponse, { status: 201 });
} catch (err: any) {
console.log(err);
return Response.json({ message: err.message }, { status: err.status });
}
} else {
Expand All @@ -63,30 +66,20 @@ export async function GET(req: NextRequest, res: NextResponse) {
const token = await getToken({ req });

if (token) {
let credential = await prisma.credentials.findFirst({
let assistants = await prisma.assistant.findMany({
where: {
owner: token.sub,
ownerType: 'personal',
accountOwner: token.sub,
accountOwnerType: 'personal',
},
select: {
id: true,
object: true,
},
});

if (credential) {
const openai = new OpenAI({
apiKey: credential.openAIApiKey,
});

try {
const listResponse = await openai.beta.assistants.list();
return Response.json(listResponse, { status: 200 });
} catch (err: any) {
return Response.json({ message: err.message }, { status: err.status });
}
} else {
return Response.json(
{ message: 'OpenAI API Key does not exist' },
{ status: 400 }
);
}
let assistantsCollection = assistants.map((assistant) => {
return assistant.object;
});
return Response.json(assistantsCollection, { status: 200 });
} else {
// Not Signed in
return Response.json({ message: 'Unauthenticated' }, { status: 401 });
Expand Down
7 changes: 4 additions & 3 deletions src/app/api/openai/models/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@ import { NextRequest, NextResponse } from 'next/server';

const prisma = new PrismaClient();

// Note: We should not cache the models list as it may change frequently for different organizations
export async function GET(req: NextRequest, res: NextResponse) {
const token = await getToken({ req });
if (token) {
let credential = await prisma.credentials.findFirst({
let account = await prisma.account.findFirst({
where: {
owner: token.sub,
ownerType: 'personal',
},
});

if (credential) {
if (account) {
const openai = new OpenAI({
apiKey: credential.openAIApiKey,
apiKey: account.openAIApiKey,
});
const models = await openai.models.list();
return Response.json(models);
Expand Down
Loading

0 comments on commit a9c2806

Please sign in to comment.