diff --git a/app/imports/api/creature/creatures/methods/index.js b/app/imports/api/creature/creatures/methods/index.js index 2cd1b752..42e9c99e 100644 --- a/app/imports/api/creature/creatures/methods/index.js +++ b/app/imports/api/creature/creatures/methods/index.js @@ -1,5 +1,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/transferCreatureOwnership.js'; import '/imports/api/creature/creatures/methods/updateCreature.js'; diff --git a/app/imports/api/creature/creatures/methods/transferCreatureOwnership.js b/app/imports/api/creature/creatures/methods/transferCreatureOwnership.js deleted file mode 100644 index c7012d03..00000000 --- a/app/imports/api/creature/creatures/methods/transferCreatureOwnership.js +++ /dev/null @@ -1,55 +0,0 @@ -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/Creatures.js'; -import { assertOwnership } from '/imports/api/creature/creatures/creaturePermissions.js'; -import { getUserTier } from '/imports/api/users/patreon/tiers.js'; - -const transferCreatureOwnership = new ValidatedMethod({ - - name: 'creatures.methods.transferOwnership', - - validate: new SimpleSchema({ - creatureId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - }, - userId: { - type: String, - regEx: SimpleSchema.RegEx.Id, - }, - }).validator(), - - mixins: [RateLimiterMixin], - rateLimit: { - numRequests: 5, - timeInterval: 5000, - }, - - run({creatureId, userId}) { - assertOwnership(creatureId, this.userId); - - let tier = getUserTier(userId); - let currentCharacterCount = Creatures.find({ - owner: userId, - }, { - fields: {_id: 1}, - }).count(); - - if ( - tier.characterSlots !== -1 && - currentCharacterCount >= tier.characterSlots - ){ - throw new Meteor.Error('Creatures.methods.transferOwnership.denied', - 'The new owner is already at their character limit') - } - - Creatures.update(creatureId, { - $set: {owner: userId}, - }); - - return creatureId; - }, -}); - -export default transferCreatureOwnership; diff --git a/app/imports/api/sharing/sharing.js b/app/imports/api/sharing/sharing.js index 616dd8e7..d026d879 100644 --- a/app/imports/api/sharing/sharing.js +++ b/app/imports/api/sharing/sharing.js @@ -5,6 +5,7 @@ import getCollectionByName from '/imports/api/parenting/getCollectionByName.js'; import { RefSchema } from '/imports/api/parenting/ChildSchema.js'; import { ValidatedMethod } from 'meteor/mdg:validated-method'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; +import { getUserTier } from '/imports/api/users/patreon/tiers.js'; const setPublic = new ValidatedMethod({ name: 'sharing.setPublic', @@ -47,7 +48,7 @@ const updateUserSharePermissions = new ValidatedMethod({ run({docRef, userId, role}){ let doc = fetchDocByRef(docRef); if (role === 'none'){ - // only asser ownership if you aren't removing yourself + // only assert ownership if you aren't removing yourself if (this.userId !== userId){ assertOwnership(doc, this.userId); } @@ -74,4 +75,58 @@ const updateUserSharePermissions = new ValidatedMethod({ }, }); -export { setPublic, updateUserSharePermissions }; +const transferOwnership = new ValidatedMethod({ + name: 'sharing.transferOwnership', + validate: new SimpleSchema({ + docRef: RefSchema, + userId: { + type: String, + regEx: SimpleSchema.RegEx.Id, + }, + }).validator(), + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run({docRef, userId}){ + let doc = fetchDocByRef(docRef); + assertOwnership(doc, this.userId); + + let collection = getCollectionByName(docRef.collection); + + let tier = getUserTier(userId); + if (docRef.collection === 'creatures'){ + let currentCharacterCount = collection.find({ + owner: userId, + }, { + fields: {_id: 1}, + }).count(); + + if ( + tier.characterSlots !== -1 && + currentCharacterCount >= tier.characterSlots + ){ + throw new Meteor.Error('Sharing.methods.transferOwnership.denied', + 'The new owner is already at their character limit') + } + } else if (docRef.collection === 'libraries'){ + if (!tier.paidBenefits){ + throw new Meteor.Error('Sharing.methods.transferOwnership.denied', + 'The new owner\'s Patreon tier does not have access to library ownership'); + } + } + + // First remove current permissions for the user + collection.update(docRef.id, { + $pullAll: { writers: userId, readers: userId }, + }); + // Then make the user the owner and the current owner a writer + return collection.update(docRef.id, { + $set: {owner: userId}, + $addToSet: { writers: this.userId }, + }); + }, +}); + +export { setPublic, updateUserSharePermissions, transferOwnership }; diff --git a/app/imports/ui/dialogStack/DialogComponentIndex.js b/app/imports/ui/dialogStack/DialogComponentIndex.js index 7b5abecc..75a69d56 100644 --- a/app/imports/ui/dialogStack/DialogComponentIndex.js +++ b/app/imports/ui/dialogStack/DialogComponentIndex.js @@ -21,6 +21,7 @@ import ShareDialog from '/imports/ui/sharing/ShareDialog.vue'; import SlotDetailsDialog from '/imports/ui/creature/slots/SlotDetailsDialog.vue'; import SlotFillDialog from '/imports/ui/creature/slots/SlotFillDialog.vue'; import TierTooLowDialog from '/imports/ui/user/TierTooLowDialog.vue'; +import TransferOwnershipDialog from '/imports/ui/sharing/TransferOwnershipDialog.vue'; import UsernameDialog from '/imports/ui/user/UsernameDialog.vue'; export default { @@ -47,5 +48,6 @@ export default { SlotDetailsDialog, SlotFillDialog, TierTooLowDialog, + TransferOwnershipDialog, UsernameDialog, }; diff --git a/app/imports/ui/sharing/ShareDialog.vue b/app/imports/ui/sharing/ShareDialog.vue index ecedf571..728688e6 100644 --- a/app/imports/ui/sharing/ShareDialog.vue +++ b/app/imports/ui/sharing/ShareDialog.vue @@ -17,7 +17,7 @@ v-if="model.public && docRef.collection === 'libraries'" readonly label="Link" - :value="'https://beta.dicecloud.com' + this.$router.resolve({ + :value="'https://beta.dicecloud.com' + $router.resolve({ name: 'singleLibrary', params: { id: model._id }, }).href" @@ -56,6 +56,7 @@