diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx index 2f1eeb3..ba8adb2 100644 --- a/app/(auth)/login/page.tsx +++ b/app/(auth)/login/page.tsx @@ -41,12 +41,21 @@ export default function LoginPage() {

+ By clicking continue, you agree to our{" "} - Don't have an account? Sign Up + Terms of Service + {" "} + and{" "} + + Privacy Policy + .

diff --git a/app/(protected)/dashboard/record-list.tsx b/app/(protected)/dashboard/record-list.tsx index 97d9bbd..914ca72 100644 --- a/app/(protected)/dashboard/record-list.tsx +++ b/app/(protected)/dashboard/record-list.tsx @@ -4,8 +4,8 @@ import { useState } from "react"; import Link from "next/link"; import { UserRecordFormData } from "@/actions/cloudflare-dns-record"; import { User } from "@prisma/client"; -import { ArrowUpRight } from "lucide-react"; -import useSWR from "swr"; +import { ArrowUpRight, DotSquareIcon, RefreshCwIcon } from "lucide-react"; +import useSWR, { useSWRConfig } from "swr"; import { TTL_ENUMS } from "@/lib/cloudflare"; import { fetcher } from "@/lib/utils"; @@ -66,6 +66,7 @@ export default function UserRecordsList({ user }: RecordListProps) { const [currentEditRecord, setCurrentEditRecord] = useState(null); + const { mutate } = useSWRConfig(); const { data, error, isLoading } = useSWR( "/api/record", fetcher, @@ -74,6 +75,10 @@ export default function UserRecordsList({ user }: RecordListProps) { }, ); + const handleRefresh = () => { + mutate("/api/record", undefined); + }; + return ( <> @@ -84,18 +89,31 @@ export default function UserRecordsList({ user }: RecordListProps) { All Dns Records - +
+ + +
{isShowForm && ( @@ -105,6 +123,7 @@ export default function UserRecordsList({ user }: RecordListProps) { setShowForm={setShowForm} type={formType} initData={currentEditRecord} + onRefresh={handleRefresh} /> )} @@ -179,7 +198,18 @@ export default function UserRecordsList({ user }: RecordListProps) { You don't have any record yet. Start creating record. - + )} diff --git a/app/api/record/add/route.ts b/app/api/record/add/route.ts index 90dbdae..c903d85 100644 --- a/app/api/record/add/route.ts +++ b/app/api/record/add/route.ts @@ -7,11 +7,14 @@ import { import { env } from "@/env.mjs"; import { createDNSRecord } from "@/lib/cloudflare"; import { getCurrentUser } from "@/lib/session"; +import { checkUserStatus } from "@/lib/user"; import { generateSecret } from "@/lib/utils"; export async function POST(req: Request) { try { - const user = await getCurrentUser(); + const user = checkUserStatus(await getCurrentUser()); + if (user instanceof Response) return user; + const { records } = await req.json(); const { CLOUDFLARE_ZONE_ID, @@ -20,13 +23,6 @@ export async function POST(req: Request) { NEXT_PUBLIC_FREE_RECORD_QUOTA, } = env; - if (!user?.id) { - return Response.json("Unauthorized", { - status: 401, - statusText: "Unauthorized", - }); - } - if (!CLOUDFLARE_ZONE_ID || !CLOUDFLARE_API_KEY || !CLOUDFLARE_EMAIL) { return Response.json("API key态zone iD and email are required", { status: 400, @@ -106,9 +102,9 @@ export async function POST(req: Request) { } } catch (error) { console.error(error); - return Response.json(error, { - status: 500, - statusText: "Server error", + return Response.json(error?.statusText || error, { + status: error?.status || 500, + statusText: error?.statusText || "Server error", }); } } diff --git a/app/api/record/delete/route.ts b/app/api/record/delete/route.ts index 65e700a..439600e 100644 --- a/app/api/record/delete/route.ts +++ b/app/api/record/delete/route.ts @@ -1,28 +1,38 @@ import { deleteUserRecord } from "@/actions/cloudflare-dns-record"; import { env } from "@/env.mjs"; +import { deleteDNSRecord } from "@/lib/cloudflare"; import { getCurrentUser } from "@/lib/session"; +import { checkUserStatus } from "@/lib/user"; export async function POST(req: Request) { try { - const user = await getCurrentUser(); - if (!user?.id) { - return Response.json("Unauthorized", { - status: 401, - statusText: "Unauthorized", - }); - } + const user = checkUserStatus(await getCurrentUser()); + if (user instanceof Response) return user; const { record_id, zone_id, active } = await req.json(); const { CLOUDFLARE_ZONE_ID, CLOUDFLARE_API_KEY, CLOUDFLARE_EMAIL } = env; - await deleteUserRecord(user.id, record_id, zone_id, active); - // await + // Delete cf dns record first. + const res = await deleteDNSRecord( + CLOUDFLARE_ZONE_ID, + CLOUDFLARE_API_KEY, + CLOUDFLARE_EMAIL, + record_id, + ); + if (res && res.result?.id) { + // Then delete user record. + await deleteUserRecord(user.id, record_id, zone_id, active); + return Response.json({ + status: 200, + statusText: "success", + }); + } } catch (error) { console.error(error); - return Response.json(error, { - status: 500, - statusText: "Server error", + return Response.json(error?.statusText || error, { + status: error.status || 500, + statusText: error.statusText || "Server error", }); } } diff --git a/app/api/record/route.ts b/app/api/record/route.ts index 7f94fc0..a074261 100644 --- a/app/api/record/route.ts +++ b/app/api/record/route.ts @@ -2,26 +2,21 @@ import { getUserRecords } from "@/actions/cloudflare-dns-record"; import { env } from "@/env.mjs"; import { getCurrentUser } from "@/lib/session"; +import { checkUserStatus } from "@/lib/user"; export async function GET(req: Request) { try { - const user = await getCurrentUser(); - if (!user?.id) { - return Response.json("Unauthorized", { - status: 401, - statusText: "Unauthorized", - }); - } - + const user = checkUserStatus(await getCurrentUser()); + if (user instanceof Response) return user; // const { CLOUDFLARE_ZONE_ID, CLOUDFLARE_API_KEY, CLOUDFLARE_EMAIL } = env; const user_records = await getUserRecords(user.id, 1); return Response.json(user_records); } catch (error) { - return Response.json(error, { - status: 500, - statusText: "Server error", + return Response.json(error?.statusText || error, { + status: error.status || 500, + statusText: error.statusText || "Server error", }); } } diff --git a/app/api/record/update/route.ts b/app/api/record/update/route.ts index fb573e3..d4957bc 100644 --- a/app/api/record/update/route.ts +++ b/app/api/record/update/route.ts @@ -1,8 +1,10 @@ import { env } from "@/env.mjs"; import { getCurrentUser } from "@/lib/session"; +import { checkUserStatus } from "@/lib/user"; export async function POST(req: Request) { try { + const user = checkUserStatus(await getCurrentUser()); } catch (error) { console.error(error); return Response.json(error, { diff --git a/components/forms/record-form.tsx b/components/forms/record-form.tsx index ab3710d..94770c3 100644 --- a/components/forms/record-form.tsx +++ b/components/forms/record-form.tsx @@ -38,6 +38,7 @@ export interface RecordFormProps { setShowForm: Dispatch>; type: FormType; initData?: UserRecordFormData | null; + onRefresh: () => void; } export function RecordForm({ @@ -46,8 +47,10 @@ export function RecordForm({ setShowForm, type, initData, + onRefresh, }: RecordFormProps) { const [isPending, startTransition] = useTransition(); + const [isDeleting, startDeleteTransition] = useTransition(); const { handleSubmit, @@ -66,68 +69,79 @@ export function RecordForm({ }); const onSubmit = handleSubmit((data) => { - startTransition(async () => { - if (type === "add") { - handleCreateRecord(data); - } else if (type === "edit") { - handleUpdateRecord(data); - } - }); + if (type === "add") { + handleCreateRecord(data); + } else if (type === "edit") { + handleUpdateRecord(data); + } }); const handleCreateRecord = async (data: CreateDNSRecord) => { - const response = await fetch("/api/record/add", { - method: "POST", - body: JSON.stringify({ - records: [data], - }), - }); - if (!response.ok || response.status !== 200) { - toast.error("Created Failed!", { - description: response.statusText, + startTransition(async () => { + const response = await fetch("/api/record/add", { + method: "POST", + body: JSON.stringify({ + records: [data], + }), }); - } else { - const res = await response.json(); - toast.success(`Created successfully!`); - setShowForm(false); - } + if (!response.ok || response.status !== 200) { + toast.error("Created Failed!", { + description: response.statusText, + }); + } else { + const res = await response.json(); + toast.success(`Created successfully!`); + setShowForm(false); + onRefresh(); + } + }); }; const handleUpdateRecord = async (data: CreateDNSRecord) => { - const response = await fetch("/api/record/update", { - method: "POST", - body: JSON.stringify({ - records: [data], - }), + startTransition(async () => { + if (type === "edit") { + const response = await fetch("/api/record/update", { + method: "POST", + body: JSON.stringify({ + records: [data], + }), + }); + if (!response.ok || response.status !== 200) { + toast.error("Update Failed", { + description: response.statusText, + }); + } else { + const res = await response.json(); + toast.success(`Update successfully!`); + setShowForm(false); + onRefresh(); + } + } }); - if (!response.ok || response.status !== 200) { - toast.error("Update Failed", { - description: response.statusText, - }); - } else { - const res = await response.json(); - toast.success(`Update successfully!`); - setShowForm(false); - } }; const handleDeleteRecord = async () => { - const response = await fetch("/api/record/delete", { - method: "POST", - body: JSON.stringify({ - record_id: initData?.record_id, - zone_id: initData?.zone_id, - active: initData?.active, - }), - }); - if (!response.ok || response.status !== 200) { - toast.error("Delete Failed", { - description: response.statusText, + if (type === "edit") { + startTransition(async () => { + const response = await fetch("/api/record/delete", { + method: "POST", + body: JSON.stringify({ + record_id: initData?.record_id, + zone_id: initData?.zone_id, + active: initData?.active, + }), + }); + if (!response.ok || response.status !== 200) { + toast.error("Delete Failed", { + description: response.statusText, + }); + } else { + await response.json(); + toast.success(`Success`); + setShowForm(false); + onRefresh(); + } }); - } else { - await response.json(); - toast.success(`Delete successfully!`); - setShowForm(false); } }; @@ -261,16 +275,22 @@ export function RecordForm({
{type === "edit" && ( )}