mirror of
https://github.com/dyzulk/trustlab.git
synced 2026-01-26 05:25:36 +07:00
feat: add Purge CDN button and confirmation UI to CA management
This commit is contained in:
@@ -31,6 +31,8 @@ export default function RootCaManagementClient() {
|
||||
const [isPromoting, setIsPromoting] = useState(false);
|
||||
const [confirmRenewUuid, setConfirmRenewUuid] = useState<string | null>(null);
|
||||
const [showBulkRenewConfirm, setShowBulkRenewConfirm] = useState(false);
|
||||
const [showPurgeConfirm, setShowPurgeConfirm] = useState(false);
|
||||
const [isPurging, setIsPurging] = useState(false);
|
||||
|
||||
// Redirect if not admin or owner (double security, backend also checks)
|
||||
const { isAdminOrOwner } = useAuth();
|
||||
@@ -82,6 +84,21 @@ export default function RootCaManagementClient() {
|
||||
}
|
||||
};
|
||||
|
||||
const handlePurgeCdn = async () => {
|
||||
setIsPurging(true);
|
||||
try {
|
||||
const response = await axios.post("/api/admin/ca-certificates/purge-cdn");
|
||||
addToast(response.data.message || t("toast_purge_success"), "success");
|
||||
setShowPurgeConfirm(false);
|
||||
mutate(); // Refresh local list to see 'Local Only' status
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
addToast(err.response?.data?.message || t("toast_purge_failed"), "error");
|
||||
} finally {
|
||||
setIsPurging(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePromote = async (uuid: string) => {
|
||||
setIsPromoting(true);
|
||||
try {
|
||||
@@ -182,8 +199,9 @@ export default function RootCaManagementClient() {
|
||||
{/* CDN Synchronization Controls */}
|
||||
<CdnManagementCard
|
||||
onSync={handleSyncCdn}
|
||||
onPurge={() => setShowPurgeConfirm(true)}
|
||||
activeSync={activeSync}
|
||||
disabled={isLoading || isPromoting}
|
||||
disabled={isLoading || isPromoting || isPurging}
|
||||
/>
|
||||
|
||||
{/* Full-width Archive History */}
|
||||
@@ -232,6 +250,18 @@ export default function RootCaManagementClient() {
|
||||
variant="warning"
|
||||
requiredInput="RENEW-ALL"
|
||||
/>
|
||||
|
||||
<ConfirmationModal
|
||||
isOpen={showPurgeConfirm}
|
||||
onClose={() => setShowPurgeConfirm(false)}
|
||||
onConfirm={handlePurgeCdn}
|
||||
title={t("purge_modal_title")}
|
||||
message={t("purge_modal_msg")}
|
||||
isLoading={isPurging}
|
||||
confirmLabel={t("purge_confirm_label")}
|
||||
variant="error"
|
||||
requiredInput="PURGE"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,11 +6,12 @@ import { useTranslations } from "next-intl";
|
||||
|
||||
interface CdnManagementCardProps {
|
||||
onSync: (type: "all" | "crt" | "installers" | "bundles", mode: "latest" | "archive" | "both") => void;
|
||||
onPurge: () => void;
|
||||
activeSync: string | null;
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
export default function CdnManagementCard({ onSync, activeSync, disabled }: CdnManagementCardProps) {
|
||||
export default function CdnManagementCard({ onSync, onPurge, activeSync, disabled }: CdnManagementCardProps) {
|
||||
const t = useTranslations("RootCA");
|
||||
|
||||
const SyncButton = ({
|
||||
@@ -130,6 +131,26 @@ export default function CdnManagementCard({ onSync, activeSync, disabled }: CdnM
|
||||
</div>
|
||||
</ComponentCard>
|
||||
</div>
|
||||
|
||||
{/* Danger Zone: Purge Control */}
|
||||
<div className="mt-8 p-4 border border-error-100 dark:border-error-900/30 bg-error-50/30 dark:bg-error-900/10 rounded-xl">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
|
||||
<div className="flex flex-col">
|
||||
<span className="text-sm font-bold text-error-700 dark:text-error-400">{t("btn_purge_cdn")}</span>
|
||||
<p className="text-xs text-error-600 dark:text-error-500/80 mt-1">{t("desc_purge_cdn")}</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={onPurge}
|
||||
disabled={disabled || activeSync !== null}
|
||||
className="flex items-center justify-center gap-2 px-6 py-2.5 bg-error-600 hover:bg-error-700 disabled:bg-error-400 text-white text-xs font-bold rounded-lg transition-all shadow-sm active:scale-95 whitespace-nowrap"
|
||||
>
|
||||
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
||||
</svg>
|
||||
{t("btn_purge_cdn")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -706,7 +706,14 @@
|
||||
"label_latest_sync": "Latest Sync (Clean URLs)",
|
||||
"desc_latest_sync": "Only update the primary public links for installers.",
|
||||
"label_archive_sync": "Archive Sync (Versioned)",
|
||||
"desc_archive_sync": "Only save permanent archives without changing public links."
|
||||
"desc_archive_sync": "Only save permanent archives without changing public links.",
|
||||
"btn_purge_cdn": "Purge CDN Assets",
|
||||
"desc_purge_cdn": "PERMANENTLY delete all CA files from Cloudflare R2 and reset local sync status. Highly destructive.",
|
||||
"purge_modal_title": "Purge All CDN Assets?",
|
||||
"purge_modal_msg": "This action cannot be undone. All public certificates, installers, and bundles will be deleted from the CDN. Clients will not be able to download CA files until you re-sync.",
|
||||
"purge_confirm_label": "Purge Everything",
|
||||
"toast_purge_success": "CDN assets purged and local status reset successfully",
|
||||
"toast_purge_failed": "Failed to purge CDN assets"
|
||||
},
|
||||
"SmtpTester": {
|
||||
"page_title": "SMTP Tester",
|
||||
|
||||
@@ -706,7 +706,14 @@
|
||||
"label_latest_sync": "Sinkronisasi Terbaru (URL Bersih)",
|
||||
"desc_latest_sync": "Hanya perbarui link publik utama pendukung installer.",
|
||||
"label_archive_sync": "Sinkronisasi Arsip (Versi)",
|
||||
"desc_archive_sync": "Hanya simpan arsip permanen tanpa mengubah link publik."
|
||||
"desc_archive_sync": "Hanya simpan arsip permanen tanpa mengubah link publik.",
|
||||
"btn_purge_cdn": "Kosongkan Aset CDN",
|
||||
"desc_purge_cdn": "Hapus secara PERMANEN semua file CA dari Cloudflare R2 dan reset status sinkronisasi lokal. Sangat destruktif.",
|
||||
"purge_modal_title": "Kosongkan Semua Aset CDN?",
|
||||
"purge_modal_msg": "Tindakan ini tidak dapat dibatalkan. Semua sertifikat publik, installer, dan bundle akan dihapus dari CDN. Client tidak akan bisa mengunduh file CA sampai Anda melakukan sinkronisasi ulang.",
|
||||
"purge_confirm_label": "Hapus Semuanya",
|
||||
"toast_purge_success": "Aset CDN dikosongkan dan status lokal berhasil direset",
|
||||
"toast_purge_failed": "Gagal mengosongkan aset CDN"
|
||||
},
|
||||
"SmtpTester": {
|
||||
"page_title": "Pengetes SMTP",
|
||||
|
||||
Reference in New Issue
Block a user