From: PhiTux Date: Tue, 9 Sep 2025 15:43:42 +0000 (+0200) Subject: admin can delete old data (from before migration) X-Git-Url: http://git.99rst.org/?a=commitdiff_plain;h=254e12731ea4f7503b6746e13f9c51790018d3b7;p=DailyTxT.git admin can delete old data (from before migration) --- diff --git a/backend/handlers/admin.go b/backend/handlers/admin.go index 9628d6a..f6058e2 100644 --- a/backend/handlers/admin.go +++ b/backend/handlers/admin.go @@ -63,8 +63,11 @@ func validateAdminPasswordInRequest(r *http.Request) bool { return req.AdminPassword == adminPassword } -// GetAllUsers returns all users with their disk usage -func GetAllUsers(w http.ResponseWriter, r *http.Request) { +// GetAdminData returns: +// - all users with their disk usage +// - free disk space +// - migration-info +func GetAdminData(w http.ResponseWriter, r *http.Request) { if !validateAdminPasswordInRequest(r) { http.Error(w, "Invalid admin password", http.StatusUnauthorized) return @@ -115,10 +118,14 @@ func GetAllUsers(w http.ResponseWriter, r *http.Request) { freeSpace = 0 // Default to 0 if we can't determine free space } + // Check for old directory and get old users info + oldDirInfo := getOldDirectoryInfo() + w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]any{ "users": adminUsers, "free_space": freeSpace, + "old_data": oldDirInfo, }) } @@ -158,6 +165,59 @@ func getFreeDiskSpace() (int64, error) { return freeSpace, nil } +// getOldDirectoryInfo checks for old directory and returns info about old users and directory size +func getOldDirectoryInfo() map[string]any { + oldDirPath := filepath.Join(utils.Settings.DataPath, "old") + + // Check if old directory exists + if _, err := os.Stat(oldDirPath); os.IsNotExist(err) { + return map[string]any{ + "exists": false, + } + } + + // Read users.json from old directory + usersJsonPath := filepath.Join(oldDirPath, "users.json") + var oldUsernames []string + + if _, err := os.Stat(usersJsonPath); err == nil { + // Read and parse users.json + data, err := os.ReadFile(usersJsonPath) + if err == nil { + var usersData map[string]any + if json.Unmarshal(data, &usersData) == nil { + if usersList, ok := usersData["users"].([]any); ok { + for _, u := range usersList { + if user, ok := u.(map[string]any); ok { + if username, ok := user["username"].(string); ok { + oldUsernames = append(oldUsernames, username) + } + } + } + } + } + } + } + + // Calculate total size of old directory + var totalSize int64 + filepath.Walk(oldDirPath, func(path string, info os.FileInfo, err error) error { + if err != nil { + return nil // Continue on errors + } + if !info.IsDir() { + totalSize += info.Size() + } + return nil + }) + + return map[string]any{ + "exists": true, + "usernames": oldUsernames, + "total_size": totalSize, + } +} + // DeleteUser deletes a user and all their data func DeleteUser(w http.ResponseWriter, r *http.Request) { var req struct { @@ -194,3 +254,33 @@ func DeleteUser(w http.ResponseWriter, r *http.Request) { "success": true, }) } + +// DeleteOldData deletes the entire old directory +func DeleteOldData(w http.ResponseWriter, r *http.Request) { + if !validateAdminPasswordInRequest(r) { + http.Error(w, "Invalid admin password", http.StatusUnauthorized) + return + } + + oldDirPath := filepath.Join(utils.Settings.DataPath, "old") + + // Check if old directory exists + if _, err := os.Stat(oldDirPath); os.IsNotExist(err) { + http.Error(w, "Old directory does not exist", http.StatusNotFound) + return + } + + // Remove the entire old directory + if err := os.RemoveAll(oldDirPath); err != nil { + log.Printf("Error deleting old directory: %v", err) + http.Error(w, "Error deleting old directory", http.StatusInternalServerError) + return + } + + log.Printf("Old directory successfully deleted by admin (id: %d, username: %s)", r.Context().Value(utils.UserIDKey), r.Context().Value(utils.UsernameKey)) + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]bool{ + "success": true, + }) +} diff --git a/backend/main.go b/backend/main.go index c040b86..ed9bbc6 100644 --- a/backend/main.go +++ b/backend/main.go @@ -91,9 +91,10 @@ func main() { mux.HandleFunc("GET /logs/exportData", middleware.RequireAuth(handlers.ExportData)) // Admin routes - mux.HandleFunc("POST /admin/validate-password", handlers.ValidateAdminPassword) - mux.HandleFunc("POST /admin/users", handlers.GetAllUsers) - mux.HandleFunc("POST /admin/delete-user", handlers.DeleteUser) + mux.HandleFunc("POST /admin/validate-password", middleware.RequireAuth(handlers.ValidateAdminPassword)) + mux.HandleFunc("POST /admin/get-data", middleware.RequireAuth(handlers.GetAdminData)) + mux.HandleFunc("POST /admin/delete-user", middleware.RequireAuth(handlers.DeleteUser)) + mux.HandleFunc("POST /admin/delete-old-data", middleware.RequireAuth(handlers.DeleteOldData)) // Create a handler chain with Timeout, Logger and CORS middleware // Timeout middleware will be executed first, then Logger, then CORS diff --git a/frontend/src/lib/settings/Admin.svelte b/frontend/src/lib/settings/Admin.svelte index 481667c..f69090e 100644 --- a/frontend/src/lib/settings/Admin.svelte +++ b/frontend/src/lib/settings/Admin.svelte @@ -21,11 +21,15 @@ // Admin data let freeSpace = $state(0); + let oldData = $state({}); let users = $state([]); let isLoadingUsers = $state(false); let deleteUserId = $state(null); let isDeletingUser = $state(false); + let confirmDeleteOldData = $state(false); + let isDeletingOldData = $state(false); + onMount(() => { currentUser = localStorage.getItem('user'); resetAdminState(); @@ -75,9 +79,10 @@ isLoadingUsers = true; try { - const response = await makeAdminApiCall('/admin/users'); + const response = await makeAdminApiCall('/admin/get-data'); users = response.data.users || []; freeSpace = response.data.free_space; + oldData = response.data.old_data; } catch (error) { console.error('Error loading users:', error); if (error.response?.status === 401) { @@ -130,6 +135,44 @@ function confirmDeleteUser(userId) { deleteUserId = deleteUserId === userId ? null : userId; } + + // Delete old data directory + async function deleteOldData() { + if (isDeletingOldData) return; + isDeletingOldData = true; + + try { + const response = await makeAdminApiCall('/admin/delete-old-data'); + if (response.data.success) { + // Reset old data state + oldData = { exists: false }; + confirmDeleteOldData = false; + + // Show success toast + const toast = new bootstrap.Toast(document.getElementById('toastSuccessOldDataDelete')); + toast.show(); + } else { + // Show error toast + const toast = new bootstrap.Toast(document.getElementById('toastErrorOldDataDelete')); + toast.show(); + } + } catch (error) { + console.error('Error deleting old data:', error); + if (error.response?.status === 401) { + resetAdminState(); + } else { + // Show error toast + const toast = new bootstrap.Toast(document.getElementById('toastErrorOldDataDelete')); + toast.show(); + } + } finally { + isDeletingOldData = false; + } + } + + function toggleDeleteOldDataConfirmation() { + confirmDeleteOldData = !confirmDeleteOldData; + }
@@ -303,16 +346,91 @@
{/if} + + -
- + + {#if confirmDeleteOldData} +
+
+

+ {$t('settings.admin.confirm_delete_old_data')}
+ {@html $t('settings.admin.delete_old_data_warning')} +

+
+ + +
+
+
{/if} - {$t('settings.admin.refresh_users')} - +
+ {/if} + + +
+
{/if} @@ -343,6 +461,52 @@
{$t('settings.statistics.toast_error_user_delete')}
+ + + + + + +