-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add api management routes and screen
- Loading branch information
1 parent
c477066
commit e43fcf3
Showing
17 changed files
with
382 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import Empty from "@/components/empty"; | ||
|
||
export default async function ApiManagementPage() { | ||
const integrations = []; | ||
|
||
if (!integrations || integrations.length === 0) { | ||
return ( | ||
<Empty | ||
empty={{ description: "No integrations available to manage yet" }} | ||
/> | ||
); | ||
} | ||
|
||
return integrations.map((integration) => integration._id); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { getServerSession } from "next-auth"; | ||
import { NextResponse } from "next/server"; | ||
import { authOptions } from "../auth/[...nextauth]/route"; | ||
import { saveApiKeys } from "@/lib/db/writes"; | ||
import { encrypt } from "@/lib/encryption"; | ||
|
||
export async function POST(req, res) { | ||
const session = await getServerSession(req, res, authOptions); | ||
|
||
if (!session) { | ||
return new NextResponse("Unauthorized", { status: 401 }); | ||
} | ||
|
||
try { | ||
const { vendorName, vendorUrl } = await req.body; | ||
|
||
if (!vendorUrl) { | ||
throw new Error("You must enter a vendor URL."); | ||
} | ||
|
||
if (!vendorName) { | ||
throw new Error("You must enter a vendor name."); | ||
} | ||
|
||
// Validate URL | ||
new URL(vendorUrl); | ||
|
||
const vendorId = crypto.randomBytes(8).toString("hex").toUpperCase(); | ||
|
||
// Generate the API key by hashing the vendor name and URL together | ||
const apiKey = crypto | ||
.createHash("sha512") | ||
.update(vendorName + "-" + vendorUrl) | ||
.digest() | ||
.subarray(0, 64) | ||
.toString("base64"); | ||
|
||
const data = { | ||
vendorId, | ||
apiKey: encrypt(apiKey), | ||
vendorName, | ||
vendorUrl, | ||
createdBy: session.user.email, | ||
}; | ||
|
||
await saveApiKeys(data); | ||
|
||
return new NextResponse("Created", { | ||
status: 201, | ||
}); | ||
} catch (error) { | ||
console.error(error); | ||
|
||
return new NextResponse("Error", { | ||
status: 500, | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,18 @@ | ||
import { authOptions } from "@/app/api/auth/[...nextauth]/route"; | ||
import { getCompletionsPendingReview } from "@/lib/db/reads"; | ||
import { getServerSession } from "next-auth/next"; | ||
import { NextResponse } from "next/server"; | ||
|
||
export async function GET(request, _) { | ||
const completionsPendingReview = await getCompletionsPendingReview(); | ||
export async function GET() { | ||
const session = await getServerSession(authOptions); | ||
|
||
return new NextResponse(JSON.stringify(completionsPendingReview), { | ||
status: 200, | ||
}); | ||
} | ||
if (!session) { | ||
return new NextResponse(JSON.stringify([]), { status: 401 }); | ||
} | ||
|
||
export async function PATCH(request) { | ||
// TODO: Approved/reject review | ||
const completionsPendingReview = await getCompletionsPendingReview(); | ||
|
||
return new NextResponse(JSON.stringify({ answer: "John Doe" }), { | ||
return new NextResponse(JSON.stringify(completionsPendingReview), { | ||
status: 200, | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { authOptions } from "@/app/api/auth/[...nextauth]/route"; | ||
import { reviewCompletion } from "@/lib/db/writes"; | ||
import { getServerSession } from "next-auth"; | ||
import { NextResponse } from "next/server"; | ||
|
||
function validateDirection(direction) { | ||
const validDirections = [ | ||
"pending2approve", | ||
"pending2reject", | ||
"approve2reject", | ||
"reject2approve", | ||
]; | ||
|
||
if (!validDirections.includes(direction)) { | ||
throw new Error(`Invalid direction: ${direction}`); | ||
} | ||
} | ||
|
||
export async function POST(req) { | ||
const session = await getServerSession(authOptions); | ||
|
||
if (!session) { | ||
return new NextResponse(JSON.stringify("Unauthorized"), { status: 401 }); | ||
} | ||
|
||
if (!req.body._id && !req.body.direction) { | ||
return new NextResponse(JSON.stringify("Bad Request"), { status: 400 }); | ||
} | ||
|
||
try { | ||
const { _id, direction } = req.body; | ||
validateDirection(direction); | ||
|
||
const result = await reviewCompletion(_id, direction); | ||
|
||
return new NextResponse(JSON.stringify(result), { | ||
status: 200, | ||
}); | ||
} catch (error) { | ||
console.error(error); | ||
return new NextResponse(JSON.stringify("Internal Server Error"), { | ||
status: 500, | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { getApiKey } from "@/lib/db/reads"; | ||
import { saveCompletion } from "@/lib/db/writes"; | ||
import { decrypt } from "@/lib/encryption"; | ||
import { NextResponse } from "next/server"; | ||
|
||
export async function POST(req) { | ||
const { vendorId, apiKey } = req.headers; | ||
|
||
if (!vendorId) { | ||
return new NextResponse("Bad Request", { | ||
status: 400, | ||
}); | ||
} | ||
|
||
if (!apiKey) { | ||
return new NextResponse("Bad Request", { | ||
status: 400, | ||
}); | ||
} | ||
|
||
const result = await getApiKey(vendorId); | ||
|
||
const decryptedApiKey = decrypt(result.apiKey); | ||
|
||
if (decryptedApiKey !== apiKey) { | ||
return new NextResponse("Unauthorized", { | ||
status: 401, | ||
}); | ||
} | ||
|
||
const { origin } = new URL(result.vendorUrl); | ||
const { origin: requestOrigin } = new URL(req.headers.referer); | ||
|
||
if (origin !== requestOrigin) { | ||
return new NextResponse("Forbidden", { | ||
status: 403, | ||
}); | ||
} | ||
|
||
if (!req.body) { | ||
return new NextResponse("Bad Request", { | ||
status: 400, | ||
}); | ||
} | ||
|
||
try { | ||
await saveCompletion(req.body); | ||
|
||
return new NextResponse("Created", { | ||
status: 201, | ||
}); | ||
} catch (error) { | ||
console.error(error); | ||
|
||
return new NextResponse("Error", { | ||
status: 500, | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export { default } from "next-auth/middleware"; | ||
|
||
export const config = { | ||
matcher: [ | ||
"/api-management", | ||
"completions", | ||
"/api/api-keys", | ||
"/api/data/completions/approved", | ||
"/api/data/completions/pending", | ||
"/api/data/completions/rejected", | ||
"/api/data/completions/review", | ||
], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.