fix: merge comparisons [id] and [slug] routes to resolve ambiguous route error
This commit is contained in:
@@ -99,7 +99,7 @@ export default function ProfilePage() {
|
|||||||
|
|
||||||
const handleToggleVisibility = async (comparison: Comparison) => {
|
const handleToggleVisibility = async (comparison: Comparison) => {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`/api/comparisons/${comparison.id}`, {
|
const res = await fetch(`/api/comparisons/${comparison.slug}`, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ isPublic: !comparison.isPublic }),
|
body: JSON.stringify({ isPublic: !comparison.isPublic }),
|
||||||
@@ -116,7 +116,7 @@ export default function ProfilePage() {
|
|||||||
const handleDelete = async (comparison: Comparison) => {
|
const handleDelete = async (comparison: Comparison) => {
|
||||||
if (!window.confirm(`Delete "${comparison.title}"? This cannot be undone.`)) return
|
if (!window.confirm(`Delete "${comparison.title}"? This cannot be undone.`)) return
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`/api/comparisons/${comparison.id}`, {
|
const res = await fetch(`/api/comparisons/${comparison.slug}`, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
})
|
})
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
|
|||||||
@@ -1,111 +0,0 @@
|
|||||||
import { db } from "@/lib/db";
|
|
||||||
import { comparisons, sessions, users } from "@/lib/db/schema";
|
|
||||||
import { eq, and, gt } from "drizzle-orm";
|
|
||||||
import { headers } from "next/headers";
|
|
||||||
|
|
||||||
async function getAuthedUserId(): Promise<string | null> {
|
|
||||||
const hdrs = await headers();
|
|
||||||
const cookieHeader = hdrs.get("cookie") ?? "";
|
|
||||||
const cookieMatch = cookieHeader
|
|
||||||
.split(";")
|
|
||||||
.map((c) => c.trim())
|
|
||||||
.find(
|
|
||||||
(c) =>
|
|
||||||
c.startsWith("__Secure-better-auth.session_token=") ||
|
|
||||||
c.startsWith("better-auth.session_token=")
|
|
||||||
);
|
|
||||||
const token = cookieMatch
|
|
||||||
?.split("=")
|
|
||||||
?.slice(1)
|
|
||||||
?.join("=")
|
|
||||||
?.trim()
|
|
||||||
.split(".")[0];
|
|
||||||
if (!token) return null;
|
|
||||||
|
|
||||||
const sessionRows = await db
|
|
||||||
.select()
|
|
||||||
.from(sessions)
|
|
||||||
.where(and(eq(sessions.token, token), gt(sessions.expiresAt, new Date())))
|
|
||||||
.limit(1);
|
|
||||||
if (!sessionRows.length) return null;
|
|
||||||
|
|
||||||
const userRows = await db
|
|
||||||
.select()
|
|
||||||
.from(users)
|
|
||||||
.where(eq(users.id, sessionRows[0].userId))
|
|
||||||
.limit(1);
|
|
||||||
if (!userRows.length) return null;
|
|
||||||
|
|
||||||
return userRows[0].id;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function DELETE(
|
|
||||||
_request: Request,
|
|
||||||
{ params }: { params: Promise<{ id: string }> }
|
|
||||||
) {
|
|
||||||
const userId = await getAuthedUserId();
|
|
||||||
if (!userId) {
|
|
||||||
return Response.json({ error: "Unauthorized" }, { status: 401 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const { id } = await params;
|
|
||||||
|
|
||||||
const existing = await db
|
|
||||||
.select({ userId: comparisons.userId })
|
|
||||||
.from(comparisons)
|
|
||||||
.where(eq(comparisons.id, id))
|
|
||||||
.limit(1);
|
|
||||||
|
|
||||||
if (!existing.length) {
|
|
||||||
return Response.json({ error: "Not found" }, { status: 404 });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (existing[0].userId !== userId) {
|
|
||||||
return Response.json({ error: "Forbidden" }, { status: 403 });
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.delete(comparisons).where(eq(comparisons.id, id));
|
|
||||||
|
|
||||||
return Response.json({ success: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function PATCH(
|
|
||||||
request: Request,
|
|
||||||
{ params }: { params: Promise<{ id: string }> }
|
|
||||||
) {
|
|
||||||
const userId = await getAuthedUserId();
|
|
||||||
if (!userId) {
|
|
||||||
return Response.json({ error: "Unauthorized" }, { status: 401 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const { id } = await params;
|
|
||||||
|
|
||||||
const existing = await db
|
|
||||||
.select({ userId: comparisons.userId, isPublic: comparisons.isPublic })
|
|
||||||
.from(comparisons)
|
|
||||||
.where(eq(comparisons.id, id))
|
|
||||||
.limit(1);
|
|
||||||
|
|
||||||
if (!existing.length) {
|
|
||||||
return Response.json({ error: "Not found" }, { status: 404 });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (existing[0].userId !== userId) {
|
|
||||||
return Response.json({ error: "Forbidden" }, { status: 403 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = await request.json();
|
|
||||||
const newIsPublic =
|
|
||||||
typeof body.isPublic === "boolean" ? body.isPublic : !existing[0].isPublic;
|
|
||||||
|
|
||||||
const [updated] = await db
|
|
||||||
.update(comparisons)
|
|
||||||
.set({ isPublic: newIsPublic, updatedAt: new Date() })
|
|
||||||
.where(eq(comparisons.id, id))
|
|
||||||
.returning();
|
|
||||||
|
|
||||||
return Response.json({
|
|
||||||
id: updated.id,
|
|
||||||
isPublic: updated.isPublic,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,45 @@
|
|||||||
import { db } from "@/lib/db";
|
import { db } from "@/lib/db";
|
||||||
import { comparisons } from "@/lib/db/schema";
|
import { comparisons, sessions, users } from "@/lib/db/schema";
|
||||||
import { eq, sql } from "drizzle-orm";
|
import { eq, sql, and, gt } from "drizzle-orm";
|
||||||
|
import { headers } from "next/headers";
|
||||||
import { getComparison } from "@/app/actions/comparison";
|
import { getComparison } from "@/app/actions/comparison";
|
||||||
|
|
||||||
|
async function getAuthedUserId(): Promise<string | null> {
|
||||||
|
const hdrs = await headers();
|
||||||
|
const cookieHeader = hdrs.get("cookie") ?? "";
|
||||||
|
const cookieMatch = cookieHeader
|
||||||
|
.split(";")
|
||||||
|
.map((c) => c.trim())
|
||||||
|
.find(
|
||||||
|
(c) =>
|
||||||
|
c.startsWith("__Secure-better-auth.session_token=") ||
|
||||||
|
c.startsWith("better-auth.session_token=")
|
||||||
|
);
|
||||||
|
const token = cookieMatch
|
||||||
|
?.split("=")
|
||||||
|
?.slice(1)
|
||||||
|
?.join("=")
|
||||||
|
?.trim()
|
||||||
|
.split(".")[0];
|
||||||
|
if (!token) return null;
|
||||||
|
|
||||||
|
const sessionRows = await db
|
||||||
|
.select()
|
||||||
|
.from(sessions)
|
||||||
|
.where(and(eq(sessions.token, token), gt(sessions.expiresAt, new Date())))
|
||||||
|
.limit(1);
|
||||||
|
if (!sessionRows.length) return null;
|
||||||
|
|
||||||
|
const userRows = await db
|
||||||
|
.select()
|
||||||
|
.from(users)
|
||||||
|
.where(eq(users.id, sessionRows[0].userId))
|
||||||
|
.limit(1);
|
||||||
|
if (!userRows.length) return null;
|
||||||
|
|
||||||
|
return userRows[0].id;
|
||||||
|
}
|
||||||
|
|
||||||
export async function GET(
|
export async function GET(
|
||||||
_request: Request,
|
_request: Request,
|
||||||
{ params }: { params: Promise<{ slug: string }> }
|
{ params }: { params: Promise<{ slug: string }> }
|
||||||
@@ -22,3 +59,78 @@ export async function GET(
|
|||||||
|
|
||||||
return Response.json(comparison);
|
return Response.json(comparison);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function DELETE(
|
||||||
|
_request: Request,
|
||||||
|
{ params }: { params: Promise<{ slug: string }> }
|
||||||
|
) {
|
||||||
|
const userId = await getAuthedUserId();
|
||||||
|
if (!userId) {
|
||||||
|
return Response.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { slug } = await params;
|
||||||
|
|
||||||
|
const existing = await db
|
||||||
|
.select({ id: comparisons.id, userId: comparisons.userId })
|
||||||
|
.from(comparisons)
|
||||||
|
.where(eq(comparisons.slug, slug))
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (!existing.length) {
|
||||||
|
return Response.json({ error: "Not found" }, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existing[0].userId !== userId) {
|
||||||
|
return Response.json({ error: "Forbidden" }, { status: 403 });
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.delete(comparisons).where(eq(comparisons.id, existing[0].id));
|
||||||
|
|
||||||
|
return Response.json({ success: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function PATCH(
|
||||||
|
request: Request,
|
||||||
|
{ params }: { params: Promise<{ slug: string }> }
|
||||||
|
) {
|
||||||
|
const userId = await getAuthedUserId();
|
||||||
|
if (!userId) {
|
||||||
|
return Response.json({ error: "Unauthorized" }, { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { slug } = await params;
|
||||||
|
|
||||||
|
const existing = await db
|
||||||
|
.select({
|
||||||
|
id: comparisons.id,
|
||||||
|
userId: comparisons.userId,
|
||||||
|
isPublic: comparisons.isPublic,
|
||||||
|
})
|
||||||
|
.from(comparisons)
|
||||||
|
.where(eq(comparisons.slug, slug))
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (!existing.length) {
|
||||||
|
return Response.json({ error: "Not found" }, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existing[0].userId !== userId) {
|
||||||
|
return Response.json({ error: "Forbidden" }, { status: 403 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = await request.json();
|
||||||
|
const newIsPublic =
|
||||||
|
typeof body.isPublic === "boolean" ? body.isPublic : !existing[0].isPublic;
|
||||||
|
|
||||||
|
const [updated] = await db
|
||||||
|
.update(comparisons)
|
||||||
|
.set({ isPublic: newIsPublic, updatedAt: new Date() })
|
||||||
|
.where(eq(comparisons.id, existing[0].id))
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
return Response.json({
|
||||||
|
id: updated.id,
|
||||||
|
isPublic: updated.isPublic,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user