Files
habitica/website/server/models/userHistory.js
Phillip Thelen 379afa9554 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 16:48:21 -05:00

130 lines
3.1 KiB
JavaScript

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);
},
};
};