diff --git a/src/app/dashboard/admin/inquiries/InquiryClient.tsx b/src/app/dashboard/admin/inquiries/InquiryClient.tsx index c0e001c..d33dc18 100644 --- a/src/app/dashboard/admin/inquiries/InquiryClient.tsx +++ b/src/app/dashboard/admin/inquiries/InquiryClient.tsx @@ -1,6 +1,7 @@ "use client"; -import React, { useState, useMemo } from "react"; +import React, { useState, useMemo, useEffect } from "react"; +import { useRouter } from "next/navigation"; import useSWR from "swr"; import axios from "@/lib/axios"; import PageBreadcrumb from "@/components/common/PageBreadCrumb"; @@ -17,7 +18,15 @@ const fetcher = (url: string) => axios.get(url).then((res) => res.data); export default function InquiryClient() { const t = useTranslations("Inquiries"); + const router = useRouter(); + const { user, isAdminOrOwner } = useAuth(); const { addToast } = useToast(); + + useEffect(() => { + if (user && !isAdminOrOwner) { + router.push("/dashboard"); + } + }, [user, isAdminOrOwner, router]); const [searchTerm, setSearchTerm] = useState(""); const [statusFilter, setStatusFilter] = useState("all"); const [isDeleting, setIsDeleting] = useState(false); diff --git a/src/app/dashboard/admin/legal/AdminLegalEditorClient.tsx b/src/app/dashboard/admin/legal/AdminLegalEditorClient.tsx index a00d547..9115752 100644 --- a/src/app/dashboard/admin/legal/AdminLegalEditorClient.tsx +++ b/src/app/dashboard/admin/legal/AdminLegalEditorClient.tsx @@ -5,6 +5,8 @@ import axios from "@/lib/axios"; import { useRouter } from "next/navigation"; import { Save, ArrowLeft, Eye, Edit3 } from "lucide-react"; import { useToast } from "@/context/ToastContext"; +import { useAuth } from "@/hooks/useAuth"; +import PageLoader from "@/components/ui/PageLoader"; import PageBreadcrumb from "@/components/common/PageBreadCrumb"; import Link from "next/link"; import ComponentCard from "@/components/common/ComponentCard"; @@ -12,18 +14,25 @@ import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; import { useTranslations } from "next-intl"; -interface EditorProps { +interface AdminLegalEditorClientProps { mode: "create" | "edit"; initialData?: any; } -export default function AdminLegalEditorClient({ mode, initialData }: EditorProps) { +export default function AdminLegalEditorClient({ mode, initialData }: AdminLegalEditorClientProps) { const t = useTranslations("LegalAdmin"); const router = useRouter(); + const { user, isAdminOrOwner } = useAuth(); const { addToast } = useToast(); const [isSubmitting, setIsSubmitting] = useState(false); const [activeTab, setActiveTab] = useState<'write' | 'preview'>('write'); + useEffect(() => { + if (user && !isAdminOrOwner) { + router.push("/dashboard"); + } + }, [user, isAdminOrOwner, router]); + // Load history if edit mode const [versionHistory, setVersionHistory] = useState([]); diff --git a/src/app/dashboard/admin/legal/AdminLegalListClient.tsx b/src/app/dashboard/admin/legal/AdminLegalListClient.tsx index b05a26f..50ede17 100644 --- a/src/app/dashboard/admin/legal/AdminLegalListClient.tsx +++ b/src/app/dashboard/admin/legal/AdminLegalListClient.tsx @@ -1,6 +1,8 @@ "use client"; -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; +import { useRouter } from "next/navigation"; +import { useAuth } from "@/hooks/useAuth"; import useSWR from "swr"; import axios from "@/lib/axios"; import { Plus, Search, FileText, ChevronRight, Edit3, Trash2 } from "lucide-react"; @@ -15,7 +17,16 @@ const fetcher = (url: string) => axios.get(url).then((res) => res.data); export default function AdminLegalListClient() { const t = useTranslations("LegalAdmin"); + const router = useRouter(); + const { user, isAdminOrOwner } = useAuth(); const { addToast } = useToast(); + + useEffect(() => { + if (user && !isAdminOrOwner) { + router.push("/dashboard"); + } + }, [user, isAdminOrOwner, router]); + const [searchTerm, setSearchTerm] = useState(""); const { data, mutate, isLoading } = useSWR("/api/admin/legal-pages", fetcher); diff --git a/src/app/dashboard/admin/root-ca/RootCaManagementClient.tsx b/src/app/dashboard/admin/root-ca/RootCaManagementClient.tsx index e810815..02f781a 100644 --- a/src/app/dashboard/admin/root-ca/RootCaManagementClient.tsx +++ b/src/app/dashboard/admin/root-ca/RootCaManagementClient.tsx @@ -24,12 +24,13 @@ export default function RootCaManagementClient() { const [isRenewing, setIsRenewing] = useState(false); const [confirmRenewUuid, setConfirmRenewUuid] = useState(null); - // Redirect if not admin (double security, backend also checks) + // Redirect if not admin or owner (double security, backend also checks) + const { isAdminOrOwner } = useAuth(); React.useEffect(() => { - if (user && user.role !== "admin") { + if (user && !isAdminOrOwner) { router.push("/dashboard"); } - }, [user, router]); + }, [user, isAdminOrOwner, router]); const handleRenew = async (uuid: string) => { setIsRenewing(true); diff --git a/src/app/dashboard/admin/smtp-tester/page.tsx b/src/app/dashboard/admin/smtp-tester/page.tsx index 61b0d16..a2529e5 100644 --- a/src/app/dashboard/admin/smtp-tester/page.tsx +++ b/src/app/dashboard/admin/smtp-tester/page.tsx @@ -34,13 +34,14 @@ export default function SmtpTesterPage() { const [testEmail, setTestEmail] = useState(''); const [results, setResults] = useState<{ [key: string]: { success: boolean; message: string } }>({}); + const { isAdminOrOwner } = useAuth(); useEffect(() => { - if (user && user.role !== 'admin') { + if (user && !isAdminOrOwner) { router.push('/dashboard/settings'); return; } fetchConfigs(); - }, [user, router]); + }, [user, isAdminOrOwner, router]); const fetchConfigs = async () => { try { diff --git a/src/app/dashboard/admin/tickets/AdminTicketDetailsClient.tsx b/src/app/dashboard/admin/tickets/AdminTicketDetailsClient.tsx index 35563bd..58584f5 100644 --- a/src/app/dashboard/admin/tickets/AdminTicketDetailsClient.tsx +++ b/src/app/dashboard/admin/tickets/AdminTicketDetailsClient.tsx @@ -31,10 +31,17 @@ const priorityColors: any = { export default function AdminTicketDetailsClient() { const t = useTranslations("Tickets"); + const router = useRouter(); const searchParams = useSearchParams(); const ticketId = searchParams.get("id"); - const { user } = useAuth(); + const { user, isAdminOrOwner } = useAuth(); const { addToast } = useToast(); + + useEffect(() => { + if (user && !isAdminOrOwner) { + router.push("/dashboard"); + } + }, [user, isAdminOrOwner, router]); const [replyMessage, setReplyMessage] = useState(""); const [isSubmitting, setIsSubmitting] = useState(false); const [isCloseModalOpen, setIsCloseModalOpen] = useState(false); diff --git a/src/app/dashboard/admin/tickets/AdminTicketListClient.tsx b/src/app/dashboard/admin/tickets/AdminTicketListClient.tsx index 354d306..45cd447 100644 --- a/src/app/dashboard/admin/tickets/AdminTicketListClient.tsx +++ b/src/app/dashboard/admin/tickets/AdminTicketListClient.tsx @@ -1,6 +1,8 @@ "use client"; -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; +import { useRouter } from "next/navigation"; +import { useAuth } from "@/hooks/useAuth"; import useSWR from "swr"; import axios from "@/lib/axios"; import { Search, MessageSquare, Clock, Filter, ChevronRight, User as UserIcon } from "lucide-react"; @@ -29,7 +31,16 @@ const priorityColors: any = { export default function AdminTicketListClient() { const t = useTranslations("Tickets"); + const router = useRouter(); + const { user, isAdminOrOwner } = useAuth(); const { addToast } = useToast(); + + useEffect(() => { + if (user && !isAdminOrOwner) { + router.push("/dashboard"); + } + }, [user, isAdminOrOwner, router]); + const [searchTerm, setSearchTerm] = useState(""); const [statusFilter, setStatusFilter] = useState("all"); const { data, mutate, isLoading } = useSWR("/api/support/tickets?all=true", fetcher); diff --git a/src/app/dashboard/admin/users/UsersManagementClient.tsx b/src/app/dashboard/admin/users/UsersManagementClient.tsx index 13e2205..ad223be 100644 --- a/src/app/dashboard/admin/users/UsersManagementClient.tsx +++ b/src/app/dashboard/admin/users/UsersManagementClient.tsx @@ -33,9 +33,9 @@ export default function UsersManagementClient() { const { data, error, mutate, isLoading } = useSWR("/api/admin/users", fetcher); - const hasAdminAccess = ['admin', 'owner'].includes(currentUser?.role || ''); - const isOwner = currentUser?.role === "owner"; - const isAdmin = currentUser?.role === "admin"; + const { isAdmin, isOwner, isAdminOrOwner } = useAuth(); + const hasAdminAccess = isAdminOrOwner; + const handleDelete = async (id: string) => { setIsDeleting(true);