From 6f7e742eb9c104f62f743d79de1d77588cfa59f3 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Wed, 20 Jul 2022 00:09:58 +0200 Subject: [PATCH] More of the sheet conforms to library allowances --- .../methods/changeAllowedLibraries.js | 90 ++++++ .../api/creature/creatures/methods/index.js | 1 + .../creatures/methods/insertCreature.js | 8 +- .../server/publications/searchLibraryNodes.js | 28 +- .../server/publications/slotFillers.js | 5 +- app/imports/ui/creature/CreatureForm.vue | 118 ++++++- .../character/CharacterCreationDialog.vue | 2 +- .../creature/character/CharacterSheetFab.vue | 1 + .../AddCreaturePropertyDialog.vue | 296 +++++++++--------- .../CreaturePropertyDialog.vue | 1 + 10 files changed, 377 insertions(+), 173 deletions(-) create mode 100644 app/imports/api/creature/creatures/methods/changeAllowedLibraries.js diff --git a/app/imports/api/creature/creatures/methods/changeAllowedLibraries.js b/app/imports/api/creature/creatures/methods/changeAllowedLibraries.js new file mode 100644 index 00000000..29057f55 --- /dev/null +++ b/app/imports/api/creature/creatures/methods/changeAllowedLibraries.js @@ -0,0 +1,90 @@ +import { ValidatedMethod } from 'meteor/mdg:validated-method'; +import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; +import Creatures from '/imports/api/creature/creatures/Creatures.js'; +import {assertEditPermission} from '/imports/api/sharing/sharingPermissions.js'; +import SimpleSchema from 'simpl-schema'; +import simpleSchemaMixin from '/imports/api/creature/mixins/simpleSchemaMixin.js'; + +const changeAllowedLibraries = new ValidatedMethod({ + name: 'creatures.changeAllowedLibraries', + mixins: [RateLimiterMixin, simpleSchemaMixin], + schema: new SimpleSchema({ + _id: { + type: String, + regEx: SimpleSchema.RegEx.Id, + }, + allowedLibraries: { + type: Array, + optional: true, + maxCount: 100, + }, + 'allowedLibraries.$': { + type: String, + regEx: SimpleSchema.RegEx.Id, + }, + allowedLibraryCollections: { + type: Array, + optional: true, + maxCount: 100, + }, + 'allowedLibraryCollections.$': { + type: String, + regEx: SimpleSchema.RegEx.Id, + }, + }), + rateLimit: { + numRequests: 10, + timeInterval: 5000, + }, + run({_id, allowedLibraries, allowedLibraryCollections}) { + let creature = Creatures.findOne(_id); + assertEditPermission(creature, this.userId); + let $set; + if (allowedLibraries) { + $set = { allowedLibraries } + } + if (allowedLibraryCollections) { + if (!$set) $set = {}; + $set.allowedLibraryCollections = allowedLibraryCollections; + } + if (!$set) return; + Creatures.update(_id, {$set}); + }, +}); + +const toggleAllUserLibraries = new ValidatedMethod({ + name: 'creatures.removeLibraryLimits', + mixins: [RateLimiterMixin, simpleSchemaMixin], + schema: new SimpleSchema({ + _id: { + type: String, + regEx: SimpleSchema.RegEx.Id, + }, + value: { + type: Boolean, + }, + }), + rateLimit: { + numRequests: 10, + timeInterval: 5000, + }, + run({_id, value}) { + if (value) { + Creatures.update(_id, { + $unset: { + allowedLibraryCollections: 1, + allowedLibraries: 1, + }, + }); + } else { + Creatures.update(_id, { + $set: { + allowedLibraryCollections: [], + allowedLibraries: [], + }, + }); + } + }, +}); + +export {changeAllowedLibraries, toggleAllUserLibraries}; diff --git a/app/imports/api/creature/creatures/methods/index.js b/app/imports/api/creature/creatures/methods/index.js index 42e9c99e..85aefc77 100644 --- a/app/imports/api/creature/creatures/methods/index.js +++ b/app/imports/api/creature/creatures/methods/index.js @@ -2,3 +2,4 @@ import '/imports/api/creature/creatures/methods/insertCreature.js'; import '/imports/api/creature/creatures/methods/removeCreature.js'; import '/imports/api/creature/creatures/methods/restCreature.js'; import '/imports/api/creature/creatures/methods/updateCreature.js'; +import '/imports/api/creature/creatures/methods/changeAllowedLibraries.js'; diff --git a/app/imports/api/creature/creatures/methods/insertCreature.js b/app/imports/api/creature/creatures/methods/insertCreature.js index 210f7b49..da72f6ed 100644 --- a/app/imports/api/creature/creatures/methods/insertCreature.js +++ b/app/imports/api/creature/creatures/methods/insertCreature.js @@ -7,7 +7,7 @@ import defaultCharacterProperties from '/imports/api/creature/creatures/defaultC import insertPropertyFromLibraryNode from '/imports/api/creature/creatureProperties/methods/insertPropertyFromLibraryNode.js'; import assertHasCharactersSlots from '/imports/api/creature/creatures/methods/assertHasCharacterSlots.js'; import getSlotFillFilter from '/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js'; -import getUserLibraryIds from '/imports/api/library/getUserLibraryIds.js'; +import getCreatureLibraryIds from '/imports/api/library/getCreatureLibraryIds.js'; import LibraryNodes from '/imports/api/library/LibraryNodes.js'; import { insertExperienceForCreature } from '/imports/api/creature/experience/Experiences.js'; import SimpleSchema from 'simpl-schema'; @@ -78,7 +78,7 @@ const insertCreature = new ValidatedMethod({ // If the user only has a single ruleset subscribed, use it by default if (Meteor.isServer) { - insertDefaultRuleset(baseId, userId, rulesetSlot); + insertDefaultRuleset(creatureId, baseId, userId, rulesetSlot); } return creatureId; @@ -86,8 +86,8 @@ const insertCreature = new ValidatedMethod({ }); // If the user only has a single ruleset subscribed, insert it by default -function insertDefaultRuleset(baseId, userId, slot) { - const libraryIds = getUserLibraryIds(userId); +function insertDefaultRuleset(creatureId, baseId, userId, slot) { + const libraryIds = getCreatureLibraryIds(creatureId, userId); const filter = getSlotFillFilter({ slot, libraryIds }); const fillCursor = LibraryNodes.find(filter, { fields: { _id: 1 } }); const numRulesets = fillCursor.count(); diff --git a/app/imports/server/publications/searchLibraryNodes.js b/app/imports/server/publications/searchLibraryNodes.js index ddbbf4ba..cedbc7a8 100644 --- a/app/imports/server/publications/searchLibraryNodes.js +++ b/app/imports/server/publications/searchLibraryNodes.js @@ -1,6 +1,8 @@ import { check } from 'meteor/check'; import Libraries from '/imports/api/library/Libraries.js'; import LibraryNodes from '/imports/api/library/LibraryNodes.js'; +import getCreatureLibraryIds from '/imports/api/library/getCreatureLibraryIds.js'; +import getUserLibraryIds from '/imports/api/library/getUserLibraryIds.js'; import { assertViewPermission } from '/imports/api/sharing/sharingPermissions.js'; Meteor.publish('selectedLibraryNodes', function(selectedNodeIds){ @@ -37,7 +39,7 @@ Meteor.publish('selectedLibraryNodes', function(selectedNodeIds){ })]; }); -Meteor.publish('searchLibraryNodes', function(){ +Meteor.publish('searchLibraryNodes', function(creatureId){ let self = this; this.autorun(function (){ let type = self.data('type'); @@ -49,23 +51,12 @@ Meteor.publish('searchLibraryNodes', function(){ } // Get all the ids of libraries the user can access - const user = Meteor.users.findOne(userId, { - fields: {subscribedLibraries: 1} - }); - if (!user) return []; - - const subs = user.subscribedLibraries || []; - let libraries = Libraries.find({ - $or: [ - {owner: this.userId}, - {writers: this.userId}, - {readers: this.userId}, - {_id: {$in: subs}}, - ] - }, { - fields: {_id: 1, name: 1}, - }); - let libraryIds = libraries.map(lib => lib._id); + let libraryIds; + if (creatureId) { + libraryIds = getCreatureLibraryIds(creatureId, userId) + } else { + libraryIds = getUserLibraryIds(userId) + } // Build a filter for nodes in those libraries that match the type let filter = { @@ -122,6 +113,7 @@ Meteor.publish('searchLibraryNodes', function(){ }); let cursor = LibraryNodes.find(filter, options); + const libraries = Libraries.find({ _id: { $in: libraryIds } }); Mongo.Collection._publishCursor(libraries, self, 'libraries'); diff --git a/app/imports/server/publications/slotFillers.js b/app/imports/server/publications/slotFillers.js index 95a77c6c..ab6e781d 100644 --- a/app/imports/server/publications/slotFillers.js +++ b/app/imports/server/publications/slotFillers.js @@ -3,7 +3,7 @@ import Libraries from '/imports/api/library/Libraries.js'; import LibraryNodes from '/imports/api/library/LibraryNodes.js'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import getSlotFillFilter from '/imports/api/creature/creatureProperties/methods/getSlotFillFilter.js' -import getUserLibraryIds from '/imports/api/library/getUserLibraryIds.js'; +import getCreatureLibraryIds from '/imports/api/library/getCreatureLibraryIds.js'; import { LIBRARY_NODE_TREE_FIELDS } from '/imports/server/publications/library.js'; const FIELDS = { @@ -28,7 +28,8 @@ Meteor.publish('slotFillers', function(slotId, searchTerm){ } // Get all the ids of libraries the user can access - const libraryIds = getUserLibraryIds(userId); + const creatureId = slot.ancestors[0].id; + const libraryIds = getCreatureLibraryIds(creatureId, userId); const libraries = Libraries.find({ $or: [ { owner: userId }, diff --git a/app/imports/ui/creature/CreatureForm.vue b/app/imports/ui/creature/CreatureForm.vue index f5506393..b9103ff8 100644 --- a/app/imports/ui/creature/CreatureForm.vue +++ b/app/imports/ui/creature/CreatureForm.vue @@ -33,7 +33,7 @@ @change="(value, ack) => $emit('change', {path: ['avatarPicture'], value, ack})" /> - + --> + + + + +

+ {{ libraryWriteError }} +

+
diff --git a/app/imports/ui/creature/character/CharacterCreationDialog.vue b/app/imports/ui/creature/character/CharacterCreationDialog.vue index 69e33330..568ae394 100644 --- a/app/imports/ui/creature/character/CharacterCreationDialog.vue +++ b/app/imports/ui/creature/character/CharacterCreationDialog.vue @@ -195,7 +195,7 @@ export default { } else { this.$store.commit( 'setTabForCharacterSheet', - {id: creatureId, tab: 4} + {id: creatureId, tab: 5} ); this.$emit('pop', creatureId); defer(() => { diff --git a/app/imports/ui/creature/character/CharacterSheetFab.vue b/app/imports/ui/creature/character/CharacterSheetFab.vue index 4fee5c36..49590d75 100644 --- a/app/imports/ui/creature/character/CharacterSheetFab.vue +++ b/app/imports/ui/creature/character/CharacterSheetFab.vue @@ -170,6 +170,7 @@ data: { parentDoc: forcedType ? undefined : parent, forcedType, + creatureId: this.creatureId, }, callback(result){ if (!result){ diff --git a/app/imports/ui/creature/creatureProperties/AddCreaturePropertyDialog.vue b/app/imports/ui/creature/creatureProperties/AddCreaturePropertyDialog.vue index 133d713b..944c7642 100644 --- a/app/imports/ui/creature/creatureProperties/AddCreaturePropertyDialog.vue +++ b/app/imports/ui/creature/creatureProperties/AddCreaturePropertyDialog.vue @@ -171,160 +171,166 @@