diff --git a/app/imports/api/creature/creatureComputation.js b/app/imports/api/creature/creatureComputation.js index a6b52045..4d0f3978 100644 --- a/app/imports/api/creature/creatureComputation.js +++ b/app/imports/api/creature/creatureComputation.js @@ -3,6 +3,7 @@ import { ValidatedMethod } from 'meteor/mdg:validated-method'; import SimpleSchema from 'simpl-schema'; +import { canEditCreature } from '/imports/api/creature/creaturePermission.js'; import Creatures from "/imports/api/creature/Creatures.js"; import Attributes from "/imports/api/creature/properties/Attributes.js"; import Skills from "/imports/api/creature/properties/Skills.js"; @@ -10,9 +11,6 @@ import Effects from "/imports/api/creature/properties/Effects.js"; import DamageMultipliers from "/imports/api/creature/properties/DamageMultipliers.js"; import Classes from "/imports/api/creature/properties/Classes.js"; -// TODO, just checks that a charId is given -const canEditCreature = charId => !!charId; - export const recomputeCreature = new ValidatedMethod({ name: "Creatures.methods.recomputeCreature", @@ -40,8 +38,8 @@ export const recomputeCreature = new ValidatedMethod({ * distilling down effects and proficiencies into the final stats that make up * a creature. * - * Essentially this is a backtracking algorithm that computes stats' - * dependencies before computing stats themselves, while detecting + * Essentially this is a depth first tree traversal algorithm that computes + * stats' dependencies before computing stats themselves, while detecting * dependency loops. * * At the moment it makes no effort to limit recomputation to just what was diff --git a/app/imports/api/creature/creaturePermission.js b/app/imports/api/creature/creaturePermission.js new file mode 100644 index 00000000..c090d973 --- /dev/null +++ b/app/imports/api/creature/creaturePermission.js @@ -0,0 +1,53 @@ +import Creatures from '/imports/api/creature/Creatures.js'; +import { _ } from 'meteor/underscore'; + +export function canEditCreature(charId, userId) { + if (!charId || typeof charId !== 'string'){ + throw new Meteor.Error("Edit permission denied", + "No creature ID given for edit permission check"); + } + if (!userId || typeof userId !== 'string'){ + throw new Meteor.Error("Edit permission denied", + "No user ID given for edit permission check"); + } + let creature = Creatures.findOne(charId, {fields: {owner: 1, writers: 1}}); + if (!creature){ + throw new Meteor.Error("Edit permission denied", + `No creature exists with the given id: ${charId}`); + } + if (creature.owner === userId || _.contains(creature.writers, userId)){ + return true; + } else { + throw new Meteor.Error("Edit permission denied", + `You do not have permission to edit this character`); + } +}; + +export function canViewCreature(charId, userId) { + if (!charId || typeof charId !== 'string'){ + throw new Meteor.Error("View permission denied", + "No creature ID given for view permission check"); + } + if (!userId || typeof userId !== 'string'){ + throw new Meteor.Error("View permission denied", + "No user ID given for view permission check"); + } + let creature = Creatures.findOne(charId, { + fields: {owner: 1, writers: 1, readers: 1, settings: 1} + }); + if (!creature){ + throw new Meteor.Error("View permission denied", + `No creature exists with the given id: ${charId}`); + } + if ( + creature.owner === userId || + settings.viewPermission === 'public' || + _.contains(creature.readers, userId) || + _.contains(creature.writers, userId) + ){ + return true; + } else { + throw new Meteor.Error("View permission denied", + `You do not have permission to view this character`); + } +};