mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 15:17:25 +01:00
Remove user wrapping (#9960)
* remove user wrapping, fixes #9146 * update tests * fix tests
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
import partial from 'lodash/partial';
|
||||
|
||||
// When using a common module from the website or the server NEVER import the module directly
|
||||
// but access it through `api` (the main common) module, otherwise you would require the non transpiled version of the file in production.
|
||||
let api = module.exports = {};
|
||||
@@ -212,121 +210,3 @@ api.ops = {
|
||||
markPmsRead,
|
||||
pinnedGearUtils,
|
||||
};
|
||||
|
||||
/*
|
||||
------------------------------------------------------
|
||||
User (prototype wrapper to give it ops, helper funcs, and virtuals
|
||||
------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
User is now wrapped (both on client and server), adding a few new properties:
|
||||
* getters (_statsComputed)
|
||||
* user.fns, which is a bunch of helper functions
|
||||
These were originally up above, but they make more sense belonging to the user object so we don't have to pass
|
||||
the user object all over the place. In fact, we should pull in more functions such as cron(), updateStats(), etc.
|
||||
* user.ops, which is super important:
|
||||
|
||||
If a function is inside user.ops, it has magical properties. If you call it on the client it updates the user object in
|
||||
the browser and when it's done it automatically POSTs to the server, calling src/controllers/user.js#OP_NAME (the exact same name
|
||||
of the op function). The first argument req is {query, body, params}, it's what the express controller function
|
||||
expects. This means we call our functions as if we were calling an Express route. Eg, instead of score(task, direction),
|
||||
we call score({params:{id:task.id,direction:direction}}). This also forces us to think about our routes (whether to use
|
||||
params, query, or body for variables). see http://stackoverflow.com/questions/4024271/rest-api-best-practices-where-to-put-parameters
|
||||
|
||||
If `src/controllers/user.js#OP_NAME` doesn't exist on the server, it's automatically added. It runs the code in user.ops.OP_NAME
|
||||
to update the user model server-side, then performs `user.save()`. You can see this in action for `user.ops.buy`. That
|
||||
function doesn't exist on the server - so the client calls it, it updates user in the browser, auto-POSTs to server, server
|
||||
handles it by calling `user.ops.buy` again (to update user on the server), and then saves. We can do this for
|
||||
everything that doesn't need any code difference from what's in user.ops.OP_NAME for special-handling server-side. If we
|
||||
*do* need special handling, just add `src/controllers/user.js#OP_NAME` to override the user.ops.OP_NAME, and be
|
||||
sure to call user.ops.OP_NAME at some point within the overridden function.
|
||||
|
||||
TODO
|
||||
* Is this the best way to wrap the user object? I thought of using user.prototype, but user is an object not a Function.
|
||||
user on the server is a Mongoose model, so we can use prototype - but to do it on the client, we'd probably have to
|
||||
move to $resource for user
|
||||
* Move to $resource!
|
||||
*/
|
||||
|
||||
import importedOps from './ops';
|
||||
import importedFns from './fns';
|
||||
|
||||
// TODO Kept for the client side
|
||||
api.wrap = function wrapUser (user, main = true) {
|
||||
if (user._wrapped) return;
|
||||
user._wrapped = true;
|
||||
|
||||
// Make markModified available on the client side as a noop function
|
||||
if (!user.markModified) {
|
||||
user.markModified = function noopMarkModified () {};
|
||||
}
|
||||
|
||||
// same for addNotification
|
||||
if (!user.addNotification) {
|
||||
user.addNotification = function noopAddNotification () {};
|
||||
}
|
||||
|
||||
if (main) {
|
||||
user.ops = {
|
||||
sleep: partial(importedOps.sleep, user),
|
||||
revive: partial(importedOps.revive, user),
|
||||
reset: partial(importedOps.reset, user),
|
||||
reroll: partial(importedOps.reroll, user),
|
||||
rebirth: partial(importedOps.rebirth, user),
|
||||
allocateNow: partial(importedOps.allocateNow, user),
|
||||
sortTask: partial(importedOps.sortTask, user),
|
||||
updateTask: partial(importedOps.updateTask, user),
|
||||
deleteTask: partial(importedOps.deleteTask, user),
|
||||
addTask: partial(importedOps.addTask, user),
|
||||
addTag: partial(importedOps.addTag, user),
|
||||
sortTag: partial(importedOps.sortTag, user),
|
||||
updateTag: partial(importedOps.updateTag, user),
|
||||
deleteTag: partial(importedOps.deleteTag, user),
|
||||
clearPMs: partial(importedOps.clearPMs, user),
|
||||
deletePM: partial(importedOps.deletePM, user),
|
||||
blockUser: partial(importedOps.blockUser, user),
|
||||
feed: partial(importedOps.feed, user),
|
||||
buySpecialSpell: partial(importedOps.buySpecialSpell, user),
|
||||
purchase: partial(importedOps.purchase, user),
|
||||
releasePets: partial(importedOps.releasePets, user),
|
||||
releaseMounts: partial(importedOps.releaseMounts, user),
|
||||
releaseBoth: partial(importedOps.releaseBoth, user),
|
||||
buy: partial(importedOps.buy, user),
|
||||
buyHealthPotion: partial(importedOps.buyHealthPotion, user),
|
||||
buyArmoire: partial(importedOps.buyArmoire, user),
|
||||
buyGear: partial(importedOps.buyGear, user),
|
||||
buyQuest: partial(importedOps.buyQuest, user),
|
||||
buyMysterySet: partial(importedOps.buyMysterySet, user),
|
||||
hourglassPurchase: partial(importedOps.hourglassPurchase, user),
|
||||
sell: partial(importedOps.sell, user),
|
||||
equip: partial(importedOps.equip, user),
|
||||
hatch: partial(importedOps.hatch, user),
|
||||
unlock: partial(importedOps.unlock, user),
|
||||
changeClass: partial(importedOps.changeClass, user),
|
||||
disableClasses: partial(importedOps.disableClasses, user),
|
||||
allocate: partial(importedOps.allocate, user),
|
||||
readCard: partial(importedOps.readCard, user),
|
||||
openMysteryItem: partial(importedOps.openMysteryItem, user),
|
||||
score: partial(importedOps.scoreTask, user),
|
||||
markPmsRead: partial(importedOps.markPmsRead, user),
|
||||
};
|
||||
}
|
||||
|
||||
user.fns = {
|
||||
handleTwoHanded: partial(importedFns.handleTwoHanded, user),
|
||||
predictableRandom: partial(importedFns.predictableRandom, user),
|
||||
crit: partial(importedFns.crit.crit, user),
|
||||
randomDrop: partial(importedFns.randomDrop, user),
|
||||
autoAllocate: partial(importedFns.autoAllocate, user),
|
||||
updateStats: partial(importedFns.updateStats, user),
|
||||
statsComputed: partial(statsComputed, user),
|
||||
ultimateGear: partial(importedFns.ultimateGear, user),
|
||||
};
|
||||
|
||||
Object.defineProperty(user, '_statsComputed', {
|
||||
get () {
|
||||
return statsComputed(user);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user