Files
habitica/website/server/controllers/api-v4/members.js
T
Kalista Payne fb2eaa3950 Move user deletion to worker (#15586)
* WIP(delete): remove business logic from controller

* fix(deletion): handle group leave logic on app server still

* fix(lint): unused import

* fix(import): bracket syntax

* fix(test): adapt test for worker flow

* fix(deletion): update delete/feedback form copy

* fix(text): don't break to new paragraph about Gems

* fix(deletion): remove orphaned chat messages

* Revert "fix(deletion): handle group leave logic on app server still"

This reverts commit 9db541f4c3.

* fix(tests): remove tests
These can potentially be tested in the worker's suite? They target functionality that the group leave route handles within the deletion flow

* fix(lint): no-undef

* refactor redis setup into own file and use ioredis

* use bullmq directly to schedule jobs

* add space

* add key prefix

* add semicolon

* fix(jobs): update redis package

---------

Co-authored-by: Phillip Thelen <phillip@habitica.com>
2026-05-26 17:43:49 -05:00

64 lines
2.0 KiB
JavaScript

import worker from '../../libs/worker';
import { authWithHeaders } from '../../middlewares/auth';
import { ensurePermission } from '../../middlewares/ensureAccessRight';
import { TransactionModel as Transaction } from '../../models/transaction';
const api = {};
/**
* @api {get} /api/v4/members/:memberId/purchase-history Get members purchase history
* @apiName MemberGetPurchaseHistory
* @apiGroup Member
*
*/
api.purchaseHistory = {
method: 'GET',
middlewares: [authWithHeaders(), ensurePermission('userSupport')],
url: '/members/:memberId/purchase-history',
async handler (req, res) {
req.checkParams('memberId', res.t('memberIdRequired')).notEmpty().isUUID();
const validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
let transactions = await Transaction
.find({ userId: req.params.memberId })
.sort({ createdAt: -1 })
.exec();
if (!res.locals.user.hasPermission('userSupport')) {
transactions = transactions.filter(t => t.transactionType !== 'create_bank_challenge');
}
res.respond(200, transactions);
},
};
/**
* @api {delete} /api/v4/members/:memberId Delete a user
* @apiName DeleteMember
* @apiGroup Member
*
*/
api.deleteMember = {
method: 'DELETE',
middlewares: [authWithHeaders(), ensurePermission('userSupport')],
url: '/members/:memberId',
async handler (req, res) {
req.checkParams('memberId', res.t('memberIdRequired')).notEmpty().isUUID();
req.checkQuery('deleteAccount').optional().isIn(['true', 'false']);
req.checkQuery('deleteAmplitude').optional().isIn(['true', 'false']);
const validationErrors = req.validationErrors();
if (validationErrors) throw validationErrors;
await worker.sendJob('deleteUser', {
identifier: req.params.memberId,
data: {
userId: req.params.memberId,
deleteAccount: req.query.deleteAccount === 'true',
deleteAmplitude: req.query.deleteAmplitude === 'true',
},
});
res.respond(200, {});
},
};
export default api;