fix: allow owner role to access admin pages

This commit is contained in:
dyzulk
2025-12-30 20:14:39 +07:00
parent e64df76835
commit e7c02d5fa1
8 changed files with 63 additions and 14 deletions

View File

@@ -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);

View File

@@ -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<any[]>([]);

View File

@@ -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);

View File

@@ -24,12 +24,13 @@ export default function RootCaManagementClient() {
const [isRenewing, setIsRenewing] = useState(false);
const [confirmRenewUuid, setConfirmRenewUuid] = useState<string | null>(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);

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);