623 lines
20 KiB
HTML
623 lines
20 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<html>
|
|
<head>
|
|
<title>User.js</title>
|
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
|
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
|
|
<link rel="stylesheet" media="all" href="docco.css" />
|
|
</head>
|
|
<body>
|
|
<div id="container">
|
|
<div id="background"></div>
|
|
|
|
<ul id="jump_to">
|
|
<li>
|
|
<a class="large" href="javascript:void(0);">Jump To …</a>
|
|
<a class="small" href="javascript:void(0);">+</a>
|
|
<div id="jump_wrapper">
|
|
<div id="jump_page">
|
|
|
|
|
|
<a class="source" href="group.html">
|
|
group.js
|
|
</a>
|
|
|
|
|
|
<a class="source" href="user.html">
|
|
user.js
|
|
</a>
|
|
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
|
|
<ul class="sections">
|
|
|
|
|
|
|
|
<li id="section-1">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap for-h1">
|
|
<a class="pilcrow" href="#section-1">¶</a>
|
|
</div>
|
|
<h1>User.js</h1>
|
|
|
|
</div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-2">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-2">¶</a>
|
|
</div>
|
|
<p>Defines the user data model (schema) for use via the API.</p>
|
|
<h2>Dependencies</h2>
|
|
|
|
</div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-3">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-3">¶</a>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="keyword">var</span> mongoose = require(<span class="string">"mongoose"</span>);
|
|
<span class="keyword">var</span> Schema = mongoose.Schema;
|
|
<span class="keyword">var</span> helpers = require(<span class="string">'habitrpg-shared/script/helpers'</span>);
|
|
<span class="keyword">var</span> _ = require(<span class="string">'lodash'</span>);</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-4">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap for-h2">
|
|
<a class="pilcrow" href="#section-4">¶</a>
|
|
</div>
|
|
<h2>User Schema</h2>
|
|
|
|
</div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-5">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-5">¶</a>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="keyword">var</span> UserSchema = <span class="keyword">new</span> Schema({</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-6">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap for-h3">
|
|
<a class="pilcrow" href="#section-6">¶</a>
|
|
</div>
|
|
<h3>UUID and API Token</h3>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> _id: {
|
|
type: String,
|
|
<span class="string">'default'</span>: helpers.uuid
|
|
},
|
|
apiToken: {
|
|
type: String,
|
|
<span class="string">'default'</span>: helpers.uuid
|
|
},</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-7">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap for-h3">
|
|
<a class="pilcrow" href="#section-7">¶</a>
|
|
</div>
|
|
<h3>Mongoode Update Object</h3>
|
|
<p>We want to know <em>every</em> time an object updates. Mongoose uses __v to designate when an object contains arrays which
|
|
have been updated (<a href="http://goo.gl/gQLz41">http://goo.gl/gQLz41</a>), but we want <em>every</em> update</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> _v: {
|
|
type: Number,
|
|
<span class="string">'default'</span>: <span class="number">0</span>
|
|
},
|
|
achievements: {
|
|
originalUser: Boolean,
|
|
helpedHabit: Boolean,
|
|
ultimateGear: Boolean,
|
|
beastMaster: Boolean,
|
|
streak: Number
|
|
},
|
|
auth: {
|
|
facebook: Schema.Types.Mixed,
|
|
local: {
|
|
email: String,
|
|
hashed_password: String,
|
|
salt: String,
|
|
username: String
|
|
},
|
|
timestamps: {
|
|
created: {
|
|
type: Date,
|
|
<span class="string">'default'</span>: Date.now
|
|
},
|
|
loggedin: Date
|
|
}
|
|
},
|
|
|
|
backer: {
|
|
tier: Number,
|
|
admin: Boolean,
|
|
npc: String,
|
|
contributor: String,
|
|
tokensApplied: Boolean
|
|
},
|
|
|
|
balance: Number,
|
|
habitIds: Array,
|
|
dailyIds: Array,
|
|
todoIds: Array,
|
|
rewardIds: Array,
|
|
filters: {type: Schema.Types.Mixed, <span class="string">'default'</span>: {}},
|
|
|
|
flags: {
|
|
showTour: {type: Boolean, <span class="string">'default'</span>: <span class="literal">true</span>},
|
|
ads: {type: String, <span class="string">'default'</span>: <span class="string">'show'</span>}, <span class="comment">// FIXME make this a boolean, run migration</span>
|
|
dropsEnabled: {type: Boolean, <span class="string">'default'</span>: <span class="literal">false</span>},
|
|
itemsEnabled: {type: Boolean, <span class="string">'default'</span>: <span class="literal">false</span>},
|
|
newStuff: {type: String, <span class="string">'default'</span>: <span class="string">'hide'</span>}, <span class="comment">//FIXME to boolean (currently show/hide)</span>
|
|
rewrite: {type: Boolean, <span class="string">'default'</span>: <span class="literal">true</span>},
|
|
partyEnabled: Boolean, <span class="comment">// FIXME do we need this?</span>
|
|
petsEnabled: {type: Boolean, <span class="string">'default'</span>: <span class="literal">false</span>},
|
|
rest: {type: Boolean, <span class="string">'default'</span>: <span class="literal">false</span>} <span class="comment">// fixme - change to preferences.resting once we're off derby</span>
|
|
},
|
|
history: {
|
|
exp: [
|
|
{
|
|
date: Date,
|
|
value: Number
|
|
}
|
|
],
|
|
todos: [
|
|
{
|
|
data: Date,
|
|
value: Number
|
|
}
|
|
]
|
|
},
|
|
<span class="comment">/* FIXME remove?*/</span>
|
|
|
|
invitations: {
|
|
guilds: {type: Array, <span class="string">'default'</span>: []},
|
|
party: Schema.Types.Mixed
|
|
},
|
|
items: {
|
|
armor: Number,
|
|
weapon: Number,
|
|
head: Number,
|
|
shield: Number,
|
|
|
|
<span class="comment">/*FIXME - tidy this up, not the best way to store current pet*/</span>
|
|
|
|
currentPet: {
|
|
<span class="comment">/*Cactus*/</span>
|
|
|
|
text: String,
|
|
<span class="comment">/*Cactus*/</span>
|
|
|
|
name: String,
|
|
<span class="comment">/*3*/</span>
|
|
|
|
value: Number,
|
|
<span class="comment">/*"Find a hatching potion to pour on this egg, and one day it will hatch into a loyal pet.",*/</span>
|
|
|
|
notes: String,
|
|
<span class="comment">/*Skeleton*/</span>
|
|
|
|
modifier: String,
|
|
<span class="comment">/*Cactus-Skeleton*/</span>
|
|
|
|
str: String
|
|
},
|
|
|
|
eggs: [
|
|
{</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-8">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-8">¶</a>
|
|
</div>
|
|
<p>example: You've found a Wolf Egg! Find a hatching potion to pour on this egg, and one day it will hatch into a loyal pet</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> dialog: String,</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-9">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-9">¶</a>
|
|
</div>
|
|
<p>example: Wolf</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> name: String,</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-10">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-10">¶</a>
|
|
</div>
|
|
<p>example: Find a hatching potion to pour on this egg, and one day it will hatch into a loyal pet.</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> notes: String,</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-11">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-11">¶</a>
|
|
</div>
|
|
<p>example: Wolf </p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> text: String,
|
|
<span class="comment">/* type: String, //Egg // this is forcing mongoose to return object as "[object Object]", but I don't think this is needed anyway? */</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-12">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-12">¶</a>
|
|
</div>
|
|
<p>example: 3</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> value: Number
|
|
}
|
|
],
|
|
hatchingPotions: Array, <span class="comment">// ["Base", "Skeleton",...]</span>
|
|
lastDrop: {
|
|
date: {type: Date, <span class="string">'default'</span>: Date.now},
|
|
count: {type: Number, <span class="string">'default'</span>: <span class="number">0</span>}
|
|
},</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-13">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-13">¶</a>
|
|
</div>
|
|
<p>["BearCub-Base", "Cactus-Base", ...]</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> pets: Array
|
|
},</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-14">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-14">¶</a>
|
|
</div>
|
|
<p>FIXME store as Date?</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> lastCron: {
|
|
type: Date,
|
|
<span class="string">'default'</span>: Date.now
|
|
},</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-15">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-15">¶</a>
|
|
</div>
|
|
<p>FIXME remove?</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> party: {</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-16">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-16">¶</a>
|
|
</div>
|
|
<p>party._id // FIXME make these populate docs?</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> current: String, <span class="comment">// party._id</span>
|
|
invitation: String, <span class="comment">// party._id</span>
|
|
lastMessageSeen: String,
|
|
leader: Boolean
|
|
},
|
|
preferences: {
|
|
armorSet: String,
|
|
dayStart: {type:Number, <span class="string">'default'</span>: <span class="number">0</span>},
|
|
gender: {type:String, <span class="string">'default'</span>: <span class="string">'m'</span>},
|
|
hair: {type:String, <span class="string">'default'</span>:<span class="string">'blond'</span>},
|
|
hideHeader: {type:Boolean, <span class="string">'default'</span>:<span class="literal">false</span>},
|
|
showHelm: {type:Boolean, <span class="string">'default'</span>:<span class="literal">true</span>},
|
|
skin: {type:String, <span class="string">'default'</span>:<span class="string">'white'</span>},
|
|
timezoneOffset: Number
|
|
},
|
|
profile: {
|
|
blurb: String,
|
|
imageUrl: String,
|
|
name: String,
|
|
websites: Array <span class="comment">// styled like --> ["http://ocdevel.com" ]</span>
|
|
},
|
|
stats: {
|
|
hp: Number,
|
|
exp: Number,
|
|
gp: Number,
|
|
lvl: Number
|
|
},
|
|
tags: [
|
|
{</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-17">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-17">¶</a>
|
|
</div>
|
|
<p>FIXME use refs?</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> id: String,
|
|
name: String
|
|
}
|
|
],</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-18">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap for-h3">
|
|
<a class="pilcrow" href="#section-18">¶</a>
|
|
</div>
|
|
<h3>Tasks Definition</h3>
|
|
<p>We can't define <code>tasks</code> until we move off Derby, since Derby requires dictionary of objects. When we're off, migrate
|
|
to array of subdocs</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> tasks: Schema.Types.Mixed
|
|
<span class="comment">/*
|
|
# history: {date, value}
|
|
# id
|
|
# notes
|
|
# tags { "4ddf03d9-54bd-41a3-b011-ca1f1d2e9371" : true },
|
|
# text
|
|
# type
|
|
# up
|
|
# down
|
|
# value
|
|
# completed
|
|
# priority: '!!'
|
|
# repeat {m: true, t: true}
|
|
# streak
|
|
*/</span>
|
|
|
|
}, {
|
|
strict: <span class="literal">true</span>
|
|
});</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-19">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap for-h2">
|
|
<a class="pilcrow" href="#section-19">¶</a>
|
|
</div>
|
|
<h2>Legacy Derby Function?</h2>
|
|
|
|
</div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-20">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-20">¶</a>
|
|
</div>
|
|
<p>Derby requires a strange storage format for somethign called "refLists". Here we hook into loading the data, so we
|
|
can provide a more "expected" storage format for our various helper methods. Since the attributes are passed by reference,
|
|
the underlying data will be modified too - so when we save back to the database, it saves it in the way Derby likes.
|
|
This will go away after the rewrite is complete</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="keyword">function</span> <span class="title">transformTaskLists</span><span class="params">(doc)</span> {</span>
|
|
_.each([<span class="string">'habit'</span>, <span class="string">'daily'</span>, <span class="string">'todo'</span>, <span class="string">'reward'</span>], <span class="keyword">function</span>(type) {</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-21">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-21">¶</a>
|
|
</div>
|
|
<p>we use <em>.transform instead of a simple </em>.where in order to maintain sort-order</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> doc[type + <span class="string">"s"</span>] = _.reduce(doc[type + <span class="string">"Ids"</span>], <span class="keyword">function</span>(m, tid) {
|
|
<span class="keyword">if</span> (!doc.tasks[tid]) <span class="keyword">return</span> m; <span class="comment">// FIXME tmp hotfix, people still have null tasks?</span>
|
|
<span class="keyword">if</span> (!doc.tasks[tid].tags) doc.tasks[tid].tags = {}; <span class="comment">// FIXME remove this when we switch tasks to subdocs and can define tags default in schema</span>
|
|
m.push(doc.tasks[tid]);
|
|
<span class="keyword">return</span> m;
|
|
}, []);
|
|
});
|
|
}
|
|
|
|
UserSchema.post(<span class="string">'init'</span>, <span class="keyword">function</span>(doc) {
|
|
transformTaskLists(doc);
|
|
});
|
|
|
|
UserSchema.methods.toJSON = <span class="keyword">function</span>() {
|
|
<span class="keyword">var</span> doc = <span class="keyword">this</span>.toObject();
|
|
doc.id = doc._id;
|
|
transformTaskLists(doc); <span class="comment">// we need to also transform for our server-side routes</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-22">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-22">¶</a>
|
|
</div>
|
|
<p>FIXME? Is this a reference to <code>doc.filters</code> or just disabled code? Remove?</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> <span class="comment">/*</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-23">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-23">¶</a>
|
|
</div>
|
|
<p>Remove some unecessary data as far as client consumers are concerned
|
|
_.each(['habit', 'daily', 'todo', 'reward'], function(type) {
|
|
delete doc["#{type}Ids"]
|
|
});
|
|
delete doc.tasks</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> */
|
|
doc.filters = {};
|
|
|
|
return doc;
|
|
};</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-24">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-24">¶</a>
|
|
</div>
|
|
<p>FIXME - since we're using special @post('init') above, we need to flag when the original path was modified.
|
|
Custom setter/getter virtuals?</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>UserSchema.pre(<span class="string">'save'</span>, <span class="keyword">function</span>(next) {
|
|
<span class="keyword">this</span>.markModified(<span class="string">'tasks'</span>);</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-25">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-25">¶</a>
|
|
</div>
|
|
<p>our own version incrementer</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> <span class="keyword">this</span>._v++;
|
|
next();
|
|
});
|
|
|
|
module.exports.schema = UserSchema;
|
|
module.exports.model = mongoose.model(<span class="string">"User"</span>, UserSchema);</pre></div></div>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</div>
|
|
</body>
|
|
</html>
|