habitica/website/server/models/userHistory.js

130 lines
3.1 KiB
JavaScript
Raw Permalink Normal View History

Improve Adminpanel with local logs (#15404) * log armoire, quoest response and cron events to history * show user history in admin panel * allow stats to be edited from admin panel * Improve admin panel stats input * improve setting client in history * fix tests * fix lint * fix armoire buying issue * Improve hero saving * Formatting fix * Improve user history logging * allow class to be changed from admin panel * make terminating subscriptions easier * support decimal extraMonths * Fix editing some achievements in admin panel * log if a user invites party to quest * Log more quest events into user history * make userhistory length configurable * fix some numbered achievements * fix extraMonths field * Automatically set up group plan subs with admin panel * show party info nicer in admin panel * improve admin panel sub handling * add missing brace * display when there are unsaved changes * fix setting group plan * fix showing group id * Display group plan info in admin panel * fix setting hourglass promo date * Improve termination handling in admin panel * reload data after certain save events in admin panel * remove console * fix plan.extraMonths not being reset if terminating a sub * add more options when cancelling subs * reload data after group plan change * Add a way to remove users from a party * fix issue with removing user from party * pass party id correctly * correctly call async function * Improve sub display in admin panel * fix line length * fix line * shorter * plaid * fix(lint): vue code style --------- Co-authored-by: Kalista Payne <sabrecat@gmail.com>
2025-03-17 21:48:21 +00:00
import nconf from 'nconf';
import mongoose from 'mongoose';
import validator from 'validator';
import baseModel from '../libs/baseModel';
const { Schema } = mongoose;
const userHistoryLength = nconf.get('USER_HISTORY_LENGTH') || 20;
export const schema = new Schema({
userId: {
$type: String,
ref: 'User',
required: true,
validate: [v => validator.isUUID(v), 'Invalid uuid for userhistory.'],
index: true,
unique: true,
},
armoire: [
{
_id: false,
timestamp: { $type: Date, required: true },
client: { $type: String, required: false },
reward: { $type: String, required: true },
},
],
questInviteResponses: [
{
_id: false,
timestamp: { $type: Date, required: true },
client: { $type: String, required: false },
quest: { $type: String, required: true },
response: { $type: String, required: true },
},
],
cron: [
{
_id: false,
timestamp: { $type: Date, required: true },
checkinCount: { $type: Number, required: true },
client: { $type: String, required: false },
},
],
}, {
strict: true,
minimize: false, // So empty objects are returned
typeKey: '$type', // So that we can use fields named `type`
});
schema.plugin(baseModel, {
noSet: ['id', '_id', 'userId'],
timestamps: true,
_id: false, // using custom _id
});
export const model = mongoose.model('UserHistory', schema);
const commitUserHistoryUpdate = function commitUserHistoryUpdate (update) {
const data = {
$push: {
},
};
if (update.data.armoire.length) {
data.$push.armoire = {
$each: update.data.armoire,
$sort: { timestamp: -1 },
$slice: userHistoryLength,
};
}
if (update.data.questInviteResponses.length) {
data.$push.questInviteResponses = {
$each: update.data.questInviteResponses,
$sort: { timestamp: -1 },
$slice: userHistoryLength,
};
}
if (update.data.cron.length > 0) {
data.$push.cron = {
$each: update.data.cron,
$sort: { timestamp: -1 },
$slice: userHistoryLength,
};
}
return model.updateOne(
{ userId: update.userId },
data,
).exec();
};
model.beginUserHistoryUpdate = function beginUserHistoryUpdate (userID, headers = null) {
return {
userId: userID,
data: {
headers: headers || {},
armoire: [],
questInviteResponses: [],
cron: [],
},
withArmoire: function withArmoire (reward) {
this.data.armoire.push({
timestamp: new Date(),
client: this.data.headers['x-client'],
reward,
});
return this;
},
withQuestInviteResponse: function withQuestInviteResponse (quest, response) {
this.data.questInviteResponses.push({
timestamp: new Date(),
client: this.data.headers['x-client'],
quest,
response,
});
return this;
},
withCron: function withCron (checkinCount) {
this.data.cron.push({
timestamp: new Date(),
checkinCount,
client: this.data.headers['x-client'],
});
return this;
},
commit: function commit () {
commitUserHistoryUpdate(this);
},
};
};