mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-04-27 09:26:23 +02:00
use api key instead of project secret
This commit is contained in:
parent
83591a690d
commit
e3576489e3
5 changed files with 29 additions and 24 deletions
|
|
@ -1,22 +1,26 @@
|
|||
import { NextRequest } from "next/server";
|
||||
import { projectsCollection } from "@/app/lib/mongodb";
|
||||
import { apiKeysCollection, projectsCollection } from "@/app/lib/mongodb";
|
||||
|
||||
export async function authCheck(projectId: string, req: NextRequest, handler: () => Promise<Response>): Promise<Response> {
|
||||
const authHeader = req.headers.get('Authorization');
|
||||
if (!authHeader?.startsWith('Bearer ')) {
|
||||
return Response.json({ error: "Authorization header must be a Bearer token" }, { status: 400 });
|
||||
}
|
||||
const token = authHeader.split(' ')[1];
|
||||
if (!token) {
|
||||
const key = authHeader.split(' ')[1];
|
||||
if (!key) {
|
||||
return Response.json({ error: "Missing API key in request" }, { status: 400 });
|
||||
}
|
||||
|
||||
// check the key in project settings
|
||||
const project = await projectsCollection.findOne({
|
||||
_id: projectId,
|
||||
secret: token,
|
||||
});
|
||||
if (!project) {
|
||||
// check if api key is valid
|
||||
// while also updating last used timestamp
|
||||
const result = await apiKeysCollection.findOneAndUpdate(
|
||||
{
|
||||
projectId,
|
||||
key,
|
||||
},
|
||||
{ $set: { lastUsedAt: new Date().toISOString() } }
|
||||
);
|
||||
if (!result) {
|
||||
return Response.json({ error: "Invalid API key" }, { status: 403 });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ import { getProjectConfig, updateProjectName, updateWebhookUrl, createApiKey, de
|
|||
import { CopyButton } from "@/app/lib/components/copy-button";
|
||||
import { EditableField } from "@/app/lib/components/editable-field";
|
||||
import { EyeIcon, EyeOffIcon, CopyIcon, MoreVerticalIcon, PlusIcon, EllipsisVerticalIcon } from "lucide-react";
|
||||
import { WithStringId, ApiKey } from "@/app/lib/types";
|
||||
import { z } from "zod";
|
||||
import { RelativeTime } from "@primer/react";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Project config",
|
||||
|
|
@ -142,11 +145,7 @@ export function ApiKeysSection({
|
|||
}: {
|
||||
projectId: string;
|
||||
}) {
|
||||
const [keys, setKeys] = useState<Array<{
|
||||
_id: string;
|
||||
key: string;
|
||||
createdAt: string;
|
||||
}>>([]);
|
||||
const [keys, setKeys] = useState<WithStringId<z.infer<typeof ApiKey>>[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [message, setMessage] = useState<{
|
||||
type: 'success' | 'error' | 'info';
|
||||
|
|
@ -254,9 +253,11 @@ export function ApiKeysSection({
|
|||
<ApiKeyDisplay apiKey={key.key} />
|
||||
</div>
|
||||
<div className="flex-1 p-2">
|
||||
{new Date(key.createdAt).toLocaleDateString()}
|
||||
<RelativeTime date={new Date(key.createdAt)} />
|
||||
</div>
|
||||
<div className="flex-1 p-2">
|
||||
{key.lastUsedAt ? <RelativeTime date={new Date(key.lastUsedAt)} /> : 'Never'}
|
||||
</div>
|
||||
<div className="flex-1 p-2">Never</div>
|
||||
<div className="w-10 p-2">
|
||||
<Dropdown>
|
||||
<DropdownTrigger>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue