Skip to content

Commit a26ec55

Browse files
committed
Add backend user deletion cascade cleanup endpoint
1 parent de2ba8d commit a26ec55

3 files changed

Lines changed: 40 additions & 3 deletions

File tree

backend/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Server starts at `http://localhost:4000` by default.
3434
- `GET /api/orders?spotId=...&userId=...`
3535
- `POST /api/orders`
3636
- `GET /api/bills/:spotId`
37+
- `DELETE /api/users/:userId` (removes the user and all related records)
3738

3839
## Example login payload
3940

backend/db.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ db.exec(`
5353
location TEXT NOT NULL,
5454
date TEXT NOT NULL,
5555
host_user_id TEXT NOT NULL,
56-
FOREIGN KEY (host_user_id) REFERENCES users(id)
56+
FOREIGN KEY (host_user_id) REFERENCES users(id) ON DELETE CASCADE
5757
);
5858
5959
CREATE TABLE IF NOT EXISTS catalog_items (
@@ -70,7 +70,7 @@ db.exec(`
7070
total_amount REAL NOT NULL,
7171
created_at TEXT NOT NULL,
7272
FOREIGN KEY (spot_id) REFERENCES spots(id),
73-
FOREIGN KEY (user_id) REFERENCES users(id)
73+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
7474
);
7575
7676
CREATE TABLE IF NOT EXISTS order_items (
@@ -160,6 +160,9 @@ const userExistsStatement = db.prepare('SELECT 1 AS found FROM users WHERE id =
160160
const spotExistsStatement = db.prepare('SELECT 1 AS found FROM spots WHERE id = ? LIMIT 1');
161161
const getUserByUsernameStatement = db.prepare('SELECT id, username, password, name, role FROM users WHERE username = ?');
162162
const updateUserPasswordStatement = db.prepare('UPDATE users SET password = ? WHERE id = ?');
163+
const deleteUserByIdStatement = db.prepare('DELETE FROM users WHERE id = ?');
164+
const deleteOrdersByUserIdStatement = db.prepare('DELETE FROM orders WHERE user_id = ?');
165+
const deleteSpotsByHostUserIdStatement = db.prepare('DELETE FROM spots WHERE host_user_id = ?');
163166

164167
export const database = {
165168
getUserByCredentials(username, password) {
@@ -303,6 +306,21 @@ export const database = {
303306
};
304307
},
305308

309+
deleteUserCompletely(userId) {
310+
db.exec('BEGIN');
311+
312+
try {
313+
deleteOrdersByUserIdStatement.run(userId);
314+
deleteSpotsByHostUserIdStatement.run(userId);
315+
deleteUserByIdStatement.run(userId);
316+
317+
db.exec('COMMIT');
318+
} catch (error) {
319+
db.exec('ROLLBACK');
320+
throw error;
321+
}
322+
},
323+
306324
getBillBySpotId(spotId) {
307325
const summaryRows = db
308326
.prepare(

backend/server.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const sendJson = (res, statusCode, body) => {
99
'Content-Type': 'application/json',
1010
'Access-Control-Allow-Origin': '*',
1111
'Access-Control-Allow-Headers': 'Content-Type',
12-
'Access-Control-Allow-Methods': 'GET,POST,OPTIONS',
12+
'Access-Control-Allow-Methods': 'GET,POST,DELETE,OPTIONS',
1313
});
1414
res.end(JSON.stringify(body));
1515
};
@@ -149,6 +149,24 @@ const server = createServer(async (req, res) => {
149149
return;
150150
}
151151

152+
if (method === 'DELETE' && path.startsWith('/api/users/')) {
153+
const userId = path.replace('/api/users/', '');
154+
155+
if (!userId) {
156+
sendJson(res, 400, { error: 'userId is required' });
157+
return;
158+
}
159+
160+
if (!database.userExists(userId)) {
161+
sendJson(res, 404, { error: `Unknown userId: ${userId}` });
162+
return;
163+
}
164+
165+
database.deleteUserCompletely(userId);
166+
sendJson(res, 200, { success: true, deletedUserId: userId });
167+
return;
168+
}
169+
152170
sendJson(res, 404, { error: 'Route not found' });
153171
});
154172

0 commit comments

Comments
 (0)