From c7985af83b586feed4a340abe5c2c6e683e76b31 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Sun, 26 Jul 2020 19:45:07 +0200 Subject: [PATCH] Continued work on tabletops, hidden from main app and all methods disallowed for non-admins --- app/imports/api/tabletop/Messages.js | 115 ++++++++++++++++++ app/imports/api/tabletop/Tabletops.js | 14 ++- app/imports/server/publications/tabletops.js | 11 +- app/imports/ui/creature/CreatureListTile.vue | 2 +- .../ui/tabletop/SelectCreaturesDialog.vue | 7 +- app/imports/ui/tabletop/TabletopComponent.vue | 2 +- app/imports/ui/tabletop/TabletopLog.vue | 46 ++++++- 7 files changed, 190 insertions(+), 7 deletions(-) create mode 100644 app/imports/api/tabletop/Messages.js diff --git a/app/imports/api/tabletop/Messages.js b/app/imports/api/tabletop/Messages.js new file mode 100644 index 00000000..badf61e6 --- /dev/null +++ b/app/imports/api/tabletop/Messages.js @@ -0,0 +1,115 @@ +import SimpleSchema from 'simpl-schema'; +import { ValidatedMethod } from 'meteor/mdg:validated-method'; +import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; +import Creatures from '/imports/api/creature/Creatures.js'; +import Tabletops, { assertUserInTabletop } from '/imports/api/tabletop/Tabletops.js'; + +let Messages = new Mongo.Collection('messages'); + +let MessagesSchema = new SimpleSchema({ + tabletopId: { + type: String, + regEx: SimpleSchema.RegEx.id, + }, + content: { + type: String, + max: 1000, + }, + timestamp: { + type: Date, + index: 1, + }, + userId: { + type: String, + regEx: SimpleSchema.RegEx.id, + }, + username: { + type: String, + }, +}); + +Messages.attachSchema(MessagesSchema); + +const sendMessage = new ValidatedMethod({ + + name: 'messages.send', + + validate: new SimpleSchema({ + content: { + type: String, + max: 1000, + }, + tabletopId: { + type: String, + regEx: SimpleSchema.RegEx.id, + }, + }).validator(), + + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 10, + timeInterval: 5000, + }, + + run({content, tabletopId}) { + let user = Meteor.user(); + if (!user) { + throw new Meteor.Error('messages.send.denied', + 'You need to be logged in to send a message'); + } + assertUserInTabletop(tabletopId, this.userId); + + return Messages.insert({ + content, + tabletopId, + timestamp: new Date(), + userId: user._id, + username: user.username, + }); + }, + +}); + +const removeMessages = new ValidatedMethod({ + + name: 'messages.remove', + + validate: new SimpleSchema({ + messageId: { + type: String, + regEx: SimpleSchema.RegEx.id, + }, + }).validator(), + + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + + run({messageId, tabletopId}) { + if (!this.userId) { + throw new Meteor.Error('messages.remove.denied', + 'You need to be logged in to remove a tabletop'); + } + let message = Messages.findOne(messageId); + let tabletop = Tabletops.findOne(message.tabletopId); + if (this.userId !== message.userId && this.userId !== tabletop.gameMaster){ + throw new Meteor.Error('messages.remove.denied', + 'You don\'t have permission to remove this message'); + } + let removed = Messages.remove({ + _id: messageId, + }); + Creatures.update({ + tabletop: tabletopId, + }, { + $unset: {tabletop: 1}, + }); + return removed; + }, + +}); + +export default Messages; +export { sendMessage, removeMessages }; diff --git a/app/imports/api/tabletop/Tabletops.js b/app/imports/api/tabletop/Tabletops.js index 3e108494..29c3f04d 100644 --- a/app/imports/api/tabletop/Tabletops.js +++ b/app/imports/api/tabletop/Tabletops.js @@ -64,7 +64,7 @@ function assertUserIsTabletopOwner(tabletopId, userId){ } } -function assertUserInTabletop(tabletopId, userId){ +export function assertUserInTabletop(tabletopId, userId){ let tabletop = Tabletops.findOne(tabletopId); if (!tabletop){ throw new Meteor.Error('Tabletop does not exist', @@ -76,6 +76,13 @@ function assertUserInTabletop(tabletopId, userId){ } } +function assertUserIsAdmin(userId){ + if (!Meteor.users.isAdmin(userId)){ + throw new Meteor.Error('Admin only', + 'This is restricted to admins for now'); + } +} + const insertTabletop = new ValidatedMethod({ name: 'tabletops.insert', @@ -94,6 +101,7 @@ const insertTabletop = new ValidatedMethod({ 'You need to be logged in to insert a tabletop'); } assertUserHasPaidBenefits(this.userId); + assertUserIsAdmin(this.userId); return Tabletops.insert({ gameMaster: this.userId, @@ -126,6 +134,8 @@ const removeTabletop = new ValidatedMethod({ } assertUserHasPaidBenefits(this.userId); assertUserIsTabletopOwner(tabletopId, this.userId); + assertUserIsAdmin(this.userId); + let removed = Tabletops.remove({ _id: tabletopId, }); @@ -170,6 +180,8 @@ const addCreaturesToTabletop = new ValidatedMethod({ } assertUserHasPaidBenefits(this.userId); assertUserInTabletop(tabletopId, this.userId); + assertUserIsAdmin(this.userId); + Creatures.update({ _id: {$in: creatureIds}, $or: [ diff --git a/app/imports/server/publications/tabletops.js b/app/imports/server/publications/tabletops.js index 7aa30abb..3f2ac41d 100644 --- a/app/imports/server/publications/tabletops.js +++ b/app/imports/server/publications/tabletops.js @@ -1,5 +1,6 @@ import Tabletops from '/imports/api/tabletop/Tabletops.js'; import Creatures from '/imports/api/creature/Creatures.js'; +import Messages from '/imports/api/tabletop/Messages.js'; Meteor.publish('tabletops', function(){ var userId = this.userId; @@ -46,6 +47,14 @@ Meteor.publish('tabletop', function(tabletopId){ initiativeRoll: 1, }, }); - return [ tabletopCursor, creatureSummaries] + let recentMessages = Messages.find({ + tabletopId, + }, { + sort: { + timeStamp: -1, + }, + limit: 100, + }); + return [ tabletopCursor, creatureSummaries, recentMessages] }) }); diff --git a/app/imports/ui/creature/CreatureListTile.vue b/app/imports/ui/creature/CreatureListTile.vue index c6402838..9ae0d322 100644 --- a/app/imports/ui/creature/CreatureListTile.vue +++ b/app/imports/ui/creature/CreatureListTile.vue @@ -2,7 +2,7 @@ lang="html" functional > - + +

+ There are no creatures to add or you have already added them all +

- +
diff --git a/app/imports/ui/tabletop/TabletopLog.vue b/app/imports/ui/tabletop/TabletopLog.vue index c93fabb6..bd0eaa55 100644 --- a/app/imports/ui/tabletop/TabletopLog.vue +++ b/app/imports/ui/tabletop/TabletopLog.vue @@ -1,9 +1,53 @@