Summary
DELETE /api/v1/teams/:teamId/databases/:databaseId answers 200 and writes a team.database.deleted audit entry even when dropping the Postgres database, user or role threw an error, in which case nothing was deleted and the database record is still there.
Steps to reproduce
- Use a Postgres tables driver (localfs or supavisor).
- Make one of the
DROP DATABASE, DROP USER or DROP ROLE statements fail, for example by keeping a connection open to the team database while deleting it (Postgres refuses to drop a database that has active connections).
DELETE /api/v1/teams/<teamId>/databases/<databaseId>.
Expected
A 500 unexpected_error (the route already has this branch), no deleted audit entry for a delete that did not happen, and the database record left intact.
Actual
The driver wraps the three drops and db.destroy() in a try whose catch is empty, so destroyDatabase resolves. The route then replies {} with 200 and logs the deletion. Callers are told the data is gone while the database, its roles and its record are all still there: a GET still returns it and a create returns 409 already_exists. A later DELETE succeeds once nothing is connected.
References
forge/ee/lib/tables/drivers/postgres-localfs.js:103-111
forge/ee/lib/tables/drivers/postgres-supavisor.js:173-180
forge/ee/routes/tables/index.js:173-205 (route and its success path)
- The Supavisor tenant delete at
postgres-supavisor.js:161-170 also swallows its error.
Summary
DELETE /api/v1/teams/:teamId/databases/:databaseIdanswers 200 and writes ateam.database.deletedaudit entry even when dropping the Postgres database, user or role threw an error, in which case nothing was deleted and the database record is still there.Steps to reproduce
DROP DATABASE,DROP USERorDROP ROLEstatements fail, for example by keeping a connection open to the team database while deleting it (Postgres refuses to drop a database that has active connections).DELETE /api/v1/teams/<teamId>/databases/<databaseId>.Expected
A 500
unexpected_error(the route already has this branch), nodeletedaudit entry for a delete that did not happen, and the database record left intact.Actual
The driver wraps the three drops and
db.destroy()in atrywhosecatchis empty, sodestroyDatabaseresolves. The route then replies{}with 200 and logs the deletion. Callers are told the data is gone while the database, its roles and its record are all still there: a GET still returns it and a create returns 409already_exists. A later DELETE succeeds once nothing is connected.References
forge/ee/lib/tables/drivers/postgres-localfs.js:103-111forge/ee/lib/tables/drivers/postgres-supavisor.js:173-180forge/ee/routes/tables/index.js:173-205(route and its success path)postgres-supavisor.js:161-170also swallows its error.