diff --git a/README.md b/README.md index c31f95e..b440a2e 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,8 @@ Base URL: `http://localhost:5000` | `PUT` | `/api/profile` | Update the current user's profile | ✅ | | `GET` | `/api/search/teammates` | Search teammates by skill & availability | ✅ | | `GET` | `/api/teammates` | Paginated teammate list | ✅ | +| `DELETE` | `/api/profile` | Permanently delete the current user's account | ✅ | +| `DELETE` | `/api/teammates/:id` | Delete a teammate entry | ✅ | **Example — search for ML developers:** diff --git a/public/dashboard.js b/public/dashboard.js index f4b0958..2e2ff0f 100644 --- a/public/dashboard.js +++ b/public/dashboard.js @@ -83,7 +83,10 @@ document.addEventListener("DOMContentLoaded", () => {
${escapeHtml(u.bio || "No bio provided yet.")}
Error loading profile: ${escapeHtml(err.message)}
`; @@ -114,6 +122,32 @@ document.addEventListener("DOMContentLoaded", () => { } } + // ----------------------------------------------------------- + // Delete Account Handler + // ----------------------------------------------------------- + async function handleDeleteAccount() { + const confirmed = window.confirm( + "Are you sure you want to permanently delete your account? This cannot be undone." + ); + if (!confirmed) return; + + try { + const res = await fetch("/api/profile", { + method: "DELETE", + headers: { Authorization: `Bearer ${token}` } + }); + const data = await res.json(); + if (!data.success) { + throw new Error(data.message || "Failed to delete account"); + } + localStorage.removeItem("authToken"); + window.location.href = "signup.html"; + } catch (err) { + console.error("Delete account error:", err); + window.alert("Error deleting account: " + err.message); + } + } + // ----------------------------------------------------------- // Teammates Fetch & Render // ----------------------------------------------------------- diff --git a/server.js b/server.js index 5f1f445..3f9e081 100644 --- a/server.js +++ b/server.js @@ -435,6 +435,36 @@ app.put("/api/profile", authenticateUser, async (req, res) => { } }); +// Delete Account (permanent — removes the user and all their sessions) +app.delete("/api/profile", authenticateUser, async (req, res) => { + try { + const userId = req.user._id || req.user.id; + + // 1. MongoDB Mode + if (mongoose.connection.readyState === 1) { + await Session.deleteMany({ userId }); + await User.findByIdAndDelete(userId); + return res.json({ success: true, message: "Account deleted successfully" }); + } + + // 2. In-Memory Mode + const idx = inMemoryUsers.findIndex(u => u.id === userId || u._id === userId); + if (idx !== -1) { + inMemoryUsers.splice(idx, 1); + } + Object.keys(inMemorySessions).forEach((t) => { + if (inMemorySessions[t].userId === userId) { + delete inMemorySessions[t]; + } + }); + + res.json({ success: true, message: "Account deleted successfully" }); + } catch (error) { + console.error("Delete account error:", error); + res.status(500).json({ success: false, message: "Error deleting account" }); + } +}); + // Logout app.post("/api/logout", authenticateUser, async (req, res) => { try { @@ -610,6 +640,38 @@ app.get("/api/teammates", async (req, res) => { } }); +// Delete a Teammate entry (moderation / cleanup) +app.delete("/api/teammates/:id", authenticateUser, async (req, res) => { + try { + const { id } = req.params; + + // 1. MongoDB Mode + if (mongoose.connection.readyState === 1) { + try { + const deleted = await Teammate.findByIdAndDelete(id); + if (!deleted) { + return res.status(404).json({ success: false, message: "Teammate not found" }); + } + return res.json({ success: true, message: "Teammate deleted successfully" }); + } catch (mongoErr) { + console.warn("MongoDB teammate delete error, falling back to memory:", mongoErr.message); + } + } + + // 2. In-Memory Mode + const idx = inMemoryTeammates.findIndex(t => t.id === id || t._id === id); + if (idx === -1) { + return res.status(404).json({ success: false, message: "Teammate not found" }); + } + inMemoryTeammates.splice(idx, 1); + + res.json({ success: true, message: "Teammate deleted successfully" }); + } catch (error) { + console.error("Delete teammate error:", error); + res.status(500).json({ success: false, message: "Error deleting teammate" }); + } +}); + // Database status (diagnostic endpoint) app.get("/api/db-status", authenticateUser, async (req, res) => { try {