From 6ea645f3581c35db6925d91538c24e4a18acd7b5 Mon Sep 17 00:00:00 2001
From: Sean Hatfield <seanhatfield5@gmail.com>
Date: Wed, 30 Aug 2023 15:28:30 -0700
Subject: [PATCH] Hide delete workspace button on non-admin users if setting is
 disabled (#227)

* hide delete workspace button on non-admin users if setting is disabled

---------

Co-authored-by: Timothy Carambat <timothycarambat@Timothys-MacBook-Pro.local>
---
 .../Modals/MangeWorkspace/Documents/index.jsx | 18 ++++++------
 frontend/src/models/system.js                 | 16 +++++++++++
 server/endpoints/system.js                    | 28 +++++++++++++++++++
 server/models/systemSettings.js               |  6 ++++
 4 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/frontend/src/components/Modals/MangeWorkspace/Documents/index.jsx b/frontend/src/components/Modals/MangeWorkspace/Documents/index.jsx
index 167a8cbf8..3dcfd3374 100644
--- a/frontend/src/components/Modals/MangeWorkspace/Documents/index.jsx
+++ b/frontend/src/components/Modals/MangeWorkspace/Documents/index.jsx
@@ -16,6 +16,7 @@ export default function DocumentSettings({ workspace }) {
   const [originalDocuments, setOriginalDocuments] = useState([]);
   const [selectedFiles, setSelectFiles] = useState([]);
   const [hasFiles, setHasFiles] = useState(true);
+  const [canDelete, setCanDelete] = useState(false);
 
   useEffect(() => {
     async function fetchKeys() {
@@ -24,6 +25,9 @@ export default function DocumentSettings({ workspace }) {
       const hasAnyFiles = localFiles.items.some(
         (folder) => folder?.items?.length > 0
       );
+
+      const canDelete = await System.getCanDeleteWorkspaces();
+      setCanDelete(canDelete);
       setDirectories(localFiles);
       setOriginalDocuments([...originalDocs]);
       setSelectFiles([...originalDocs]);
@@ -92,13 +96,6 @@ export default function DocumentSettings({ workspace }) {
       : selectedFiles.some((doc) => doc.includes(filepath));
   };
 
-  const isOriginalDoc = (filepath) => {
-    const isFolder = !filepath.includes("/");
-    return isFolder
-      ? originalDocuments.some((doc) => doc.includes(filepath.split("/")[0]))
-      : originalDocuments.some((doc) => doc.includes(filepath));
-  };
-
   const toggleSelection = (filepath) => {
     const isFolder = !filepath.includes("/");
     const parent = isFolder ? filepath : filepath.split("/")[0];
@@ -179,14 +176,19 @@ export default function DocumentSettings({ workspace }) {
           </div>
         </div>
       </div>
-      <div className="flex items-center justify-between p-4 md:p-6 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600">
+      <div
+        className={`flex items-center ${canDelete ? "justify-between" : "justify-end"
+          } p-4 md:p-6 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600`}
+      >
         <button
+          hidden={!canDelete}
           onClick={deleteWorkspace}
           type="button"
           className="border border-transparent text-gray-500 bg-white hover:bg-red-100 rounded-lg whitespace-nowrap text-sm font-medium px-5 py-2.5 hover:text-red-900 focus:z-10 dark:bg-transparent dark:text-gray-300 dark:hover:text-white dark:hover:bg-red-600"
         >
           Delete Workspace
         </button>
+
         <div className="flex items-center">
           <button
             disabled={saving}
diff --git a/frontend/src/models/system.js b/frontend/src/models/system.js
index bcab69f3e..219690d18 100644
--- a/frontend/src/models/system.js
+++ b/frontend/src/models/system.js
@@ -188,6 +188,22 @@ const System = {
         return { success: false, error: e.message };
       });
   },
+  getCanDeleteWorkspaces: async function () {
+    return await fetch(`${API_BASE}/system/can-delete-workspaces`, {
+      method: "GET",
+      cache: "no-cache",
+      headers: baseHeaders(),
+    })
+      .then((res) => {
+        if (!res.ok) throw new Error("Could not fetch can delete workspaces.");
+        return res.json();
+      })
+      .then((res) => res?.canDelete)
+      .catch((e) => {
+        console.error(e);
+        return false;
+      });
+  },
   getWelcomeMessages: async function () {
     return await fetch(`${API_BASE}/system/welcome-messages`, {
       method: "GET",
diff --git a/server/endpoints/system.js b/server/endpoints/system.js
index 85416f4cd..736ab1418 100644
--- a/server/endpoints/system.js
+++ b/server/endpoints/system.js
@@ -431,6 +431,34 @@ function systemEndpoints(app) {
     }
   );
 
+  app.get(
+    "/system/can-delete-workspaces",
+    [validatedRequest],
+    async function (request, response) {
+      try {
+        if (!response.locals.multiUserMode) {
+          return response.status(200).json({ canDelete: true });
+        }
+
+        if (response.locals.user?.role === "admin") {
+          return response.status(200).json({ canDelete: true });
+        }
+
+        const canDelete = await SystemSettings.canDeleteWorkspaces();
+        response.status(200).json({ canDelete });
+      } catch (error) {
+        console.error("Error fetching can delete workspaces:", error);
+        response
+          .status(500)
+          .json({
+            success: false,
+            message: "Internal server error",
+            canDelete: false,
+          });
+      }
+    }
+  );
+
   app.get("/system/welcome-messages", async function (request, response) {
     try {
       const welcomeMessages = await WelcomeMessages.getMessages();
diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js
index 7e2356301..9271fe3cf 100644
--- a/server/models/systemSettings.js
+++ b/server/models/systemSettings.js
@@ -180,6 +180,12 @@ const SystemSettings = {
     const result = await this.get(`label = 'logo_filename'`);
     return result ? result.value : null;
   },
+  canDeleteWorkspaces: async function () {
+    return (
+      (await this.get(`label = 'users_can_delete_workspaces'`))?.value ===
+      "true"
+    );
+  },
 };
 
 module.exports.SystemSettings = SystemSettings;
-- 
GitLab