diff --git a/app/imports/Model/Campaign/Instance.js b/app/imports/api/campaign/Instance.js similarity index 100% rename from app/imports/Model/Campaign/Instance.js rename to app/imports/api/campaign/Instance.js diff --git a/app/imports/Model/Campaign/Party.js b/app/imports/api/campaign/Party.js similarity index 100% rename from app/imports/Model/Campaign/Party.js rename to app/imports/api/campaign/Party.js diff --git a/app/imports/Model/Creature/Actions.js b/app/imports/api/creature/Actions.js similarity index 100% rename from app/imports/Model/Creature/Actions.js rename to app/imports/api/creature/Actions.js diff --git a/app/imports/Model/Creature/Attacks.js b/app/imports/api/creature/Attacks.js similarity index 100% rename from app/imports/Model/Creature/Attacks.js rename to app/imports/api/creature/Attacks.js diff --git a/app/imports/Model/Creature/Attributes.js b/app/imports/api/creature/Attributes.js similarity index 100% rename from app/imports/Model/Creature/Attributes.js rename to app/imports/api/creature/Attributes.js diff --git a/app/imports/Model/Creature/Buffs.js b/app/imports/api/creature/Buffs.js similarity index 100% rename from app/imports/Model/Creature/Buffs.js rename to app/imports/api/creature/Buffs.js diff --git a/app/imports/Model/Creature/Classes.js b/app/imports/api/creature/Classes.js similarity index 100% rename from app/imports/Model/Creature/Classes.js rename to app/imports/api/creature/Classes.js diff --git a/app/imports/Model/Creature/Conditions.js b/app/imports/api/creature/Conditions.js similarity index 100% rename from app/imports/Model/Creature/Conditions.js rename to app/imports/api/creature/Conditions.js diff --git a/app/imports/Model/Creature/Creatures.js b/app/imports/api/creature/Creatures.js similarity index 100% rename from app/imports/Model/Creature/Creatures.js rename to app/imports/api/creature/Creatures.js diff --git a/app/imports/Model/Creature/CustomBuffs.js b/app/imports/api/creature/CustomBuffs.js similarity index 100% rename from app/imports/Model/Creature/CustomBuffs.js rename to app/imports/api/creature/CustomBuffs.js diff --git a/app/imports/Model/Creature/DamageMultipliers.js b/app/imports/api/creature/DamageMultipliers.js similarity index 100% rename from app/imports/Model/Creature/DamageMultipliers.js rename to app/imports/api/creature/DamageMultipliers.js diff --git a/app/imports/Model/Creature/Effects.js b/app/imports/api/creature/Effects.js similarity index 100% rename from app/imports/Model/Creature/Effects.js rename to app/imports/api/creature/Effects.js diff --git a/app/imports/Model/Creature/Experience.js b/app/imports/api/creature/Experience.js similarity index 100% rename from app/imports/Model/Creature/Experience.js rename to app/imports/api/creature/Experience.js diff --git a/app/imports/Model/Creature/Features.js b/app/imports/api/creature/Features.js similarity index 100% rename from app/imports/Model/Creature/Features.js rename to app/imports/api/creature/Features.js diff --git a/app/imports/Model/Creature/Notes.js b/app/imports/api/creature/Notes.js similarity index 100% rename from app/imports/Model/Creature/Notes.js rename to app/imports/api/creature/Notes.js diff --git a/app/imports/Model/Creature/Proficiencies.js b/app/imports/api/creature/Proficiencies.js similarity index 100% rename from app/imports/Model/Creature/Proficiencies.js rename to app/imports/api/creature/Proficiencies.js diff --git a/app/imports/Model/Creature/Skills.js b/app/imports/api/creature/Skills.js similarity index 100% rename from app/imports/Model/Creature/Skills.js rename to app/imports/api/creature/Skills.js diff --git a/app/imports/Model/Creature/SpellLists.js b/app/imports/api/creature/SpellLists.js similarity index 100% rename from app/imports/Model/Creature/SpellLists.js rename to app/imports/api/creature/SpellLists.js diff --git a/app/imports/Model/Creature/Spells.js b/app/imports/api/creature/Spells.js similarity index 100% rename from app/imports/Model/Creature/Spells.js rename to app/imports/api/creature/Spells.js diff --git a/app/imports/Model/Creature/TemporaryHitPoints.js b/app/imports/api/creature/TemporaryHitPoints.js similarity index 100% rename from app/imports/Model/Creature/TemporaryHitPoints.js rename to app/imports/api/creature/TemporaryHitPoints.js diff --git a/app/imports/model/creature/creatureComputation.js b/app/imports/api/creature/creatureComputation.js similarity index 100% rename from app/imports/model/creature/creatureComputation.js rename to app/imports/api/creature/creatureComputation.js diff --git a/app/imports/model/creature/creatureComputation.test.js b/app/imports/api/creature/creatureComputation.test.js similarity index 100% rename from app/imports/model/creature/creatureComputation.test.js rename to app/imports/api/creature/creatureComputation.test.js diff --git a/app/imports/Model/Creature/SubSchemas/Adjustment.js b/app/imports/api/creature/subSchemas/Adjustment.js similarity index 100% rename from app/imports/Model/Creature/SubSchemas/Adjustment.js rename to app/imports/api/creature/subSchemas/Adjustment.js diff --git a/app/imports/Model/Creature/SubSchemas/Attribute.js b/app/imports/api/creature/subSchemas/Attribute.js similarity index 100% rename from app/imports/Model/Creature/SubSchemas/Attribute.js rename to app/imports/api/creature/subSchemas/Attribute.js diff --git a/app/imports/Model/Creature/SubSchemas/DeathSaves.js b/app/imports/api/creature/subSchemas/DeathSaves.js similarity index 100% rename from app/imports/Model/Creature/SubSchemas/DeathSaves.js rename to app/imports/api/creature/subSchemas/DeathSaves.js diff --git a/app/imports/Model/Creature/SubSchemas/Skill.js b/app/imports/api/creature/subSchemas/Skill.js similarity index 100% rename from app/imports/Model/Creature/SubSchemas/Skill.js rename to app/imports/api/creature/subSchemas/Skill.js diff --git a/app/imports/Model/Inventory/Containers.js b/app/imports/api/inventory/Containers.js similarity index 100% rename from app/imports/Model/Inventory/Containers.js rename to app/imports/api/inventory/Containers.js diff --git a/app/imports/Model/Inventory/Items.js b/app/imports/api/inventory/Items.js similarity index 100% rename from app/imports/Model/Inventory/Items.js rename to app/imports/api/inventory/Items.js diff --git a/app/imports/Model/Library/Library.js b/app/imports/api/library/Library.js similarity index 100% rename from app/imports/Model/Library/Library.js rename to app/imports/api/library/Library.js diff --git a/app/imports/Model/Library/LibraryItems.js b/app/imports/api/library/LibraryItems.js similarity index 100% rename from app/imports/Model/Library/LibraryItems.js rename to app/imports/api/library/LibraryItems.js diff --git a/app/imports/Model/Library/LibrarySpells.js b/app/imports/api/library/LibrarySpells.js similarity index 100% rename from app/imports/Model/Library/LibrarySpells.js rename to app/imports/api/library/LibrarySpells.js diff --git a/app/imports/Model/Library/subSchemas/LibraryAttacks.js b/app/imports/api/library/subSchemas/LibraryAttacks.js similarity index 100% rename from app/imports/Model/Library/subSchemas/LibraryAttacks.js rename to app/imports/api/library/subSchemas/LibraryAttacks.js diff --git a/app/imports/Model/Library/subSchemas/LibraryEffects.js b/app/imports/api/library/subSchemas/LibraryEffects.js similarity index 100% rename from app/imports/Model/Library/subSchemas/LibraryEffects.js rename to app/imports/api/library/subSchemas/LibraryEffects.js diff --git a/app/imports/Model/Meta/Blacklist.js b/app/imports/api/meta/Blacklist.js similarity index 100% rename from app/imports/Model/Meta/Blacklist.js rename to app/imports/api/meta/Blacklist.js diff --git a/app/imports/Model/Meta/ChangeLogs.js b/app/imports/api/meta/ChangeLogs.js similarity index 100% rename from app/imports/Model/Meta/ChangeLogs.js rename to app/imports/api/meta/ChangeLogs.js diff --git a/app/imports/Model/Meta/Reports.js b/app/imports/api/meta/Reports.js similarity index 100% rename from app/imports/Model/Meta/Reports.js rename to app/imports/api/meta/Reports.js diff --git a/app/imports/Model/parenting.js b/app/imports/api/parenting.js similarity index 100% rename from app/imports/Model/parenting.js rename to app/imports/api/parenting.js diff --git a/app/imports/Model/Users/Users.js b/app/imports/api/users/Users.js similarity index 100% rename from app/imports/Model/Users/Users.js rename to app/imports/api/users/Users.js diff --git a/app/imports/model/campaign/Instance.js b/app/imports/model/campaign/Instance.js deleted file mode 100644 index c47e2dd3..00000000 --- a/app/imports/model/campaign/Instance.js +++ /dev/null @@ -1,9 +0,0 @@ -let Instances = new Mongo.Collection("instances"); - -let instanceSchema = new SimpleSchema({ - //an instance is a single flow of time all parties in an instance are in-sync time wise -}); - -Instances.attachSchema(instanceSchema); - -export default Instances; diff --git a/app/imports/model/campaign/Party.js b/app/imports/model/campaign/Party.js deleted file mode 100644 index 6c8c4ae8..00000000 --- a/app/imports/model/campaign/Party.js +++ /dev/null @@ -1,44 +0,0 @@ -let Parties = new Mongo.Collection("parties"); - -let partySchema = new SimpleSchema({ - name: { - type: String, - defaultValue: "New Party", - trim: false, - optional: true, - }, - characters: { - type: [String], - regEx: SimpleSchema.RegEx.Id, - index: 1, - defaultValue: [], - }, - owner: { - type: String, - regEx: SimpleSchema.RegEx.Id, - }, -}); - -Parties.attachSchema(Schemas.Party); - -Parties.allow({ - insert: function(userId, doc) { - return userId && doc.owner === userId; - }, - update: function(userId, doc, fields, modifier) { - return userId && doc.owner === userId; - }, - remove: function(userId, doc) { - return userId && doc.owner === userId; - }, - fetch: ["owner"], -}); - -Parties.deny({ - update: function(userId, docs, fields, modifier) { - // can't change owners - return _.contains(fields, "owner"); - } -}); - -export default Parties; diff --git a/app/imports/model/creature/Actions.js b/app/imports/model/creature/Actions.js deleted file mode 100644 index 1318bb76..00000000 --- a/app/imports/model/creature/Actions.js +++ /dev/null @@ -1,42 +0,0 @@ -let Actions = new Mongo.Collection("actions"); - -/* - * Actions are given to a character by items and features - */ -let actionSchema = new SimpleSchema({ - charId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - index: 1, - }, - name: { - type: String, - optional: true, - trim: false, - }, - description: { - type: String, - optional: true, - trim: false, - }, - type: { - type: String, - allowedValues: ["action, bonus, reaction, free"], - defaultValue: "action", - }, - //the immediate impact of doing this action (eg. -1 rages) - adjustments: { - type: [Schemas.Adjustment], - defaultValue: [], - }, -}); - -Actions.attachSchema(actionSchema); - -Actions.attachBehaviour("softRemovable"); -makeChild(Actions); - -Actions.allow(CHARACTER_SUBSCHEMA_ALLOW); -Actions.deny(CHARACTER_SUBSCHEMA_DENY); - -export default Actions diff --git a/app/imports/model/creature/Attacks.js b/app/imports/model/creature/Attacks.js deleted file mode 100644 index eeb8b2f6..00000000 --- a/app/imports/model/creature/Attacks.js +++ /dev/null @@ -1,89 +0,0 @@ -let Attacks = new Mongo.Collection("attacks"); - -/* - * Attacks are given to a character by items and features - */ -attackSchema = new SimpleSchema({ - charId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - index: 1, - }, - name: { - type: String, - defaultValue: "New Attack", - optional: true, - trim: false, - }, - details: { - type: String, - optional: true, - trim: false, - }, - attackBonus: { - type: String, - defaultValue: "strengthMod + proficiencyBonus", - optional: true, - trim: false, - }, - damage: { - type: String, - defaultValue: "1d8 + {strengthMod}", - optional: true, - trim: false, - }, - damageType: { - type: String, - allowedValues: [ - "bludgeoning", - "piercing", - "slashing", - "acid", - "cold", - "fire", - "force", - "lightning", - "necrotic", - "poison", - "psychic", - "radiant", - "thunder", - ], - defaultValue: "slashing", - }, - //the id of the feature, buff or item that created this effect - parent: { - type: Schemas.Parent - }, - color: { - type: String, - allowedValues: _.pluck(colorOptions, "key"), - defaultValue: "q", - }, - enabled: { - type: Boolean, - defaultValue: true, - }, -}); - -Attacks.attachSchema(attackSchema); - -Attacks.attachBehaviour("softRemovable"); -makeChild(Attacks, ["name", "enabled"]); //children of lots of things - -Attacks.after.insert(function (userId, attack) { - //Check to see if this attack's parent is a spell, if so, mirror prepared state to enabled - if (attack.parent.collection === "Spells") { - var parentSpell = Spells.findOne(attack.parent.id); - if (parentSpell.prepared === "unprepared") { - Attacks.update(attack._id, {$set: {enabled: false}}); - } else if (parentSpell.prepared === "prepared" || "always") { - Attacks.update(attack._id, {$set: {enabled: true}}); - } - } -}); - -Attacks.allow(CHARACTER_SUBSCHEMA_ALLOW); -Attacks.deny(CHARACTER_SUBSCHEMA_DENY); - -export default Attacks; diff --git a/app/imports/model/creature/Attributes.js b/app/imports/model/creature/Attributes.js deleted file mode 100644 index e7abdad0..00000000 --- a/app/imports/model/creature/Attributes.js +++ /dev/null @@ -1,87 +0,0 @@ -Attributes = new Mongo.Collection("attributes"); - -/* - * Attributes are whole numbered stats of a character - */ -Schemas.Attribute = new SimpleSchema({ - charId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - index: 1, - }, - // The nice-to-read name - name: { - type: String, - index: 1, - }, - // The technical, lowercase, single-word name used in formulae - variableName: { - type: String, - }, - // Attributes need to store their order to keep the sheet consistent - order: { - type: Number, - index: 1, - }, - type: { - type: String, - allowedValues: [ - "ability", //Strength, Dex, Con, etc. - "stat", // Speed, Armor Class - "hitDice", - "healthBar", // Hitpoints, Temporary Hitpoints - "resource", // Rages, sorcery points - "spellSlot", // Level 1, 2, 3... spell slots - "utility", // Aren't displayed, Jump height, Carry capacity - ], - index: 1, - }, - baseValue: { - type: Number, - decimal: true, - optional: true, - }, - value: { - type: Number, - decimal: true, - defaultValue: 0, - }, - mod: { - type: Number, - optional: true, - }, - adjustment: { - type: Number, - optional: true, - }, - // Can the value be decimal? - decimal: { - type: Boolean, - optional: true, - }, - parent: { - type: Schemas.Parent - }, - enabled: { - type: Boolean, - defaultValue: true, - }, - reset: { - type: String, - optional: true, - allowedValues: ["shortRest", "longRest"], - }, - // Some things are only reset by half on rest - resetMultiplier: { - type: Number, - optional: true, - }, -}); - -Attributes.attachSchema(Schemas.Attribute); - -Attributes.attachBehaviour("softRemovable"); -makeChild(Attributes, ["enabled"]); //children of lots of things - -Attributes.allow(CHARACTER_SUBSCHEMA_ALLOW); -Attributes.deny(CHARACTER_SUBSCHEMA_DENY); diff --git a/app/imports/model/creature/Buffs.js b/app/imports/model/creature/Buffs.js deleted file mode 100644 index e6e00710..00000000 --- a/app/imports/model/creature/Buffs.js +++ /dev/null @@ -1,67 +0,0 @@ -Buffs = new Mongo.Collection("buffs"); - -Schemas.Buff = new SimpleSchema({ - charId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - index: 1, - }, - name: { - type: String, - optional: true, - trim: false, - }, - description: { - type: String, - optional: true, - trim: false, - }, - enabled: { - type: Boolean, - defaultValue: true, - }, - type: { - type: String, - allowedValues: [ - "inate", //this should be "innate", but changing it could be problematic - "custom", - ], - }, - "lifeTime.total": { - type: Number, - defaultValue: 0, //0 is infinite - min: 0, - }, - "lifeTime.spent": { - type: Number, - defaultValue: 0, - min: 0, - }, - color: { - type: String, - allowedValues: _.pluck(colorOptions, "key"), - defaultValue: "q", - }, - appliedBy: { //the charId of whoever applied the buff - type: String, - regEx: SimpleSchema.RegEx.Id, - }, - appliedByDetails: {//the name and collection of the thing that applied the buff - type: Object, - optional: true, - }, - "appliedByDetails.name": { - type: String, - }, - "appliedByDetails.collection": { - type: String, - }, -}); - -Buffs.attachSchema(Schemas.Buff); - -Buffs.attachBehaviour("softRemovable"); -makeParent(Buffs, ["name", "enabled"]); //parents of effects, attacks, proficiencies - -Buffs.allow(CHARACTER_SUBSCHEMA_ALLOW); -Buffs.deny(CHARACTER_SUBSCHEMA_DENY); diff --git a/app/imports/model/creature/Classes.js b/app/imports/model/creature/Classes.js deleted file mode 100644 index 52e4df9e..00000000 --- a/app/imports/model/creature/Classes.js +++ /dev/null @@ -1,32 +0,0 @@ -Classes = new Mongo.Collection("classes"); - -Schemas.Class = new SimpleSchema({ - charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, - name: {type: String, optional: true, trim: false}, - level: {type: Number}, - createdAt: { - type: Date, - autoValue: function() { - if (this.isInsert) { - return new Date(); - } else if (this.isUpsert) { - return {$setOnInsert: new Date()}; - } else { - this.unset(); - } - }, - }, - color: { - type: String, - allowedValues: _.pluck(colorOptions, "key"), - defaultValue: "q", - }, -}); - -Classes.attachSchema(Schemas.Class); - -Classes.attachBehaviour("softRemovable"); -makeParent(Classes, "name"); //parents of effects and attacks - -Classes.allow(CHARACTER_SUBSCHEMA_ALLOW); -Classes.deny(CHARACTER_SUBSCHEMA_DENY); diff --git a/app/imports/model/creature/Conditions.js b/app/imports/model/creature/Conditions.js deleted file mode 100644 index ce894fe1..00000000 --- a/app/imports/model/creature/Conditions.js +++ /dev/null @@ -1,42 +0,0 @@ -Conditions = new Mongo.Collection("conditions"); - -Schemas.Conditions = new SimpleSchema({ - charId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - index: 1, - }, - name: { - type: String, - optional: true, - trim: false, - }, - description: { - type: String, - optional: true, - trim: false, - }, - "lifeTime.total": { - type: Number, - defaultValue: 0, //0 is infinite - min: 0, - }, - "lifeTime.spent": { - type: Number, - defaultValue: 0, - min: 0, - }, - color: { - type: String, - allowedValues: _.pluck(colorOptions, "key"), - defaultValue: "q", - }, -}); - -Conditions.attachSchema(Schemas.Conditions); - -Conditions.attachBehaviour("softRemovable"); -makeParent(Conditions, ["name"]); //parents of effects, attacks, proficiencies - -Conditions.allow(CHARACTER_SUBSCHEMA_ALLOW); -Conditions.deny(CHARACTER_SUBSCHEMA_DENY); diff --git a/app/imports/model/creature/Creatures.js b/app/imports/model/creature/Creatures.js deleted file mode 100644 index bd9e531e..00000000 --- a/app/imports/model/creature/Creatures.js +++ /dev/null @@ -1,168 +0,0 @@ -import { ValidatedMethod } from 'meteor/mdg:validated-method'; - -//set up the collection for creatures -Creatures = new Mongo.Collection("creatures"); - -Schemas.Creature = new SimpleSchema({ - //strings - name: {type: String, defaultValue: "", trim: false, optional: true}, - urlName: {type: String, defaultValue: "-", trim: false, optional: true}, - alignment: {type: String, defaultValue: "", trim: false, optional: true}, - gender: {type: String, defaultValue: "", trim: false, optional: true}, - race: {type: String, defaultValue: "", trim: false, optional: true}, - picture: {type: String, defaultValue: "", trim: true, optional: true}, - description: {type: String, defaultValue: "", trim: false, optional: true}, - personality: {type: String, defaultValue: "", trim: false, optional: true}, - ideals: {type: String, defaultValue: "", trim: false, optional: true}, - bonds: {type: String, defaultValue: "", trim: false, optional: true}, - flaws: {type: String, defaultValue: "", trim: false, optional: true}, - backstory: {type: String, defaultValue: "", trim: false, optional: true}, - - //mechanics - deathSave: {type: Schemas.DeathSave}, - xp: {type: Number, defaultValue: 0}, - weightCarried: {type: Number, defaultValue: 0}, - level: {type: Number, defaultValue: 0}, - type: {type: String, defaultValue: "pc", allowedValues: ["pc", "npc", "monster"]}, - - //permissions - party: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}, - owner: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, - readers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1}, - writers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1}, - color: { - type: String, - allowedValues: _.pluck(colorOptions, "key"), - defaultValue: "q", - }, - //TODO add per-creature settings - //how many experiences to load at a time in XP table - "settings.experiencesInc": {type: Number, defaultValue: 20}, - //slowed down by carrying too much? - "settings.useVariantEncumbrance": {type: Boolean, defaultValue: false}, - "settings.useStandardEncumbrance": {type: Boolean, defaultValue: true}, - //hide spellcasting - "settings.hideSpellcasting": {type: Boolean, defaultValue: false}, - //show to anyone with link - "settings.viewPermission": { - type: String, - defaultValue: "whitelist", - allowedValues: ["whitelist", "public"], - index: 1, - }, - "settings.swapStatAndModifier": {type: Boolean, defaultValue: false}, - "settings.exportFeatures": {type: Boolean, defaultValue: true}, - "settings.exportAttacks": {type: Boolean, defaultValue: true}, - "settings.exportDescription": {type: Boolean, defaultValue: true}, - "settings.newUserExperience": {type: Boolean, optional: true}, -}); - -Creatures.attachSchema(Schemas.Creature); - -Creatures.calculate = { - xpLevel: function(charId){ - var xp = Creatures.calculate.experience(charId); - for (var i = 0; i < 19; i++){ - if (xp < XP_TABLE[i]){ - return i; - } - } - if (xp > 355000) return 20; - return 0; - }, -}; - -const insertCharacter = new ValidatedMethod({ - - name: "Creatures.methods.insertCharacter", // DDP method name - - validate: new SimpleSchema({ - name: { - type: String, - optional: true, - }, - }).validator(), - - run({name}) { - if (!this.userId) { - throw new Meteor.Error("Creatures.methods.insert.denied", - "You need to be logged in to insert a creature"); - } - - // Create the creature document - Creatures.insert({name, owner: this.userId}); - this.unblock(); - //Add all the required attributes to it - if (Meteor.isServer){ - addDefaultStats(charId); - } - }, - -}); - -const addDefaultStats = function(charId){ - const defaultDocs = getDefaultCreatureDocs(charId); - Attributes.rawCollection().insert(defaultDocs.attributes, {ordered: false}); - Skills.rawCollection().insert(defaultDocs.skills, {ordered: false}); - DamageMultipliers.rawCollection().insert(defaultDocs.damageMultipliers, {ordered: false}); -}; - -//clean up all data related to that creature before removing it -if (Meteor.isServer){ - Creatures.after.remove(function(userId, creature) { - let charId = creature._id; - Actions .remove({charId}); - Attacks .remove({charId}); - Attributes .remove({charId}); - Buffs .remove({charId}); - Classes .remove({charId}); - CustomBuffs .remove({charId}); - DamageMultipliers.remove({charId}); - Effects .remove({charId}); - Experiences .remove({charId}); - Features .remove({charId}); - Notes .remove({charId}); - Proficiencies .remove({charId}); - Skills .remove({charId}); - SpellLists .remove({charId}); - Items .remove({charId}); - Containers .remove({charId}); - }); - Creatures.after.update(function(userId, doc, fieldNames, modifier, options) { - if (_.contains(fieldNames, "name")){ - var urlName = getSlug(doc.name, {maintainCase: true}) || "-"; - Creatures.update(doc._id, {$set: {urlName}}); - } - }); - Creatures.before.insert(function(userId, doc) { - doc.urlName = getSlug(doc.name, {maintainCase: true}) || "-"; - // The first creature a user creates should have the new user experience - if (!Creatures.find({owner: userId}).count()){ - doc.settings.newUserExperience = true; - } - }); -} - -Creatures.allow({ - insert: function(userId, doc) { - // the user must be logged in, and the document must be owned by the user - return (userId && doc.owner === userId); - }, - update: function(userId, doc, fields, modifier) { - // can only change documents you have write access to - return doc.owner === userId || - _.contains(doc.writers, userId); - }, - remove: function(userId, doc) { - // can only remove your own documents - return doc.owner === userId; - }, - fetch: ["owner", "writers"], -}); - -Creatures.deny({ - update: function(userId, docs, fields, modifier) { - // can't change owners - return _.contains(fields, "owner"); - } -}); diff --git a/app/imports/model/creature/CustomBuffs.js b/app/imports/model/creature/CustomBuffs.js deleted file mode 100644 index 7a766b01..00000000 --- a/app/imports/model/creature/CustomBuffs.js +++ /dev/null @@ -1,53 +0,0 @@ -CustomBuffs = new Mongo.Collection("customBuffs"); - -Schemas.CustomBuff = new SimpleSchema({ - charId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - index: 1, - }, - name: { - type: String, - optional: true, - trim: false, - }, - description: { - type: String, - optional: true, - trim: false, - }, - target: { - type: String, - allowedValues: [ - "self", - "others", - "both" - ], - defaultValue: "self", - }, - enabled: { - type: Boolean, - autoValue: function(){ - return false; - //enabled is ALWAYS false on these, so that its children are also not enabled, so that the buff templates have no effects. - }, - }, - "lifeTime.total": { - type: Number, - defaultValue: 0, //0 is infinite - min: 0, - }, - //the id of the feature, buff or item that creates this buff - parent: { - type: Schemas.Parent, - }, -}); - -CustomBuffs.attachSchema(Schemas.CustomBuff); - -CustomBuffs.attachBehaviour("softRemovable"); -makeParent(CustomBuffs, ["name", "enabled"]); //parents of effects, attacks, proficiencies. Since this represents a template, "enabled" is always false. -makeChild(CustomBuffs); //children of lots of things - -CustomBuffs.allow(CHARACTER_SUBSCHEMA_ALLOW); -CustomBuffs.deny(CHARACTER_SUBSCHEMA_DENY); diff --git a/app/imports/model/creature/DamageMultipliers.js b/app/imports/model/creature/DamageMultipliers.js deleted file mode 100644 index 553dc09d..00000000 --- a/app/imports/model/creature/DamageMultipliers.js +++ /dev/null @@ -1,40 +0,0 @@ -DamageMultipliers = new Mongo.Collection("damageMultipliers"); - -/* - * DamageMultipliers are whole numbered stats of a character - */ -Schemas.DamageMultiplier = new SimpleSchema({ - charId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - index: 1, - }, - // The nice-to-read name - name: { - type: String, - }, - // The technical, lowercase, single-word name used in formulae - variableName: { - type: String, - }, - value: { - type: Number, - decimal: true, - defaultValue: 1, - }, - parent: { - type: Schemas.Parent - }, - enabled: { - type: Boolean, - defaultValue: true, - }, -}); - -DamageMultipliers.attachSchema(Schemas.DamageMultiplier); - -DamageMultipliers.attachBehaviour("softRemovable"); -makeChild(DamageMultipliers, ["enabled"]); //children of lots of things - -DamageMultipliers.allow(CHARACTER_SUBSCHEMA_ALLOW); -DamageMultipliers.deny(CHARACTER_SUBSCHEMA_DENY); diff --git a/app/imports/model/creature/Effects.js b/app/imports/model/creature/Effects.js deleted file mode 100644 index 4cf9d913..00000000 --- a/app/imports/model/creature/Effects.js +++ /dev/null @@ -1,131 +0,0 @@ -Effects = new Mongo.Collection("effects"); - -/* - * Effects are reason-value attached to skills and abilities - * that modify their final value or presentation in some way - */ -Schemas.Effect = new SimpleSchema({ - charId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - index: 1, - }, - name: { - type: String, - optional: true, //TODO make necessary if there is no owner - trim: false, - }, - operation: { - type: String, - defaultValue: "add", - allowedValues: [ - "base", - "add", - "mul", - "min", - "max", - "advantage", - "disadvantage", - "passiveAdd", - "fail", - "conditional", - ], - }, - value: { - type: Number, - decimal: true, - optional: true, - }, - calculation: { - type: String, - optional: true, - trim: false, - }, - //the thing that created this effect - parent: { - type: Schemas.Parent - }, - //which stat the effect is applied to - stat: { - type: String, - optional: true, - }, - enabled: { - type: Boolean, - defaultValue: true, - }, -}); - -Effects.attachSchema(Schemas.Effect); - -Effects.attachBehaviour("softRemovable"); -makeChild(Effects, ["enabled"]); //children of lots of things - -Effects.allow(CHARACTER_SUBSCHEMA_ALLOW); -Effects.deny(CHARACTER_SUBSCHEMA_DENY); - -//give characters default character effects -Characters.after.insert(function(userId, char) { - if (Meteor.isServer) { - Effects.insert({ - charId: char._id, - name: "Constitution modifier for each level", - stat: "hitPoints", - operation: "add", - calculation: "level * constitutionMod", - parent: { - id: char._id, - collection: "Characters", - group: "Inate", - }, - }); - Effects.insert({ - charId: char._id, - name: "Proficiency bonus by level", - stat: "proficiencyBonus", - operation: "add", - calculation: "floor(level / 4 + 1.75)", - parent: { - id: char._id, - collection: "Characters", - group: "Inate", - }, - }); - Effects.insert({ - charId: char._id, - name: "Dexterity Armor Bonus", - stat: "armor", - operation: "add", - calculation: "dexterityArmor", - parent: { - id: char._id, - collection: "Characters", - group: "Inate", - }, - }); - Effects.insert({ - charId: char._id, - name: "Natural Armor", - stat: "armor", - operation: "base", - value: 10, - parent: { - id: char._id, - collection: "Characters", - group: "Inate", - }, - }); - Effects.insert({ - charId: char._id, - name: "Natural Carrying Capacity", - stat: "carryMultiplier", - operation: "base", - value: "1", - parent: { - id: char._id, - collection: "Characters", - group: "Inate", - }, - }); - } -}); diff --git a/app/imports/model/creature/Experience.js b/app/imports/model/creature/Experience.js deleted file mode 100644 index 4dc22b2a..00000000 --- a/app/imports/model/creature/Experience.js +++ /dev/null @@ -1,27 +0,0 @@ -Experiences = new Mongo.Collection("experience"); - -Schemas.Experience = new SimpleSchema({ - charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, - name: {type: String, optional: true, trim: false, defaultValue: "New Experience"}, - description: {type: String, optional: true, trim: false}, - value: {type: Number, defaultValue: 0}, - dateAdded: { - type: Date, - autoValue: function() { - if (this.isInsert) { - return new Date(); - } else if (this.isUpsert) { - return {$setOnInsert: new Date()}; - } else { - this.unset(); - } - }, - }, -}); - -Experiences.attachSchema(Schemas.Experience); - -Experiences.attachBehaviour("softRemovable"); - -Experiences.allow(CHARACTER_SUBSCHEMA_ALLOW); -Experiences.deny(CHARACTER_SUBSCHEMA_DENY); diff --git a/app/imports/model/creature/Features.js b/app/imports/model/creature/Features.js deleted file mode 100644 index 468d6fe3..00000000 --- a/app/imports/model/creature/Features.js +++ /dev/null @@ -1,115 +0,0 @@ -Features = new Mongo.Collection("features"); - -Schemas.Feature = new SimpleSchema({ - charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, - name: {type: String, optional: true, trim: false}, - description: {type: String, optional: true, trim: false}, - uses: {type: String, optional: true, trim: false}, - used: {type: Number, defaultValue: 0}, - reset: { - type: String, - allowedValues: ["manual", "longRest", "shortRest"], - defaultValue: "manual", - }, - enabled: {type: Boolean, defaultValue: true}, - alwaysEnabled:{type: Boolean, defaultValue: true}, - color: {type: String, - allowedValues: _.pluck(colorOptions, "key"), - defaultValue: "q", - }, -}); - -Features.attachSchema(Schemas.Feature); - -Features.helpers({ - usesLeft: function(){ - return evaluate(this.charId, this.uses) - this.used; - }, - usesValue: function(){ - return evaluate(this.charId, this.uses); - }, -}); - -Features.attachBehaviour("softRemovable"); -makeParent(Features, ["name", "enabled"]); //parents of effects and attacks - -Features.allow(CHARACTER_SUBSCHEMA_ALLOW); -Features.deny(CHARACTER_SUBSCHEMA_DENY); - -//give characters default feature of base ability scores of 10 -Characters.after.insert(function(userId, char) { - if (Meteor.isServer){ - var featureId = Features.insert({ - name: "Base Ability Scores", - charId: char._id, - enabled: true, - alwaysEnabled: true, - }); - Effects.insert({ - stat: "strength", - charId: char._id, - parent: { - id: featureId, - collection: "Features", - }, - operation: "base", - value: 10, - enabled: true, - }); - Effects.insert({ - stat: "dexterity", - charId: char._id, - parent: { - id: featureId, - collection: "Features", - }, - operation: "base", - value: 10, - enabled: true, - }); - Effects.insert({ - stat: "constitution", - charId: char._id, - parent: { - id: featureId, - collection: "Features", - }, - operation: "base", - value: 10, - enabled: true, - }); - Effects.insert({ - stat: "intelligence", - charId: char._id, - parent: { - id: featureId, - collection: "Features", - }, - operation: "base", - value: 10, - enabled: true, - }); - Effects.insert({ - stat: "wisdom", - charId: char._id, - parent: { - id: featureId, - collection: "Features", - }, - operation: "base", - value: 10, - enabled: true, - }); - Effects.insert({ - stat: "charisma", - charId: char._id, - parent: { - id: featureId, - collection: "Features", - }, - operation: "base", - value: 10, - enabled: true, - }); - } -}); diff --git a/app/imports/model/creature/Notes.js b/app/imports/model/creature/Notes.js deleted file mode 100644 index f1ce7aa4..00000000 --- a/app/imports/model/creature/Notes.js +++ /dev/null @@ -1,19 +0,0 @@ -Notes = new Mongo.Collection("notes"); - -Schemas.Note = new SimpleSchema({ - charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, - name: {type: String, optional: true, trim: false}, - description: {type: String, optional: true, trim: false}, - color: { - type: String, - allowedValues:_.pluck(colorOptions, "key"), - defaultValue: "q", - }, -}); - -Notes.attachSchema(Schemas.Note); - -Notes.attachBehaviour("softRemovable"); - -Notes.allow(CHARACTER_SUBSCHEMA_ALLOW); -Notes.deny(CHARACTER_SUBSCHEMA_DENY); diff --git a/app/imports/model/creature/Proficiencies.js b/app/imports/model/creature/Proficiencies.js deleted file mode 100644 index 22c6851f..00000000 --- a/app/imports/model/creature/Proficiencies.js +++ /dev/null @@ -1,37 +0,0 @@ -Proficiencies = new Mongo.Collection("proficiencies"); - -Schemas.Proficiency = new SimpleSchema({ - charId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - index: 1, - }, - name: { - type: String, - trim: false, - optional: true, - }, - value: { - type: Number, - allowedValues: [0, 0.5, 1, 2], - defaultValue: 1, - decimal: true, - }, - type: { - type: String, - allowedValues: ["skill", "save", "weapon", "armor", "tool", "language"], - defaultValue: "skill", - }, - enabled: { - type: Boolean, - defaultValue: true, - }, -}); - -Proficiencies.attachSchema(Schemas.Proficiency); - -Proficiencies.attachBehaviour("softRemovable"); -makeChild(Proficiencies, ["enabled"]); - -Proficiencies.allow(CHARACTER_SUBSCHEMA_ALLOW); -Proficiencies.deny(CHARACTER_SUBSCHEMA_DENY); diff --git a/app/imports/model/creature/Skills.js b/app/imports/model/creature/Skills.js deleted file mode 100644 index b4abb2d8..00000000 --- a/app/imports/model/creature/Skills.js +++ /dev/null @@ -1,83 +0,0 @@ -Skills = new Mongo.Collection("skills"); - -/* - * Skills are anything that results in a modifier to be added to a D20 - * Skills usually have an ability score modifier that they use as their basis - */ -Schemas.Skill = new SimpleSchema({ - charId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - index: 1, - }, - // The nice-to-read name - name: { - type: String, - }, - // The technical, lowercase, single-word name used in formulae - variableName: { - type: String, - }, - ability: { - type: String, - optional: true, - }, - type: { - type: String, - allowedValues: [ - "skill", - "save", - "stat", - "tool", - "weapon", - "language", - "utility", //not displayed anywhere - ], - }, - // Skills need to store their order to keep the sheet consistent - order: { - type: Number, - }, - value: { - type: Number, - decimal: true, - defaultValue: 0, - }, - advantage: { - type: Number, - optional: true, - allowedValues: [-1, 0, 1], - }, - passiveBonus: { - type: Number, - optional: true, - }, - proficiency: { - type: Number, - allowedValues: [0, 0.5, 1, 2], - defaultValue: 0, - }, - conditionalBenefits: { - type: Number, - optional: true, - }, - fail: { - type: Number, - optional: true, - }, - parent: { - type: Schemas.Parent - }, - enabled: { - type: Boolean, - defaultValue: true, - }, -}); - -Skills.attachSchema(Schemas.Skill); - -Skills.attachBehaviour("softRemovable"); -makeChild(Skills, ["enabled"]); //children of lots of things - -Skills.allow(CHARACTER_SUBSCHEMA_ALLOW); -Skills.deny(CHARACTER_SUBSCHEMA_DENY); diff --git a/app/imports/model/creature/SpellLists.js b/app/imports/model/creature/SpellLists.js deleted file mode 100644 index 982be871..00000000 --- a/app/imports/model/creature/SpellLists.js +++ /dev/null @@ -1,37 +0,0 @@ -SpellLists = new Mongo.Collection("spellLists"); - -Schemas.SpellLists = new SimpleSchema({ - charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, - name: {type: String, optional: true, trim: false}, - description: {type: String, optional: true, trim: false}, - saveDC: {type: String, optional: true, trim: false}, - attackBonus: {type: String, optional: true, trim: false}, - maxPrepared: {type: String, optional: true, trim: false}, - color: { - type: String, - allowedValues: _.pluck(colorOptions, "key"), - defaultValue: "q", - }, - "settings.showUnprepared": {type: Boolean, defaultValue: true}, -}); - -SpellLists.attachSchema(Schemas.SpellLists); - -SpellLists.helpers({ - numPrepared: function(){ - var num = 0; - Spells.find( - {charId: this.charId, listId: this._id, prepared: 1}, - {fields: {prepareCost: 1}} - ).forEach(function(spell){ - num += spell.prepareCost; - }); - return num; - } -}); - -SpellLists.attachBehaviour("softRemovable"); -makeParent(SpellLists); //parents of spells - -SpellLists.allow(CHARACTER_SUBSCHEMA_ALLOW); -SpellLists.deny(CHARACTER_SUBSCHEMA_DENY); diff --git a/app/imports/model/creature/Spells.js b/app/imports/model/creature/Spells.js deleted file mode 100644 index 2b5876b2..00000000 --- a/app/imports/model/creature/Spells.js +++ /dev/null @@ -1,252 +0,0 @@ -Spells = new Mongo.Collection("spells"); - -Schemas.Spell = new SimpleSchema({ - charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, - prepared: { - type: String, - defaultValue: "prepared", - allowedValues: ["prepared", "unprepared", "always"], - }, - name: { - type: String, - optional: true, - trim: false, - defaultValue: "New Spell", - }, - description: { - type: String, - optional: true, - trim: false, - }, - castingTime: { - type: String, - optional: true, - defaultValue: "action", - trim: false, - }, - range: { - type: String, - optional: true, - trim: false, - }, - duration: { - type: String, - optional: true, - trim: false, - defaultValue: "Instantaneous", - }, - "components.verbal": {type: Boolean, defaultValue: false}, - "components.somatic": {type: Boolean, defaultValue: false}, - "components.concentration": {type: Boolean, defaultValue: false}, - "components.material": {type: String, optional: true}, - ritual: { - type: Boolean, - defaultValue: false, - }, - level: { - type: Number, - defaultValue: 1, - }, - school: { - type: String, - defaultValue: "Abjuration", - allowedValues: magicSchools, - }, - color: { - type: String, - allowedValues: _.pluck(colorOptions, "key"), - defaultValue: "q", - }, -}); - -Spells.attachSchema(Schemas.Spell); - -Spells.attachBehaviour("softRemovable"); -makeChild(Spells); //children of spell lists -makeParent(Spells, ["name", "enabled"]); //parents of attacks - -Spells.after.update(function (userId, spell, fieldNames) { - //Update prepared state of spell and child attacks to be enabled or not - if (_.contains(fieldNames, "prepared")) { - var childAttacks = Attacks.find({"parent.id": spell._id}).fetch(); - if (spell.prepared === "unprepared") { - _.each(childAttacks, function(attack){ - Attacks.update(attack._id, {$set: {enabled: false}}); - }); - } else if (spell.prepared === "prepared" || "always") { - _.each(childAttacks, function(attack){ - Attacks.update(attack._id, {$set: {enabled: true}}); - }); - } - } -}); - -Spells.allow(CHARACTER_SUBSCHEMA_ALLOW); -Spells.deny(CHARACTER_SUBSCHEMA_DENY); - - - - -var checkMovePermission = function(spellId, parent, destinationOnly) { - var spell = Spells.findOne(spellId); - if (!spell) - throw new Meteor.Error("No such spell", - "An spell could not be found to move"); - //handle permissions - var permission; - - if (!destinationOnly) { //if we're not modifying the origin, only the destination - permission = Meteor.call("canWriteCharacter", spell.charId); - if (!permission){ - throw new Meteor.Error("Access denied", - "Not permitted to move spells from this character"); - } - } - if (parent.collection === "Characters"){ - permission = Meteor.call("canWriteCharacter", parent.id); - if (!permission){ - throw new Meteor.Error("Access denied", - "Not permitted to move spells to this character"); - } - } else { - var parentCollectionObject = global[parent.collection]; - var parentObject = null; - if (parentCollectionObject) - parentObject = parentCollectionObject.findOne( - parent.id, {fields: {_id: 1, charId: 1}} - ); - if (!parentObject) throw new Meteor.Error( - "Invalid parent", - "The destination parent " + parent.id + - " does not exist in the collection " + parent.collection - ); - if (parentObject.charId){ - permission = Meteor.call("canWriteCharacter", parentObject.charId); - if (!permission){ - throw new Meteor.Error("Access denied", - "Not permitted to move spells to this character"); - } - } - } -}; - -var moveSpell = function(spellId, targetCollection, targetId) { - var spell = Spells.findOne(spellId); - if (!spell) return; - targetCollection = targetCollection || spell.parent.collection; - targetId = targetId || spell.parent.id; - - if (Meteor.isServer) { - checkMovePermission(spellId, {collection: targetCollection, id: targetId}, false); - } - - if (targetCollection == "Characters") { //then we are copying the spell to a different character. - targetList = SpellLists.findOne({"charId": targetId}); - targetListId = targetList && targetList._id; - if (!targetListId) { - targetListId = SpellLists.insert({ //create a spell list if we don't already have one - name: "New SpellList", - charId: targetId, - saveDC: "8 + intelligenceMod + proficiencyBonus", - attackBonus: "intelligenceMod + proficiencyBonus", - }); - } - - Spells.update( - spellId, - {$set: { - charId: targetId, - "parent.collection": "SpellLists", - "parent.id": targetListId, - }} - ); - } - else { //we are moving the spell within the same character - //update the spell provided the update will actually change something - if ( - spell.parent.collection !== targetCollection || - spell.parent.id !== targetId - ){ - Spells.update( - spellId, - {$set: { - "parent.collection": targetCollection, - "parent.id": targetId, - }} - ); - } - } -}; - -var copySpell = function(spellId, targetCollection, targetId) { - var spell = Spells.findOne(spellId); - if (!spell) return; - targetCollection = targetCollection || spell.parent.collection; - targetId = targetId || spell.parent.id; - - if (Meteor.isServer) { - checkMovePermission(spellId, {collection: targetCollection, id: targetId}, true); //we're only reading from the source character - } - - - if (targetCollection == "Characters") { //then we are copying the spell to a different character. - targetList = SpellLists.findOne({"charId": targetId}); - targetListId = targetList && targetList._id; - if (!targetListId) { - targetListId = SpellLists.insert({ //create a spell list if we don't already have one - name: "New SpellList", - charId: targetId, - saveDC: "8 + intelligenceMod + proficiencyBonus", - attackBonus: "intelligenceMod + proficiencyBonus", - }); - } - - newSpell = _.clone(spell); - delete newSpell._id; - newSpellId = Spells.insert(newSpell); //add a new copy of the spell - Spells.update( - newSpellId, - {$set: { - charId: targetId, - "parent.collection": "SpellLists", - "parent.id": targetListId, - }} - ); - } - else { //else we are copying the spell within the same character - newSpell = _.clone(spell); - delete newSpell._id; - newSpellId = Spells.insert(newSpell); //add a new copy of the spell - Spells.update( - newSpellId, - {$set: { - "parent.collection": targetCollection, - "parent.id": targetId, - }} - ); - } -}; - - -Meteor.methods({ - moveSpellToList: function(spellId, spellListId) { - check(spellId, String); - check(spellListId, String); - moveSpell(spellId, "SpellLists", spellListId); - }, - copySpellToList: function(spellId, spellListId) { - check(spellId, String); - check(spellListId, String); - copySpell(spellId, "SpellLists", spellListId); - }, - moveSpellToCharacter: function(spellId, charId) { - check(spellId, String); - check(charId, String); - moveSpell(spellId, "Characters", charId); - }, - copySpellToCharacter: function(spellId, charId) { - check(spellId, String); - check(charId, String); - copySpell(spellId, "Characters", charId); - }, -}); \ No newline at end of file diff --git a/app/imports/model/creature/TemporaryHitPoints.js b/app/imports/model/creature/TemporaryHitPoints.js deleted file mode 100644 index 65b2a44b..00000000 --- a/app/imports/model/creature/TemporaryHitPoints.js +++ /dev/null @@ -1,41 +0,0 @@ -TemporaryHitPoints = new Mongo.Collection("temporaryHitPoints"); - -Schemas.TemporaryHitPoints = new SimpleSchema({ - charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, - name: {type: String, optional: true}, - maximum: {type: Number, defaultValue: 0, min: 0, max: 500}, - used: {type: Number, defaultValue: 0, min: 0, max: 500}, - deleteOnZero:{type: Boolean, defaultValue: false}, - dateAdded: { - type: Date, - autoValue: function() { - if (this.isInsert) { - return new Date(); - } else if (this.isUpsert) { - return {$setOnInsert: new Date()}; - } else { - this.unset(); - } - }, - }, -}); - -TemporaryHitPoints.attachSchema(Schemas.TemporaryHitPoints); - -TemporaryHitPoints.helpers({ - left: function(){ - return this.maximum - this.used; - } -}); - -//remove the temporary hit points when they hit zero -TemporaryHitPoints.after.update( - function(userId, thp, fieldNames, modifier, options){ - if (thp.used >= thp.maximum && thp.deleteOnZero){ - TemporaryHitPoints.remove(thp._id); - } - }, {fetchPrevious: false} -); - -TemporaryHitPoints.allow(CHARACTER_SUBSCHEMA_ALLOW); -TemporaryHitPoints.deny(CHARACTER_SUBSCHEMA_DENY); diff --git a/app/imports/model/creature/subschemas/Adjustment.js b/app/imports/model/creature/subschemas/Adjustment.js deleted file mode 100644 index 8025f089..00000000 --- a/app/imports/model/creature/subschemas/Adjustment.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Adjustments make instantaneous changes to the value of some attribute - * Damage, healing and resource cost/recovery are all adjustments - */ -Schemas.Adjustment = new SimpleSchema({ - //which stat the adjustment is applied to - stat: { - type: String, - optional: true, - }, - //the value added to the stat - value: { - type: Number, - decimal: true, - optional: true, - }, - calculation: { - type: String, - optional: true, - }, -}); diff --git a/app/imports/model/creature/subschemas/Attribute.js b/app/imports/model/creature/subschemas/Attribute.js deleted file mode 100644 index d93f9a67..00000000 --- a/app/imports/model/creature/subschemas/Attribute.js +++ /dev/null @@ -1,13 +0,0 @@ -Schemas.Attribute = new SimpleSchema({ - //the temporary shift of the attribute - //should be zero after reset - adjustment: { - type: Number, - defaultValue: 0, - }, - reset: { - type: String, - defaultValue: "longRest", - allowedValues: ["longRest", "shortRest"], - }, -}); diff --git a/app/imports/model/creature/subschemas/DeathSaves.js b/app/imports/model/creature/subschemas/DeathSaves.js deleted file mode 100644 index 7d587aa7..00000000 --- a/app/imports/model/creature/subschemas/DeathSaves.js +++ /dev/null @@ -1,22 +0,0 @@ -Schemas.DeathSave = new SimpleSchema({ - pass: { - type: Number, - min: 0, - max: 3, - defaultValue: 0, - }, - fail: { - type: Number, - min: 0, - max: 3, - defaultValue: 0, - }, - canDeathSave: { - type: Boolean, - defaultValue: true, - }, - stable: { - type: Boolean, - defaultValue: false, - }, -}); diff --git a/app/imports/model/creature/subschemas/Skill.js b/app/imports/model/creature/subschemas/Skill.js deleted file mode 100644 index 430d83d7..00000000 --- a/app/imports/model/creature/subschemas/Skill.js +++ /dev/null @@ -1,4 +0,0 @@ -Schemas.Skill = new SimpleSchema({ - //attribute name that this skill used as base mod for roll - ability: {type: String, defaultValue: ""}, -}); diff --git a/app/imports/model/inventory/Containers.js b/app/imports/model/inventory/Containers.js deleted file mode 100644 index 2318c930..00000000 --- a/app/imports/model/inventory/Containers.js +++ /dev/null @@ -1,56 +0,0 @@ -//set up the collection for containers -Containers = new Mongo.Collection("containers"); - -Schemas.Container = new SimpleSchema({ - name: {type: String, optional: true, trim: false}, - charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, - isCarried: {type: Boolean}, - weight: {type: Number, min: 0, defaultValue: 0, decimal: true}, - value: {type: Number, min: 0, defaultValue: 0, decimal: true}, - description:{type: String, optional: true, trim: false}, - color: { - type: String, - allowedValues: _.pluck(colorOptions, "key"), - defaultValue: "q", - }, -}); - -Containers.attachSchema(Schemas.Container); - -Containers.helpers({ - contentsValue: function(){ - var value = 0; - Items.find( - {"parent.id": this._id}, - {fields: {quantity: 1, value: 1}} - ).forEach(function(item){ - value += item.totalValue(); - }); - return value; - }, - totalValue: function(){ - return this.contentsValue() + this.value; - }, - contentsWeight: function(){ - var weight = 0; - Items.find( - {"parent.id": this._id}, - {fields: {quantity: 1, weight: 1}} - ).forEach(function(item){ - weight += item.totalWeight(); - }); - return weight; - }, - totalWeight: function(){ - return this.contentsWeight() + this.weight; - }, - moveToCharacter: function(characterId){ - if (this.charId === characterId) return; - Items.update(this._id, {$set: {charId: characterId}}); - }, -}); - -Containers.attachBehaviour("softRemovable"); -makeParent(Containers); //parents of items - -Containers.allow(CHARACTER_SUBSCHEMA_ALLOW); diff --git a/app/imports/model/inventory/Items.js b/app/imports/model/inventory/Items.js deleted file mode 100644 index 6c5c00e1..00000000 --- a/app/imports/model/inventory/Items.js +++ /dev/null @@ -1,268 +0,0 @@ -Items = new Mongo.Collection("items"); - -Schemas.Item = new SimpleSchema({ - name: {type: String, optional: true, trim: false, defaultValue: "New Item"}, - plural: {type: String, optional: true, trim: false}, - description:{type: String, optional: true, trim: false}, - charId: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, //id of owner - quantity: {type: Number, min: 0, defaultValue: 1}, - weight: {type: Number, min: 0, defaultValue: 0, decimal: true}, - value: {type: Number, min: 0, defaultValue: 0, decimal: true}, - enabled: {type: Boolean, defaultValue: false}, - requiresAttunement: {type: Boolean, defaultValue: false}, - "settings.showIncrement": {type: Boolean, defaultValue: false}, - color: { - type: String, - allowedValues: _.pluck(colorOptions, "key"), - defaultValue: "q", - }, -}); - -Items.attachSchema(Schemas.Item); - -var checkMovePermission = function(itemId, parent) { - var item = Items.findOne(itemId); - if (!item) - throw new Meteor.Error("No such item", - "An item could not be found to move"); - //handle permissions - var permission = Meteor.call("canWriteCharacter", item.charId); - if (!permission){ - throw new Meteor.Error("Access denied", - "Not permitted to move items from this character"); - } - if (parent.collection === "Characters"){ - permission = Meteor.call("canWriteCharacter", parent.id); - if (!permission){ - throw new Meteor.Error("Access denied", - "Not permitted to move items to this character"); - } - } else { - var parentCollectionObject = global[parent.collection]; - var parentObject = null; - if (parentCollectionObject) - parentObject = parentCollectionObject.findOne( - parent.id, {fields: {_id: 1, charId: 1}} - ); - if (!parentObject) throw new Meteor.Error( - "Invalid parent", - "The destination parent " + parent.id + - " does not exist in the collection " + parent.collection - ); - if (parentObject.charId){ - permission = Meteor.call("canWriteCharacter", parentObject.charId); - if (!permission){ - throw new Meteor.Error("Access denied", - "Not permitted to move items to this character"); - } - } - } -}; - -var moveItem = function(itemId, enable, parentCollection, parentId) { - var item = Items.findOne(itemId); - if (!item) return; - parentCollection = parentCollection || item.parent.collection; - parentId = parentId || item.parent.id; - - if (Meteor.isServer) { - checkMovePermission(itemId, {collection: parentCollection, id: parentId}); - } - - //update the item provided the update will actually change something - if ( - item.parent.collection !== parentCollection || - item.parent.id !== parentId || - item.enabled !== enable - ){ - Items.update( - itemId, - {$set: { - "parent.collection": parentCollection, - "parent.id": parentId, - enabled: enable, - }} - ); - } -}; - -Meteor.methods({ - moveItemToParent: function(itemId, parent) { - check(itemId, String); - check(parent, {collection: String, id: String}); - moveItem(itemId, false, parent.collection, parent.id); - }, - moveItemToCharacter: function(itemId, charId) { - check(itemId, String); - check(charId, String); - moveItem(itemId, false, "Characters", charId); - }, - moveItemToContainer: function(itemId, containerId) { - check(itemId, String); - check(containerId, String); - moveItem(itemId, false, "Containers", containerId); - }, - equipItem: function(itemId, charId){ - check(itemId, String); - check(charId, String); - moveItem(itemId, true, "Characters", charId); - }, - unequipItem: function(itemId, charId){ - check(itemId, String); - check(charId, String); - moveItem(itemId, false, "Characters", charId); - }, - splitItemToParent: function(itemId, moveQuantity, parent){ - check(itemId, String); - check(moveQuantity, Number); - check(parent, {id: String, collection: String}); - - //get the item - var item = Items.findOne(itemId); - if (!item) return; - - //don't bother moving nothing - if (moveQuantity <= 0 || item.quantity <= 0){ - return; - } - //ensure we are only moving up to the current stack size - if (item.quantity < moveQuantity){ - moveQuantity = this.quantity; - } - - if (Meteor.isServer) { - checkMovePermission(itemId, parent); - } - - //create a new item stack - var newStack = _.omit(EJSON.clone(item), "_id"); - newStack.parent = parent; - newStack.quantity = moveQuantity; - - //find out if we have an exact replica in the destination - var query = _.omit(newStack, ["parent", "quantity"]); - query["parent.collection"] = newStack.parent.collection; - query["parent.id"] = newStack.parent.id; - query._id = {$ne: itemId}; //make sure we don't join it to itself - var existingStack = Items.findOne(query); - if (existingStack){ - //increase the existing stack's size - Items.update( - existingStack._id, - {$inc: {quantity: moveQuantity}} - ); - } else { - //insert the new stack - Items.insert(newStack, function(err, id){ - if (err) throw err; - //copy the children also - Meteor.call("cloneChildren", item._id, {collection: "Items", id: id}); - }); - } - - //reduce the old stack's size - var oldQuantity = item.quantity - moveQuantity; - if (oldQuantity === 0){ - Items.remove(itemId); - } else { - Items.update(itemId, {$set: {quantity: oldQuantity}}); - } - }, -}); - -Items.helpers({ - totalValue: function(){ - return this.value * this.quantity; - }, - totalWeight: function(){ - return this.weight * this.quantity; - }, - pluralName: function(){ - if (this.plural && this.quantity !== 1){ - return this.plural; - } else { - return this.name; - } - }, -}); - -Items.before.update(function(userId, doc, fieldNames, modifier, options){ - if ( - modifier && modifier.$set && modifier.$set.enabled && //we are equipping this item - !( - modifier.$set["parent.collection"] === "Characters" && - modifier.$set["parent.id"] - ) //and we haven"t specified a character to equip to - ){ - //equip it to the current character - modifier.$set["parent.collection"] = "Characters"; - modifier.$set["parent.id"] = doc.charId; - } -}); - -Items.attachBehaviour("softRemovable"); -makeChild(Items); //children of containers -makeParent(Items, ["name", "enabled"]); //parents of effects and attacks - -Items.allow(CHARACTER_SUBSCHEMA_ALLOW); - -//give characters default items -Characters.after.insert(function(userId, char) { - if (Meteor.isServer){ - var containerId = Containers.insert({ - name: "Coin Pouch", - charId: char._id, - isCarried: true, - description: "A sturdy pouch for coins", - color: "d", - }); - Items.insert({ - name: "Gold piece", - plural: "Gold pieces", - charId: char._id, - quantity: 0, - weight: 0.02, - value: 1, - color: "n", - parent: { - id: containerId, - collection: "Containers", - }, - settings: { - showIncrement: true, - }, - }); - Items.insert({ - name: "Silver piece", - plural: "Silver pieces", - charId: char._id, - quantity: 0, - weight: 0.02, - value: 0.1, - color: "q", - parent: { - id: containerId, - collection: "Containers", - }, - settings: { - showIncrement: true, - }, - }); - Items.insert({ - name: "Copper piece", - plural: "Copper pieces", - charId: char._id, - quantity: 0, - weight: 0.02, - value: 0.01, - color: "s", - parent: { - id: containerId, - collection: "Containers", - }, - settings: { - showIncrement: true, - }, - }); - } -}); diff --git a/app/imports/model/library/Library.js b/app/imports/model/library/Library.js deleted file mode 100644 index 6688d0e5..00000000 --- a/app/imports/model/library/Library.js +++ /dev/null @@ -1,47 +0,0 @@ -Libraries = new Mongo.Collection("library"); - -Schemas.Library = new SimpleSchema({ - name: {type: String}, - owner: {type: String, regEx: SimpleSchema.RegEx.Id}, - readers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []}, - writers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []}, - public: {type: Boolean, defaultValue: false}, -}); - -Libraries.attachSchema(Schemas.Library); - -Libraries.allow({ - insert(userId, doc) { - return userId && doc.owner === userId; - }, - update(userId, doc, fields, modifier) { - return canEdit(userId, doc); - }, - remove(userId, doc) { - return canEdit(userId, doc); - }, - fetch: ["owner", "writers"], -}); - -Libraries.deny({ - // For now, only admins can manage libraries - insert(userId, doc){ - var user = Meteor.users.findOne(userId); - return !user || !_.contains(user.roles, "admin"); - }, - update(userId, doc, fields, modifier) { - // Can't change owners - return _.contains(fields, "owner") - }, - fetch: [], -}); - -const canEdit = function(userId, library){ - if (!userId || !library) return; - return library.owner === userId || _.contains(library.writers, userId); -}; - -Libraries.canEdit = function(userId, libraryId){ - const library = Libraries.findOne(libraryId); - return canEdit(userId, library); -}; diff --git a/app/imports/model/library/LibraryItems.js b/app/imports/model/library/LibraryItems.js deleted file mode 100644 index 569e1df9..00000000 --- a/app/imports/model/library/LibraryItems.js +++ /dev/null @@ -1,44 +0,0 @@ -LibraryItems = new Mongo.Collection("libraryItems"); - -Schemas.LibraryItems = new SimpleSchema({ - libraryName:{type: String, optional: true, trim: false}, - name: {type: String, defaultValue: "New Item", trim: false}, - plural: {type: String, optional: true, trim: false}, - description:{type: String, optional: true, trim: false}, - quantity: {type: Number, min: 0, defaultValue: 1}, - weight: {type: Number, min: 0, defaultValue: 0, decimal: true}, - value: {type: Number, min: 0, defaultValue: 0, decimal: true}, - requiresAttunement: {type: Boolean, defaultValue: false}, - - library: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, - - "settings.category": { - type: String, - optional: true, - allowedValues: [ - "adventuringGear", "armor", "weapons", "tools", - ], - }, - "settings.showIncrement": { - type: Boolean, - defaultValue: false, - }, - - effects: {type: [Schemas.LibraryEffects], defaultValue: []}, - attacks: {type: [Schemas.LibraryAttacks], defaultValue: []}, -}); - -LibraryItems.attachSchema(Schemas.LibraryItems); - -LibraryItems.allow({ - insert(userId, doc) { - return Libraries.canEdit(userId, doc.library); - }, - update(userId, doc, fields, modifier) { - return Libraries.canEdit(userId, doc.library); - }, - remove(userId, doc) { - return Libraries.canEdit(userId, doc.library); - }, - fetch: ["library"], -}); diff --git a/app/imports/model/library/LibrarySpells.js b/app/imports/model/library/LibrarySpells.js deleted file mode 100644 index bdbb67de..00000000 --- a/app/imports/model/library/LibrarySpells.js +++ /dev/null @@ -1,66 +0,0 @@ -LibrarySpells = new Mongo.Collection("librarySpells"); - -Schemas.LibrarySpells = new SimpleSchema({ - name: { - type: String, - trim: false, - defaultValue: "New Spell", - }, - description: { - type: String, - optional: true, - trim: false, - }, - castingTime: { - type: String, - optional: true, - defaultValue: "action", - trim: false, - }, - range: { - type: String, - optional: true, - trim: false, - }, - duration: { - type: String, - optional: true, - trim: false, - defaultValue: "Instantaneous", - }, - "components.verbal": {type: Boolean, defaultValue: false}, - "components.somatic": {type: Boolean, defaultValue: false}, - "components.concentration": {type: Boolean, defaultValue: false}, - "components.material": {type: String, optional: true}, - ritual: { - type: Boolean, - defaultValue: false, - }, - level: { - type: Number, - defaultValue: 1, - }, - school: { - type: String, - defaultValue: "Abjuration", - allowedValues: magicSchools, - }, - library: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, - effects: {type: [Schemas.LibraryEffects], defaultValue: []}, - attacks: {type: [Schemas.LibraryAttacks], defaultValue: []}, -}); - -LibrarySpells.attachSchema(Schemas.LibrarySpells); - -LibrarySpells.allow({ - insert(userId, doc) { - return Libraries.canEdit(userId, doc.library); - }, - update(userId, doc, fields, modifier) { - return Libraries.canEdit(userId, doc.library); - }, - remove(userId, doc) { - return Libraries.canEdit(userId, doc.library); - }, - fetch: ["library"], -}); diff --git a/app/imports/model/library/subSchemas/LibraryAttacks.js b/app/imports/model/library/subSchemas/LibraryAttacks.js deleted file mode 100644 index d606acd5..00000000 --- a/app/imports/model/library/subSchemas/LibraryAttacks.js +++ /dev/null @@ -1,41 +0,0 @@ -Schemas.LibraryAttacks = new SimpleSchema({ - name: { - type: String, - defaultValue: "New Attack", - trim: false, - }, - details: { - type: String, - optional: true, - trim: false, - }, - attackBonus: { - type: String, - optional: true, - trim: false, - }, - damage: { - type: String, - optional: true, - trim: false, - }, - damageType: { - type: String, - allowedValues: [ - "bludgeoning", - "piercing", - "slashing", - "acid", - "cold", - "fire", - "force", - "lightning", - "necrotic", - "poison", - "psychic", - "radiant", - "thunder", - ], - defaultValue: "slashing", - }, -}); diff --git a/app/imports/model/library/subSchemas/LibraryEffects.js b/app/imports/model/library/subSchemas/LibraryEffects.js deleted file mode 100644 index 4abcb1ef..00000000 --- a/app/imports/model/library/subSchemas/LibraryEffects.js +++ /dev/null @@ -1,40 +0,0 @@ -Schemas.LibraryEffects = new SimpleSchema({ - name: { - type: String, - optional: true, //TODO make necessary if there is no owner - trim: false, - }, - operation: { - type: String, - defaultValue: "add", - allowedValues: [ - "base", - "proficiency", - "add", - "mul", - "min", - "max", - "advantage", - "disadvantage", - "passiveAdd", - "fail", - "conditional", - ], - }, - // Effects either have a value OR a calculation - value: { - type: Number, - decimal: true, - optional: true, - }, - calculation: { - type: String, - optional: true, - trim: false, - }, - //which stat the effect is applied to - stat: { - type: String, - optional: true, - }, -}); diff --git a/app/imports/model/meta/Blacklist.js b/app/imports/model/meta/Blacklist.js deleted file mode 100644 index 221c64ec..00000000 --- a/app/imports/model/meta/Blacklist.js +++ /dev/null @@ -1,9 +0,0 @@ -Blacklist = new Mongo.Collection("blacklist"); - -Schemas.Blacklist = new SimpleSchema({ - userId: { - type: String, - }, -}); - -Blacklist.attachSchema(Schemas.Blacklist); diff --git a/app/imports/model/meta/ChangeLogs.js b/app/imports/model/meta/ChangeLogs.js deleted file mode 100644 index e56842a1..00000000 --- a/app/imports/model/meta/ChangeLogs.js +++ /dev/null @@ -1,27 +0,0 @@ -ChangeLogs = new Mongo.Collection("changeLogs"); - -Schemas.ChangeLog = new SimpleSchema({ - version: { - type: String, - }, - changes: { - type: [String], - }, -}); - -ChangeLogs.attachSchema(Schemas.ChangeLog); - -ChangeLogs.allow({ - insert: function(userId, doc) { - var user = Meteor.users.findOne(userId); - if (user) return _.contains(user.roles, "admin"); - }, - update: function(userId, doc, fields, modifier) { - var user = Meteor.users.findOne(userId); - if (user) return _.contains(user.roles, "admin"); - }, - remove: function(userId, doc) { - var user = Meteor.users.findOne(userId); - if (user) return _.contains(user.roles, "admin"); - }, -}); diff --git a/app/imports/model/meta/Reports.js b/app/imports/model/meta/Reports.js deleted file mode 100644 index 21ac4fe7..00000000 --- a/app/imports/model/meta/Reports.js +++ /dev/null @@ -1,79 +0,0 @@ -Reports = new Mongo.Collection("reports"); - -Schemas.Report = new SimpleSchema({ - owner: { - type: String, - regEx: SimpleSchema.RegEx.Id, - }, - title: { - type: String, - trim: false, - optional: true, - }, - description: { - type: String, - trim: false, - optional: true, - }, - type: { - type: String, - allowedValues: ["General Feedback", "Bug", "Suggested Change", "Feature Request"], - defaultValue: "General Feedback", - }, - //the immediate impact of doing this action (eg. -1 rages) - severity: { - type: Number, - defaultValue: 5, - min: 1, - max: 10, - }, - metaData: { - type: Object, - blackbox: true, - }, -}); - -Reports.attachSchema(Schemas.Report); - -Meteor.methods({ - insertReport: function(report) { - check(report, { - title: String, - description: String, - type: String, - severity: Number, - metaData: Object, - }); - report.owner = this.userId; - var id = Reports.insert(report); - var user = Meteor.users.findOne(this.userId); - var sender = user && - user.emails && - user.emails[0] && - user.emails[0].address || - user.services && - user.services.google && - user.services.google.email || - "reports@dicecloud.com"; - var bodyText = "Report ID: " + id + - "\nSeverity: " + report.severity + - "\nType: " + report.type + - "\n\n" + report.description; - Email.send({ - from: sender, - to: "stefan.zermatten@gmail.com", - subject: "DiceCloud feedback - " + report.title, - text: bodyText, - }); - }, - deleteReport: function(id) { - var user = Meteor.users.findOne(this.userId); - if (!_.contains(user.roles, "admin")){ - throw new Meteor.Error( - "not admin", - "The user must be an administrator to delete feedback" - ); - } - Reports.remove(id); - }, -}); diff --git a/app/imports/model/parenting.js b/app/imports/model/parenting.js deleted file mode 100644 index 21edb341..00000000 --- a/app/imports/model/parenting.js +++ /dev/null @@ -1,242 +0,0 @@ -import { ValidatedMethod } from 'meteor/mdg:validated-method'; - -let childSchema = new SimpleSchema({ - parent: {type: Object}, - "parent.collection": {type: String}, - "parent.id": {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, - "parent.group": {type: String, optional: true}, - "removedWith": { - optional: true, - type: String, - regEx: SimpleSchema.RegEx.Id, - }, -}); - -let joinWithDefaultKeys = function(keys){ - let defaultKeys = [ - "charId", - ]; - return _.union(keys, defaultKeys); -}; - -let limitModifierToKeys = function(modifier, keys){ - if (!modifier) return; - modifier = _.pick(modifier, ["$set", "$unset"]); - if (modifier.$set) modifier.$set = _.pick(modifier.$set, keys); - if (modifier.$unset) modifier.$unset = _.pick(modifier.$unset, keys); - if (_.isEmpty(modifier.$set)) delete modifier.$set; - if (_.isEmpty(modifier.$unset)) delete modifier.$unset; - return modifier; -}; - -let getParent = function(doc){ - if (!doc || !doc.parent) return; - let parentCol = Meteor.isClient ? - window[doc.parent.collection] : global[doc.parent.collection]; - if (parentCol) - return parentCol.findOne(doc.parent.id, {removed: true}); -}; - -let inheritParentProperties = function(doc, collection){ - let parent = getParent(doc); - if (!parent) throw new Meteor.Error( - "Parenting Error", - "Document's parent does not exist" - ); - let handMeDowns = _.pick(parent, collection.inheritedKeys); - if ( - _.contains(collection.inheritedKeys, "charId") && - doc.parent.collection === "Characters" - ){ - handMeDowns.charId = doc.parent.id; - } - if (_.isEmpty(handMeDowns)) return; - collection.update(doc._id, {$set: handMeDowns}); -}; - -let childCollections = []; - -let makeChild = function(collection, inheritedKeys){ - inheritedKeys = inheritedKeys || []; - if (inheritedKeys) { - collection.inheritedKeys = joinWithDefaultKeys(inheritedKeys); - } - collection.helpers({ - //returns the parent even if it's removed - getParent: function(){ - return getParent(this); - }, - getParentCollection: function(){ - return Meteor.isClient ? - window[this.parent.collection] : global[this.parent.collection]; - }, - }); - - //when created, inherit parent properties - collection.after.insert(function(userId, doc){ - inheritParentProperties(doc, collection); - }); - - collection.before.update(function(userId, doc, fieldNames, modifier, options){ - //if we are restoring this asset, unmark that it was removed with its parent, we no longer care - if (modifier && modifier.$unset && modifier.$unset.removed) { - modifier.$unset.removedWith = ""; - } - }); - - collection.after.update(function(userId, doc, fieldNames, modifier, options) { - if (modifier && modifier.$set && modifier.$set["parent.id"]){ - //when we change parents, inherit its properties - inheritParentProperties(doc, collection); - } - }); - - collection.softRemoveNode = collection.softRemoveNode || function(id){ - collection.softRemove(id); - }; - - collection.restoreNode = collection.restoreNode || function(id){ - collection.restore(id); - }; - - collection.attachSchema(childSchema); - - childCollections.push(collection); -}; - -let makeParent = function(collection, donatedKeys){ - donatedKeys = joinWithDefaultKeys(donatedKeys); - let collectionName = collection._collection.name; - //after changing, push the changes to all children - collection.after.update(function(userId, doc, fieldNames, modifier, options) { - modifier = limitModifierToKeys(modifier, donatedKeys); - doc = _.pick(doc, ["_id", "charId"]); - if (!modifier) return; - Meteor.call("updateChildren", doc, modifier, true); - }); - collection.softRemoveNode = function(id){ - Meteor.call("softRemoveNode", collectionName, id); - }; - - collection.restoreNode = function(id){ - Meteor.call("restoreNode", collectionName, id); - }; - - if (Meteor.isServer) collection.after.remove(function(userId, doc) { - _.each(childCollections, function(collection){ - collection.remove( - {"parent.id": doc._id} - ); - }); - }); -}; - -let checkPermission = function(userId, charId){ - let char = Characters.findOne(charId, {fields: {owner: 1, writers: 1}}); - if (!char) - throw new Meteor.Error("Access Denied, no charId", - "Character " + charId + " does not exist"); - if (!userId) - throw new Meteor.Error("Access Denied, no userId", - "No UserId set when trying to update character asset."); - if (char.owner !== userId && !_.contains(char.writers, userId)) - throw new Meteor.Error("Access Denied, not permitted", - "Not permitted to update assets of this character."); - return true; -}; - -let cascadeSoftRemove = function(id, removedWithId){ - _.each(childCollections, function(treeCollection){ - treeCollection.update( - {"parent.id": id}, - {$set: { - removed: true, - removedWith: removedWithId, - }}, - {multi: true} - ); - treeCollection.find({"parent.id": id}).forEach(function(doc){ - cascadeSoftRemove(doc._id, removedWithId); - }); - }); -}; - -let checkRemovePermission = function(collectionName, id, self){ - check(collectionName, String); - check(id, String); - let collection = Mongo.Collection.get(collectionName); - let node = collection.findOne(id); - let charId = node && node.charId; - checkPermission(self.userId, charId); -}; - -const softRemoveNode = new ValidatedMethod({ - name: "parenting.methods.softRemoveNode", - - validate: new SimpleSchema({ - collectionName: {type: String,}, - id: { - type: String, - regEx: SimpleSchema.RegEx.Id, - }, - }).validator(), // argument validation - - run({collectionName, id}){ - checkRemovePermission(collectionName, id, this); - let collection = Mongo.Collection.get(collectionName); - collection.softRemove(id); - cascadeSoftRemove(id, id); - }, -}); - -const restoreNode = new ValidatedMethod({ - run(collectionName, id){ - checkRemovePermission(collectionName, id, this); - let collection = Mongo.Collection.get(collectionName); - collection.restore(id); - _.each(childCollections, function(treeCollection){ - treeCollection.update( - {removedWith: id, removed: true}, - {$unset: {removed: true, removedWith: ""}}, - {multi: true} - ); - }); - }, -}); - -const updateChildren = new ValidatedMethod({ - run({parent, modifier, limitToInheritance}){ - check(parent, {_id: String, charId: String}); - check(modifier, Object); - checkPermission(this.userId, parent.charId); - let selector = {"parent.id": parent._id}; - _.each(childCollections, function(collection){ - let thisModifier; - if (limitToInheritance){ - thisModifier = limitModifierToKeys(modifier, collection.inheritedKeys); - } else { - thisModifier = _.clone(modifier); - } - if (_.isEmpty(thisModifier)) return; - collection.update(selector, thisModifier, {multi: true, removed: true}); - }); - }, -}); - -const cloneChildren = new ValidatedMethod({ - run({objectId, newParent}){ - check(objectId, String); - check(newParent, {id: String, collection: String}); - - _.each(childCollections, function(collection){ - let keys = collection.simpleSchema().objectKeys(); - collection.find({"parent.id": objectId}).forEach(function(doc){ - let newDoc = _.pick(doc, keys); - newDoc.parent = newParent; - collection.insert(newDoc); - }); - }); - } -}) - -export {makeChild, makeParent, softRemoveNode}; diff --git a/app/imports/model/users/Users.js b/app/imports/model/users/Users.js deleted file mode 100644 index a818962e..00000000 --- a/app/imports/model/users/Users.js +++ /dev/null @@ -1,110 +0,0 @@ -Schemas.UserProfile = new SimpleSchema({ - username: { - type: String, - optional: true, - }, -}); - -Schemas.User = new SimpleSchema({ - username: { - type: String, - optional: true, - }, - profile: { - type: Schemas.UserProfile, - optional: true, - }, - emails: { - type: Array, - optional: true, - }, - "emails.$": { - type: Object, - }, - "emails.$.address": { - type: String, - regEx: SimpleSchema.RegEx.Email, - }, - "emails.$.verified": { - type: Boolean, - }, - registered_emails: { - type: Array, - optional: true, - }, - "registered_emails.$": { - type: Object, - blackbox: true, - }, - createdAt: { - type: Date - }, - services: { - type: Object, - optional: true, - blackbox: true, - }, - roles: { - type: Object, - optional: true, - blackbox: true, - }, - roles: { - type: Array, - optional: true, - }, - "roles.$": { - type: String - }, - // In order to avoid an 'Exception in setInterval callback' from Meteor - heartbeat: { - type: Date, - optional: true, - }, - apiKey: { - type: String, - index: 1, - optional: true, - }, -}); - -Meteor.users.attachSchema(Schemas.User); - -Meteor.users.gnerateApiKey = new ValidatedMethod({ - name: "Users.methods.generateApiKey", - validate: null, - run(){ - if(Meteor.isClient) return; - var user = Meteor.users.findOne(this.userId); - if (!user) return; - if (user && user.apiKey) return; - var apiKey = Random.id(30); - Meteor.users.update(this.userId, {$set: {apiKey}}); - }, -}); - -Meteor.users.sendVerificationEmail = new ValidatedMethod({ - name: "Users.methods.sendVerificationEmail", - validate: new SimpleSchema({ - userId:{ - type: String, - optional: true, - }, - address: { - type: String, - }, - }).validator(), - run(userId, address){ - userId = this.userId || userId; - let user = Meteor.users.findOne(); - if (!user) { - throw new Meteor.Error("User not found", - "Can't send a validation email to a user that does not exist"); - } - if (!_.some(user.emails, email => email.address === address)) { - throw new Meteor.Error("Email address not found", - "The specified email address wasn't found on this user account"); - } - Accounts.sendVerificationEmail(this.userId, address); - } -});