Continued work on tabletops, hidden from main app and all methods disallowed for non-admins
This commit is contained in:
115
app/imports/api/tabletop/Messages.js
Normal file
115
app/imports/api/tabletop/Messages.js
Normal file
@@ -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 };
|
||||
@@ -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: [
|
||||
|
||||
@@ -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]
|
||||
})
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
lang="html"
|
||||
functional
|
||||
>
|
||||
<v-list-tile>
|
||||
<v-list-tile v-bind="$attrs">
|
||||
<v-list-tile-avatar :color="model.color || 'grey'">
|
||||
<img
|
||||
v-if="model.avatarPicture"
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
Add Characters
|
||||
</v-toolbar-title>
|
||||
<v-list>
|
||||
<p v-if="!creatures.length">
|
||||
There are no creatures to add or you have already added them all
|
||||
</p>
|
||||
<creature-list-tile
|
||||
v-for="creature in creatures"
|
||||
:key="creature._id"
|
||||
@@ -43,11 +46,11 @@ export default {
|
||||
},
|
||||
},
|
||||
data(){return {
|
||||
selected: new Set(this.startingSelection),
|
||||
selected: new Set(),
|
||||
}},
|
||||
meteor: {
|
||||
creatures(){
|
||||
return Creatures.find({});
|
||||
return Creatures.find({_id: {$nin: this.startingSelection}});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
</section>
|
||||
<section class="play-area">
|
||||
<tabletop-map />
|
||||
<tabletop-log />
|
||||
<tabletop-log :tabletop-id="model._id" />
|
||||
</section>
|
||||
<section class="action-row">
|
||||
<mini-character-sheet />
|
||||
|
||||
@@ -1,9 +1,53 @@
|
||||
<template lang="html">
|
||||
<div class="tabletop-log" />
|
||||
<div class="tabletop-log">
|
||||
<div class="messages layout column justify-end align-end">
|
||||
<div
|
||||
v-for="message in messages"
|
||||
:key="message._id"
|
||||
class="message"
|
||||
>
|
||||
{{ message.content }}
|
||||
</div>
|
||||
</div>
|
||||
<v-textarea
|
||||
v-model="messageContent"
|
||||
@keyup.enter.prevent="sendMessage"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Messages, { sendMessage } from '/imports/api/tabletop/Messages.js';
|
||||
export default {
|
||||
props: {
|
||||
tabletopId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data(){ return {
|
||||
messageContent: '',
|
||||
}},
|
||||
meteor: {
|
||||
messages() {
|
||||
return Messages.find({
|
||||
tabletopId: this.tabletopId,
|
||||
}, {
|
||||
sort: {
|
||||
timeStamp: 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sendMessage(){
|
||||
sendMessage.call({
|
||||
content: this.messageContent,
|
||||
tabletopId: this.tabletopId,
|
||||
});
|
||||
this.messageContent = '';
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user