Hunted the last of the \t's to extinction
This commit is contained in:
@@ -4,33 +4,33 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
|
||||
let CreatureFolders = new Mongo.Collection('creatureFolders');
|
||||
|
||||
let creatureFolderSchema = new SimpleSchema({
|
||||
name: {
|
||||
type: String,
|
||||
trim: false,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
creatures: {
|
||||
type: Array,
|
||||
defaultValue: [],
|
||||
},
|
||||
'creatures.$': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
owner: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
index: 1,
|
||||
},
|
||||
archived: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
order: {
|
||||
type: Number,
|
||||
defaultValue: 0,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
trim: false,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
creatures: {
|
||||
type: Array,
|
||||
defaultValue: [],
|
||||
},
|
||||
'creatures.$': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
owner: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
index: 1,
|
||||
},
|
||||
archived: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
order: {
|
||||
type: Number,
|
||||
defaultValue: 0,
|
||||
},
|
||||
});
|
||||
|
||||
CreatureFolders.attachSchema(creatureFolderSchema);
|
||||
|
||||
@@ -2,49 +2,49 @@ import SimpleSchema from 'simpl-schema';
|
||||
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
|
||||
|
||||
let ExperienceSchema = new SimpleSchema({
|
||||
title: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
// Potentially long description of the event
|
||||
description: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.description,
|
||||
},
|
||||
// The real-world date that it occured
|
||||
date: {
|
||||
type: Date,
|
||||
autoValue: function () {
|
||||
// If the date isn't set, set it to now
|
||||
if (!this.isSet) {
|
||||
return new Date();
|
||||
}
|
||||
},
|
||||
},
|
||||
// The date in-world of this event
|
||||
worldDate: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
// Tags to better find this entry later
|
||||
tags: {
|
||||
type: Array,
|
||||
defaultValue: [],
|
||||
maxCount: STORAGE_LIMITS.tagCount,
|
||||
},
|
||||
'tags.$': {
|
||||
type: String,
|
||||
max: STORAGE_LIMITS.tagLength,
|
||||
},
|
||||
// ID of the journal this entry belongs to
|
||||
journalId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
index: 1,
|
||||
}
|
||||
title: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
// Potentially long description of the event
|
||||
description: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.description,
|
||||
},
|
||||
// The real-world date that it occured
|
||||
date: {
|
||||
type: Date,
|
||||
autoValue: function () {
|
||||
// If the date isn't set, set it to now
|
||||
if (!this.isSet) {
|
||||
return new Date();
|
||||
}
|
||||
},
|
||||
},
|
||||
// The date in-world of this event
|
||||
worldDate: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
// Tags to better find this entry later
|
||||
tags: {
|
||||
type: Array,
|
||||
defaultValue: [],
|
||||
maxCount: STORAGE_LIMITS.tagCount,
|
||||
},
|
||||
'tags.$': {
|
||||
type: String,
|
||||
max: STORAGE_LIMITS.tagLength,
|
||||
},
|
||||
// ID of the journal this entry belongs to
|
||||
journalId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
index: 1,
|
||||
}
|
||||
});
|
||||
|
||||
export { ExperienceSchema };
|
||||
|
||||
@@ -20,15 +20,15 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
|
||||
let Libraries = new Mongo.Collection('libraries');
|
||||
|
||||
let LibrarySchema = new SimpleSchema({
|
||||
name: {
|
||||
type: String,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.summary,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.summary,
|
||||
},
|
||||
});
|
||||
|
||||
LibrarySchema.extend(SharingSchema);
|
||||
@@ -38,96 +38,96 @@ Libraries.attachSchema(LibrarySchema);
|
||||
export default Libraries;
|
||||
|
||||
const insertLibrary = new ValidatedMethod({
|
||||
name: 'libraries.insert',
|
||||
mixins: [
|
||||
simpleSchemaMixin,
|
||||
],
|
||||
schema: LibrarySchema.omit('owner'),
|
||||
run(library) {
|
||||
if (!this.userId) {
|
||||
throw new Meteor.Error('Libraries.methods.insert.denied',
|
||||
'You need to be logged in to insert a library');
|
||||
}
|
||||
let tier = getUserTier(this.userId);
|
||||
if (!tier.paidBenefits) {
|
||||
throw new Meteor.Error('Libraries.methods.insert.denied',
|
||||
`The ${tier.name} tier does not allow you to insert a library`);
|
||||
}
|
||||
library.owner = this.userId;
|
||||
return Libraries.insert(library);
|
||||
},
|
||||
name: 'libraries.insert',
|
||||
mixins: [
|
||||
simpleSchemaMixin,
|
||||
],
|
||||
schema: LibrarySchema.omit('owner'),
|
||||
run(library) {
|
||||
if (!this.userId) {
|
||||
throw new Meteor.Error('Libraries.methods.insert.denied',
|
||||
'You need to be logged in to insert a library');
|
||||
}
|
||||
let tier = getUserTier(this.userId);
|
||||
if (!tier.paidBenefits) {
|
||||
throw new Meteor.Error('Libraries.methods.insert.denied',
|
||||
`The ${tier.name} tier does not allow you to insert a library`);
|
||||
}
|
||||
library.owner = this.userId;
|
||||
return Libraries.insert(library);
|
||||
},
|
||||
});
|
||||
|
||||
const updateLibraryName = new ValidatedMethod({
|
||||
name: 'libraries.updateName',
|
||||
validate: new SimpleSchema({
|
||||
_id: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.id
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ _id, name }) {
|
||||
let library = Libraries.findOne(_id);
|
||||
assertEditPermission(library, this.userId);
|
||||
Libraries.update(_id, { $set: { name } });
|
||||
},
|
||||
name: 'libraries.updateName',
|
||||
validate: new SimpleSchema({
|
||||
_id: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.id
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ _id, name }) {
|
||||
let library = Libraries.findOne(_id);
|
||||
assertEditPermission(library, this.userId);
|
||||
Libraries.update(_id, { $set: { name } });
|
||||
},
|
||||
});
|
||||
|
||||
const updateLibraryDescription = new ValidatedMethod({
|
||||
name: 'libraries.updateDescription',
|
||||
validate: new SimpleSchema({
|
||||
_id: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.id
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ _id, description }) {
|
||||
let library = Libraries.findOne(_id);
|
||||
assertEditPermission(library, this.userId);
|
||||
Libraries.update(_id, { $set: { description } });
|
||||
},
|
||||
name: 'libraries.updateDescription',
|
||||
validate: new SimpleSchema({
|
||||
_id: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.id
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ _id, description }) {
|
||||
let library = Libraries.findOne(_id);
|
||||
assertEditPermission(library, this.userId);
|
||||
Libraries.update(_id, { $set: { description } });
|
||||
},
|
||||
});
|
||||
|
||||
const removeLibrary = new ValidatedMethod({
|
||||
name: 'libraries.remove',
|
||||
validate: new SimpleSchema({
|
||||
_id: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.id
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ _id }) {
|
||||
let library = Libraries.findOne(_id);
|
||||
assertOwnership(library, this.userId);
|
||||
this.unblock();
|
||||
removeLibaryWork(_id)
|
||||
}
|
||||
name: 'libraries.remove',
|
||||
validate: new SimpleSchema({
|
||||
_id: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.id
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ _id }) {
|
||||
let library = Libraries.findOne(_id);
|
||||
assertOwnership(library, this.userId);
|
||||
this.unblock();
|
||||
removeLibaryWork(_id)
|
||||
}
|
||||
});
|
||||
|
||||
export function removeLibaryWork(libraryId) {
|
||||
Libraries.remove(libraryId);
|
||||
LibraryNodes.remove({ 'ancestors.id': libraryId });
|
||||
Libraries.remove(libraryId);
|
||||
LibraryNodes.remove({ 'ancestors.id': libraryId });
|
||||
}
|
||||
|
||||
export { LibrarySchema, insertLibrary, updateLibraryName, updateLibraryDescription, removeLibrary };
|
||||
|
||||
@@ -3,79 +3,79 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
|
||||
import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema.js';
|
||||
|
||||
let BuffSchema = createPropertySchema({
|
||||
name: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
description: {
|
||||
type: 'inlineCalculationFieldToCompute',
|
||||
optional: true,
|
||||
},
|
||||
hideRemoveButton: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
// How many rounds this buff lasts
|
||||
duration: {
|
||||
type: 'fieldToCompute',
|
||||
optional: true,
|
||||
},
|
||||
target: {
|
||||
type: String,
|
||||
allowedValues: [
|
||||
'self',
|
||||
'target',
|
||||
],
|
||||
defaultValue: 'target',
|
||||
},
|
||||
// Prevent the property from showing up in the log
|
||||
silent: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
// Prevent the children from being crystalized
|
||||
skipCrystalization: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
description: {
|
||||
type: 'inlineCalculationFieldToCompute',
|
||||
optional: true,
|
||||
},
|
||||
hideRemoveButton: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
// How many rounds this buff lasts
|
||||
duration: {
|
||||
type: 'fieldToCompute',
|
||||
optional: true,
|
||||
},
|
||||
target: {
|
||||
type: String,
|
||||
allowedValues: [
|
||||
'self',
|
||||
'target',
|
||||
],
|
||||
defaultValue: 'target',
|
||||
},
|
||||
// Prevent the property from showing up in the log
|
||||
silent: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
// Prevent the children from being crystalized
|
||||
skipCrystalization: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
});
|
||||
|
||||
let ComputedOnlyBuffSchema = createPropertySchema({
|
||||
description: {
|
||||
type: 'computedOnlyInlineCalculationField',
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.description,
|
||||
},
|
||||
duration: {
|
||||
type: 'computedOnlyField',
|
||||
optional: true,
|
||||
},
|
||||
durationSpent: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
min: 0,
|
||||
},
|
||||
appliedBy: {
|
||||
type: Object,
|
||||
optional: true,
|
||||
},
|
||||
'appliedBy.name': {
|
||||
type: String,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
'appliedBy.id': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
'appliedBy.collection': {
|
||||
type: String,
|
||||
max: STORAGE_LIMITS.collectionName,
|
||||
},
|
||||
description: {
|
||||
type: 'computedOnlyInlineCalculationField',
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.description,
|
||||
},
|
||||
duration: {
|
||||
type: 'computedOnlyField',
|
||||
optional: true,
|
||||
},
|
||||
durationSpent: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
min: 0,
|
||||
},
|
||||
appliedBy: {
|
||||
type: Object,
|
||||
optional: true,
|
||||
},
|
||||
'appliedBy.name': {
|
||||
type: String,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
'appliedBy.id': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
'appliedBy.collection': {
|
||||
type: String,
|
||||
max: STORAGE_LIMITS.collectionName,
|
||||
},
|
||||
});
|
||||
|
||||
const ComputedBuffSchema = new SimpleSchema()
|
||||
.extend(BuffSchema)
|
||||
.extend(ComputedOnlyBuffSchema);
|
||||
.extend(BuffSchema)
|
||||
.extend(ComputedOnlyBuffSchema);
|
||||
|
||||
export { BuffSchema, ComputedOnlyBuffSchema, ComputedBuffSchema };
|
||||
|
||||
@@ -3,69 +3,69 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
|
||||
import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema.js';
|
||||
|
||||
let ContainerSchema = createPropertySchema({
|
||||
name: {
|
||||
type: String,
|
||||
optional: true,
|
||||
trim: false,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
carried: {
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
optional: true,
|
||||
},
|
||||
contentsWeightless: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
weight: {
|
||||
type: Number,
|
||||
min: 0,
|
||||
optional: true,
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
min: 0,
|
||||
optional: true,
|
||||
},
|
||||
description: {
|
||||
type: 'inlineCalculationFieldToCompute',
|
||||
optional: true,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
optional: true,
|
||||
trim: false,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
carried: {
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
optional: true,
|
||||
},
|
||||
contentsWeightless: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
weight: {
|
||||
type: Number,
|
||||
min: 0,
|
||||
optional: true,
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
min: 0,
|
||||
optional: true,
|
||||
},
|
||||
description: {
|
||||
type: 'inlineCalculationFieldToCompute',
|
||||
optional: true,
|
||||
},
|
||||
});
|
||||
|
||||
const ComputedOnlyContainerSchema = createPropertySchema({
|
||||
description: {
|
||||
type: 'computedOnlyInlineCalculationField',
|
||||
optional: true,
|
||||
},
|
||||
// Weight of all the contents, zero if `contentsWeightless` is true
|
||||
contentsWeight: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
removeBeforeCompute: true,
|
||||
},
|
||||
// Weight of all the carried contents (some sub-containers might not be carried)
|
||||
// zero if `contentsWeightless` is true
|
||||
carriedWeight: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
removeBeforeCompute: true,
|
||||
},
|
||||
contentsValue: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
removeBeforeCompute: true,
|
||||
},
|
||||
carriedValue: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
removeBeforeCompute: true,
|
||||
},
|
||||
description: {
|
||||
type: 'computedOnlyInlineCalculationField',
|
||||
optional: true,
|
||||
},
|
||||
// Weight of all the contents, zero if `contentsWeightless` is true
|
||||
contentsWeight: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
removeBeforeCompute: true,
|
||||
},
|
||||
// Weight of all the carried contents (some sub-containers might not be carried)
|
||||
// zero if `contentsWeightless` is true
|
||||
carriedWeight: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
removeBeforeCompute: true,
|
||||
},
|
||||
contentsValue: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
removeBeforeCompute: true,
|
||||
},
|
||||
carriedValue: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
removeBeforeCompute: true,
|
||||
},
|
||||
});
|
||||
|
||||
const ComputedContainerSchema = new SimpleSchema()
|
||||
.extend(ComputedOnlyContainerSchema)
|
||||
.extend(ContainerSchema);
|
||||
.extend(ComputedOnlyContainerSchema)
|
||||
.extend(ContainerSchema);
|
||||
|
||||
export { ContainerSchema, ComputedOnlyContainerSchema, ComputedContainerSchema };
|
||||
|
||||
@@ -3,69 +3,69 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
|
||||
import createPropertySchema from '/imports/api/properties/subSchemas/createPropertySchema.js';
|
||||
|
||||
const ItemSchema = createPropertySchema({
|
||||
name: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
// Plural name of the item, if there is more than one
|
||||
plural: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
description: {
|
||||
type: 'inlineCalculationFieldToCompute',
|
||||
optional: true,
|
||||
},
|
||||
// Number currently held
|
||||
quantity: {
|
||||
type: SimpleSchema.Integer,
|
||||
min: 0,
|
||||
defaultValue: 1
|
||||
},
|
||||
// Weight per item in the stack
|
||||
weight: {
|
||||
type: Number,
|
||||
min: 0,
|
||||
optional: true,
|
||||
},
|
||||
// Value per item in the stack, in gold pieces
|
||||
value: {
|
||||
type: Number,
|
||||
min: 0,
|
||||
optional: true,
|
||||
},
|
||||
// If this item is equipped, it requires attunement
|
||||
requiresAttunement: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
attuned: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
// Show increment/decrement buttons in item lists
|
||||
showIncrement: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
// Unequipped items shouldn't affect creature stats
|
||||
equipped: {
|
||||
type: Boolean,
|
||||
defaultValue: false,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
// Plural name of the item, if there is more than one
|
||||
plural: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
description: {
|
||||
type: 'inlineCalculationFieldToCompute',
|
||||
optional: true,
|
||||
},
|
||||
// Number currently held
|
||||
quantity: {
|
||||
type: SimpleSchema.Integer,
|
||||
min: 0,
|
||||
defaultValue: 1
|
||||
},
|
||||
// Weight per item in the stack
|
||||
weight: {
|
||||
type: Number,
|
||||
min: 0,
|
||||
optional: true,
|
||||
},
|
||||
// Value per item in the stack, in gold pieces
|
||||
value: {
|
||||
type: Number,
|
||||
min: 0,
|
||||
optional: true,
|
||||
},
|
||||
// If this item is equipped, it requires attunement
|
||||
requiresAttunement: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
attuned: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
// Show increment/decrement buttons in item lists
|
||||
showIncrement: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
// Unequipped items shouldn't affect creature stats
|
||||
equipped: {
|
||||
type: Boolean,
|
||||
defaultValue: false,
|
||||
},
|
||||
});
|
||||
|
||||
let ComputedOnlyItemSchema = createPropertySchema({
|
||||
description: {
|
||||
type: 'computedOnlyInlineCalculationField',
|
||||
optional: true,
|
||||
},
|
||||
description: {
|
||||
type: 'computedOnlyInlineCalculationField',
|
||||
optional: true,
|
||||
},
|
||||
});
|
||||
|
||||
const ComputedItemSchema = new SimpleSchema()
|
||||
.extend(ItemSchema)
|
||||
.extend(ComputedOnlyItemSchema);
|
||||
.extend(ItemSchema)
|
||||
.extend(ComputedOnlyItemSchema);
|
||||
|
||||
export { ItemSchema, ComputedItemSchema, ComputedOnlyItemSchema };
|
||||
|
||||
@@ -3,99 +3,99 @@ import SimpleSchema from 'simpl-schema';
|
||||
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
|
||||
|
||||
const magicSchools = [
|
||||
'abjuration',
|
||||
'conjuration',
|
||||
'divination',
|
||||
'enchantment',
|
||||
'evocation',
|
||||
'illusion',
|
||||
'necromancy',
|
||||
'transmutation',
|
||||
'abjuration',
|
||||
'conjuration',
|
||||
'divination',
|
||||
'enchantment',
|
||||
'evocation',
|
||||
'illusion',
|
||||
'necromancy',
|
||||
'transmutation',
|
||||
];
|
||||
|
||||
let SpellSchema = new SimpleSchema({})
|
||||
.extend(ActionSchema)
|
||||
.extend({
|
||||
name: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
// If it's always prepared, it doesn't count against the number of spells
|
||||
// prepared in a spell list, and enabled should be true
|
||||
alwaysPrepared: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
prepared: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
// This spell ignores spell slot rules
|
||||
castWithoutSpellSlots: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
hasAttackRoll: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
castingTime: {
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: 'action',
|
||||
max: STORAGE_LIMITS.spellDetail,
|
||||
},
|
||||
range: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.spellDetail,
|
||||
},
|
||||
duration: {
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: 'Instantaneous',
|
||||
max: STORAGE_LIMITS.spellDetail,
|
||||
},
|
||||
verbal: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
somatic: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
concentration: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
material: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.spellDetail,
|
||||
},
|
||||
ritual: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
level: {
|
||||
type: SimpleSchema.Integer,
|
||||
defaultValue: 1,
|
||||
max: 9,
|
||||
min: 0,
|
||||
},
|
||||
school: {
|
||||
type: String,
|
||||
defaultValue: 'abjuration',
|
||||
allowedValues: magicSchools,
|
||||
},
|
||||
});
|
||||
.extend(ActionSchema)
|
||||
.extend({
|
||||
name: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.name,
|
||||
},
|
||||
// If it's always prepared, it doesn't count against the number of spells
|
||||
// prepared in a spell list, and enabled should be true
|
||||
alwaysPrepared: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
prepared: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
// This spell ignores spell slot rules
|
||||
castWithoutSpellSlots: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
hasAttackRoll: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
castingTime: {
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: 'action',
|
||||
max: STORAGE_LIMITS.spellDetail,
|
||||
},
|
||||
range: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.spellDetail,
|
||||
},
|
||||
duration: {
|
||||
type: String,
|
||||
optional: true,
|
||||
defaultValue: 'Instantaneous',
|
||||
max: STORAGE_LIMITS.spellDetail,
|
||||
},
|
||||
verbal: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
somatic: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
concentration: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
material: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.spellDetail,
|
||||
},
|
||||
ritual: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
level: {
|
||||
type: SimpleSchema.Integer,
|
||||
defaultValue: 1,
|
||||
max: 9,
|
||||
min: 0,
|
||||
},
|
||||
school: {
|
||||
type: String,
|
||||
defaultValue: 'abjuration',
|
||||
allowedValues: magicSchools,
|
||||
},
|
||||
});
|
||||
|
||||
const ComputedOnlySpellSchema = new SimpleSchema()
|
||||
.extend(ComputedOnlyActionSchema);
|
||||
.extend(ComputedOnlyActionSchema);
|
||||
|
||||
const ComputedSpellSchema = new SimpleSchema()
|
||||
.extend(SpellSchema)
|
||||
.extend(ComputedOnlySpellSchema);
|
||||
.extend(SpellSchema)
|
||||
.extend(ComputedOnlySpellSchema);
|
||||
|
||||
export { SpellSchema, ComputedOnlySpellSchema, ComputedSpellSchema };
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import SimpleSchema from 'simpl-schema';
|
||||
|
||||
const ColorSchema = new SimpleSchema({
|
||||
color: {
|
||||
type: String,
|
||||
// match hex colors of the form #A23 or #A23f56
|
||||
regEx: /^#([a-f0-9]{3}){1,2}\b$/i,
|
||||
optional: true,
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
// match hex colors of the form #A23 or #A23f56
|
||||
regEx: /^#([a-f0-9]{3}){1,2}\b$/i,
|
||||
optional: true,
|
||||
},
|
||||
});
|
||||
|
||||
export default ColorSchema;
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
import SimpleSchema from 'simpl-schema';
|
||||
|
||||
const DeathSavesSchema = new SimpleSchema({
|
||||
pass: {
|
||||
type: SimpleSchema.Integer,
|
||||
min: 0,
|
||||
max: 3,
|
||||
defaultValue: 0,
|
||||
},
|
||||
fail: {
|
||||
type: SimpleSchema.Integer,
|
||||
min: 0,
|
||||
max: 3,
|
||||
defaultValue: 0,
|
||||
},
|
||||
canDeathSave: {
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
stable: {
|
||||
type: Boolean,
|
||||
defaultValue: false,
|
||||
},
|
||||
pass: {
|
||||
type: SimpleSchema.Integer,
|
||||
min: 0,
|
||||
max: 3,
|
||||
defaultValue: 0,
|
||||
},
|
||||
fail: {
|
||||
type: SimpleSchema.Integer,
|
||||
min: 0,
|
||||
max: 3,
|
||||
defaultValue: 0,
|
||||
},
|
||||
canDeathSave: {
|
||||
type: Boolean,
|
||||
defaultValue: true,
|
||||
},
|
||||
stable: {
|
||||
type: Boolean,
|
||||
defaultValue: false,
|
||||
},
|
||||
});
|
||||
|
||||
export default DeathSavesSchema;
|
||||
|
||||
@@ -3,36 +3,36 @@ import '/imports/api/sharing/sharing.js';
|
||||
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
|
||||
|
||||
let SharingSchema = new SimpleSchema({
|
||||
owner: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
index: 1
|
||||
},
|
||||
readers: {
|
||||
type: Array,
|
||||
defaultValue: [],
|
||||
index: 1,
|
||||
maxCount: STORAGE_LIMITS.readersCount,
|
||||
},
|
||||
'readers.$': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id
|
||||
},
|
||||
writers: {
|
||||
type: Array,
|
||||
defaultValue: [],
|
||||
index: 1,
|
||||
maxCount: STORAGE_LIMITS.writersCount,
|
||||
},
|
||||
'writers.$': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id
|
||||
},
|
||||
public: {
|
||||
type: Boolean,
|
||||
defaultValue: false,
|
||||
index: 1,
|
||||
},
|
||||
owner: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
index: 1
|
||||
},
|
||||
readers: {
|
||||
type: Array,
|
||||
defaultValue: [],
|
||||
index: 1,
|
||||
maxCount: STORAGE_LIMITS.readersCount,
|
||||
},
|
||||
'readers.$': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id
|
||||
},
|
||||
writers: {
|
||||
type: Array,
|
||||
defaultValue: [],
|
||||
index: 1,
|
||||
maxCount: STORAGE_LIMITS.writersCount,
|
||||
},
|
||||
'writers.$': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id
|
||||
},
|
||||
public: {
|
||||
type: Boolean,
|
||||
defaultValue: false,
|
||||
index: 1,
|
||||
},
|
||||
});
|
||||
|
||||
export default SharingSchema;
|
||||
|
||||
@@ -11,321 +11,321 @@ const defaultLibraries = process.env.DEFAULT_LIBRARIES && process.env.DEFAULT_LI
|
||||
const defaultLibraryCollections = process.env.DEFAULT_LIBRARY_COLLECTIONS && process.env.DEFAULT_LIBRARY_COLLECTIONS.split(',') || [];
|
||||
|
||||
const userSchema = new SimpleSchema({
|
||||
username: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: 30,
|
||||
min: 4,
|
||||
},
|
||||
emails: {
|
||||
type: Array,
|
||||
optional: true,
|
||||
},
|
||||
'emails.$': {
|
||||
type: Object,
|
||||
},
|
||||
'emails.$.address': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Email,
|
||||
},
|
||||
'emails.$.verified': {
|
||||
type: Boolean,
|
||||
},
|
||||
registered_emails: {
|
||||
type: Array,
|
||||
optional: true,
|
||||
},
|
||||
'registered_emails.$': {
|
||||
type: Object,
|
||||
blackbox: true,
|
||||
},
|
||||
createdAt: {
|
||||
type: Date
|
||||
},
|
||||
services: {
|
||||
type: Object,
|
||||
optional: true,
|
||||
blackbox: true,
|
||||
},
|
||||
roles: {
|
||||
type: Array,
|
||||
optional: true,
|
||||
},
|
||||
'roles.$': {
|
||||
type: String
|
||||
},
|
||||
// In order to avoid an 'Exception in setInterval callback' from Meteor
|
||||
heartbeat: {
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
apiKey: {
|
||||
type: String,
|
||||
index: 1,
|
||||
optional: true,
|
||||
},
|
||||
darkMode: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
subscribedLibraries: {
|
||||
type: Array,
|
||||
defaultValue: defaultLibraries,
|
||||
maxCount: 100,
|
||||
},
|
||||
'subscribedLibraries.$': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
subscribedLibraryCollections: {
|
||||
type: Array,
|
||||
defaultValue: defaultLibraryCollections,
|
||||
maxCount: 100,
|
||||
},
|
||||
'subscribedLibraryCollections.$': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
subscribedCharacters: {
|
||||
type: Array,
|
||||
defaultValue: [],
|
||||
max: 100,
|
||||
},
|
||||
'subscribedCharacters.$': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
fileStorageUsed: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
},
|
||||
profile: {
|
||||
type: Object,
|
||||
blackbox: true,
|
||||
optional: true,
|
||||
},
|
||||
preferences: {
|
||||
type: Object,
|
||||
optional: true,
|
||||
defaultValue: {},
|
||||
},
|
||||
'preferences.swapAbilityScoresAndModifiers': {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
'preferences.hidePropertySelectDialogHelp': {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
username: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: 30,
|
||||
min: 4,
|
||||
},
|
||||
emails: {
|
||||
type: Array,
|
||||
optional: true,
|
||||
},
|
||||
'emails.$': {
|
||||
type: Object,
|
||||
},
|
||||
'emails.$.address': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Email,
|
||||
},
|
||||
'emails.$.verified': {
|
||||
type: Boolean,
|
||||
},
|
||||
registered_emails: {
|
||||
type: Array,
|
||||
optional: true,
|
||||
},
|
||||
'registered_emails.$': {
|
||||
type: Object,
|
||||
blackbox: true,
|
||||
},
|
||||
createdAt: {
|
||||
type: Date
|
||||
},
|
||||
services: {
|
||||
type: Object,
|
||||
optional: true,
|
||||
blackbox: true,
|
||||
},
|
||||
roles: {
|
||||
type: Array,
|
||||
optional: true,
|
||||
},
|
||||
'roles.$': {
|
||||
type: String
|
||||
},
|
||||
// In order to avoid an 'Exception in setInterval callback' from Meteor
|
||||
heartbeat: {
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
apiKey: {
|
||||
type: String,
|
||||
index: 1,
|
||||
optional: true,
|
||||
},
|
||||
darkMode: {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
subscribedLibraries: {
|
||||
type: Array,
|
||||
defaultValue: defaultLibraries,
|
||||
maxCount: 100,
|
||||
},
|
||||
'subscribedLibraries.$': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
subscribedLibraryCollections: {
|
||||
type: Array,
|
||||
defaultValue: defaultLibraryCollections,
|
||||
maxCount: 100,
|
||||
},
|
||||
'subscribedLibraryCollections.$': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
subscribedCharacters: {
|
||||
type: Array,
|
||||
defaultValue: [],
|
||||
max: 100,
|
||||
},
|
||||
'subscribedCharacters.$': {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
fileStorageUsed: {
|
||||
type: Number,
|
||||
optional: true,
|
||||
},
|
||||
profile: {
|
||||
type: Object,
|
||||
blackbox: true,
|
||||
optional: true,
|
||||
},
|
||||
preferences: {
|
||||
type: Object,
|
||||
optional: true,
|
||||
defaultValue: {},
|
||||
},
|
||||
'preferences.swapAbilityScoresAndModifiers': {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
'preferences.hidePropertySelectDialogHelp': {
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
});
|
||||
|
||||
Meteor.users.attachSchema(userSchema);
|
||||
|
||||
Meteor.users.generateApiKey = new ValidatedMethod({
|
||||
name: 'users.generateApiKey',
|
||||
validate: null,
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run() {
|
||||
if (Meteor.isClient) return;
|
||||
var user = Meteor.users.findOne(this.userId);
|
||||
if (!user) return;
|
||||
if (user && user.apiKey) return;
|
||||
var apiKey = Random.id(30);
|
||||
Meteor.users.update(this.userId, { $set: { apiKey } });
|
||||
},
|
||||
name: 'users.generateApiKey',
|
||||
validate: null,
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run() {
|
||||
if (Meteor.isClient) return;
|
||||
var user = Meteor.users.findOne(this.userId);
|
||||
if (!user) return;
|
||||
if (user && user.apiKey) return;
|
||||
var apiKey = Random.id(30);
|
||||
Meteor.users.update(this.userId, { $set: { apiKey } });
|
||||
},
|
||||
});
|
||||
|
||||
Meteor.users.setDarkMode = new ValidatedMethod({
|
||||
name: 'users.setDarkMode',
|
||||
validate: new SimpleSchema({
|
||||
darkMode: { type: Boolean },
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ darkMode }) {
|
||||
if (!this.userId) return;
|
||||
Meteor.users.update(this.userId, { $set: { darkMode } });
|
||||
},
|
||||
name: 'users.setDarkMode',
|
||||
validate: new SimpleSchema({
|
||||
darkMode: { type: Boolean },
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ darkMode }) {
|
||||
if (!this.userId) return;
|
||||
Meteor.users.update(this.userId, { $set: { darkMode } });
|
||||
},
|
||||
});
|
||||
|
||||
Meteor.users.sendVerificationEmail = new ValidatedMethod({
|
||||
name: 'users.sendVerificationEmail',
|
||||
validate: new SimpleSchema({
|
||||
userId: {
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ userId, address }) {
|
||||
userId = this.userId || userId;
|
||||
let user = Meteor.users.findOne(userId);
|
||||
if (!user) {
|
||||
throw new Meteor.Error('User not found',
|
||||
'Can\'t send a validation email to a user that does not exist');
|
||||
}
|
||||
if (!some(user.emails, email => email.address === address)) {
|
||||
throw new Meteor.Error('Email address not found',
|
||||
'The specified email address wasn\'t found on this user account');
|
||||
}
|
||||
Accounts.sendVerificationEmail(userId, address);
|
||||
}
|
||||
name: 'users.sendVerificationEmail',
|
||||
validate: new SimpleSchema({
|
||||
userId: {
|
||||
type: String,
|
||||
optional: true,
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ userId, address }) {
|
||||
userId = this.userId || userId;
|
||||
let user = Meteor.users.findOne(userId);
|
||||
if (!user) {
|
||||
throw new Meteor.Error('User not found',
|
||||
'Can\'t send a validation email to a user that does not exist');
|
||||
}
|
||||
if (!some(user.emails, email => email.address === address)) {
|
||||
throw new Meteor.Error('Email address not found',
|
||||
'The specified email address wasn\'t found on this user account');
|
||||
}
|
||||
Accounts.sendVerificationEmail(userId, address);
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.users.canPickUsername = new ValidatedMethod({
|
||||
name: 'users.canPickUsername',
|
||||
validate: userSchema.pick('username').validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ username }) {
|
||||
if (Meteor.isClient) return;
|
||||
let user = Accounts.findUserByUsername(username);
|
||||
// You can pick your own username
|
||||
if (user && user._id === this.userId) {
|
||||
return false;
|
||||
}
|
||||
return !!user;
|
||||
}
|
||||
name: 'users.canPickUsername',
|
||||
validate: userSchema.pick('username').validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ username }) {
|
||||
if (Meteor.isClient) return;
|
||||
let user = Accounts.findUserByUsername(username);
|
||||
// You can pick your own username
|
||||
if (user && user._id === this.userId) {
|
||||
return false;
|
||||
}
|
||||
return !!user;
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.users.setUsername = new ValidatedMethod({
|
||||
name: 'users.setUsername',
|
||||
validate: userSchema.pick('username').validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ username }) {
|
||||
if (!this.userId) throw 'Can only set your username if logged in';
|
||||
if (Meteor.isClient) return;
|
||||
return Accounts.setUsername(this.userId, username)
|
||||
}
|
||||
name: 'users.setUsername',
|
||||
validate: userSchema.pick('username').validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ username }) {
|
||||
if (!this.userId) throw 'Can only set your username if logged in';
|
||||
if (Meteor.isClient) return;
|
||||
return Accounts.setUsername(this.userId, username)
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.users.setPreference = new ValidatedMethod({
|
||||
name: 'users.setPreference',
|
||||
validate: new SimpleSchema({
|
||||
preference: {
|
||||
type: String,
|
||||
},
|
||||
value: {
|
||||
type: SimpleSchema.oneOf(Boolean),
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ preference, value }) {
|
||||
if (!this.userId) throw 'You can only set preferences once logged in';
|
||||
let prefPath = `preferences.${preference}`
|
||||
if (value == true) {
|
||||
return Meteor.users.update(this.userId, {
|
||||
$set: { [prefPath]: true },
|
||||
});
|
||||
} else {
|
||||
return Meteor.users.update(this.userId, {
|
||||
$unset: { [prefPath]: 1 },
|
||||
});
|
||||
}
|
||||
},
|
||||
name: 'users.setPreference',
|
||||
validate: new SimpleSchema({
|
||||
preference: {
|
||||
type: String,
|
||||
},
|
||||
value: {
|
||||
type: SimpleSchema.oneOf(Boolean),
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ preference, value }) {
|
||||
if (!this.userId) throw 'You can only set preferences once logged in';
|
||||
let prefPath = `preferences.${preference}`
|
||||
if (value == true) {
|
||||
return Meteor.users.update(this.userId, {
|
||||
$set: { [prefPath]: true },
|
||||
});
|
||||
} else {
|
||||
return Meteor.users.update(this.userId, {
|
||||
$unset: { [prefPath]: 1 },
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Meteor.users.subscribeToLibrary = new ValidatedMethod({
|
||||
name: 'users.subscribeToLibrary',
|
||||
validate: new SimpleSchema({
|
||||
libraryId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
subscribe: {
|
||||
type: Boolean,
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ libraryId, subscribe }) {
|
||||
if (!this.userId) throw 'Can only subscribe if logged in';
|
||||
if (subscribe) {
|
||||
return Meteor.users.update(this.userId, {
|
||||
$addToSet: { subscribedLibraries: libraryId },
|
||||
});
|
||||
} else {
|
||||
return Meteor.users.update(this.userId, {
|
||||
$pullAll: { subscribedLibraries: libraryId },
|
||||
});
|
||||
}
|
||||
}
|
||||
name: 'users.subscribeToLibrary',
|
||||
validate: new SimpleSchema({
|
||||
libraryId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
subscribe: {
|
||||
type: Boolean,
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ libraryId, subscribe }) {
|
||||
if (!this.userId) throw 'Can only subscribe if logged in';
|
||||
if (subscribe) {
|
||||
return Meteor.users.update(this.userId, {
|
||||
$addToSet: { subscribedLibraries: libraryId },
|
||||
});
|
||||
} else {
|
||||
return Meteor.users.update(this.userId, {
|
||||
$pullAll: { subscribedLibraries: libraryId },
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.users.subscribeToLibraryCollection = new ValidatedMethod({
|
||||
name: 'users.subscribeToLibraryCollection',
|
||||
validate: new SimpleSchema({
|
||||
libraryCollectionId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
subscribe: {
|
||||
type: Boolean,
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ libraryCollectionId, subscribe }) {
|
||||
if (!this.userId) throw 'Can only subscribe if logged in';
|
||||
if (subscribe) {
|
||||
return Meteor.users.update(this.userId, {
|
||||
$addToSet: { subscribedLibraryCollections: libraryCollectionId },
|
||||
});
|
||||
} else {
|
||||
return Meteor.users.update(this.userId, {
|
||||
$pullAll: { subscribedLibraryCollections: libraryCollectionId },
|
||||
});
|
||||
}
|
||||
}
|
||||
name: 'users.subscribeToLibraryCollection',
|
||||
validate: new SimpleSchema({
|
||||
libraryCollectionId: {
|
||||
type: String,
|
||||
regEx: SimpleSchema.RegEx.Id,
|
||||
},
|
||||
subscribe: {
|
||||
type: Boolean,
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ libraryCollectionId, subscribe }) {
|
||||
if (!this.userId) throw 'Can only subscribe if logged in';
|
||||
if (subscribe) {
|
||||
return Meteor.users.update(this.userId, {
|
||||
$addToSet: { subscribedLibraryCollections: libraryCollectionId },
|
||||
});
|
||||
} else {
|
||||
return Meteor.users.update(this.userId, {
|
||||
$pullAll: { subscribedLibraryCollections: libraryCollectionId },
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.users.findUserByUsernameOrEmail = new ValidatedMethod({
|
||||
name: 'users.findUserByUsernameOrEmail',
|
||||
validate: new SimpleSchema({
|
||||
usernameOrEmail: {
|
||||
type: String,
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ usernameOrEmail }) {
|
||||
if (Meteor.isClient) return;
|
||||
let user = Accounts.findUserByUsername(usernameOrEmail) ||
|
||||
Accounts.findUserByEmail(usernameOrEmail);
|
||||
return user && user._id;
|
||||
}
|
||||
name: 'users.findUserByUsernameOrEmail',
|
||||
validate: new SimpleSchema({
|
||||
usernameOrEmail: {
|
||||
type: String,
|
||||
},
|
||||
}).validator(),
|
||||
mixins: [RateLimiterMixin],
|
||||
rateLimit: {
|
||||
numRequests: 5,
|
||||
timeInterval: 5000,
|
||||
},
|
||||
run({ usernameOrEmail }) {
|
||||
if (Meteor.isClient) return;
|
||||
let user = Accounts.findUserByUsername(usernameOrEmail) ||
|
||||
Accounts.findUserByEmail(usernameOrEmail);
|
||||
return user && user._id;
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user