rename /rpg-docs to /app
This commit is contained in:
27
app/server/lib/configuration/accountsMeldConfig.js
Normal file
27
app/server/lib/configuration/accountsMeldConfig.js
Normal file
@@ -0,0 +1,27 @@
|
||||
AccountsMeld.configure({
|
||||
meldDBCallback: function(sourceUserId, destinationUserId){
|
||||
// Here you can modify every collection you need for the document referencing
|
||||
// to sourceUserId to be modified in order to point to destinationUserId
|
||||
Characters.update(
|
||||
{owner: sourceUserId},
|
||||
{$set: {owner: destinationUserId}},
|
||||
{multi: true}
|
||||
);
|
||||
Characters.update(
|
||||
{writers: sourceUserId},
|
||||
{
|
||||
$pull: {writers: sourceUserId},
|
||||
$addToSet: {writers: destinationUserId},
|
||||
},
|
||||
{multi: true}
|
||||
);
|
||||
Characters.update(
|
||||
{readers: sourceUserId},
|
||||
{
|
||||
$pull: {readers: sourceUserId},
|
||||
$addToSet: {readers: destinationUserId},
|
||||
},
|
||||
{multi: true}
|
||||
);
|
||||
},
|
||||
});
|
||||
45
app/server/lib/cron/deleteRemovedDocuments.js
Normal file
45
app/server/lib/cron/deleteRemovedDocuments.js
Normal file
@@ -0,0 +1,45 @@
|
||||
Meteor.startup(() => {
|
||||
const collections = [
|
||||
Attacks, Buffs, Classes, CustomBuffs, Effects, Experiences,
|
||||
Features, Notes, Proficiencies, SpellLists, Spells,
|
||||
Containers, Items,
|
||||
];
|
||||
|
||||
/**
|
||||
* Deletes all soft removed documents that were removed more than 30 minutes ago
|
||||
* and were not restored
|
||||
* @return {Number} Number of documents removed
|
||||
*/
|
||||
const deleteOldSoftRemovedDocs = function(){
|
||||
let numRemoved = 0;
|
||||
const now = new Date();
|
||||
const thirtyMinutesAgo = new Date(now.getTime() - 30*60000);
|
||||
_.each(collections, (collection) => {
|
||||
numRemoved += collection.remove({
|
||||
removed: true,
|
||||
removedAt: {$lt: thirtyMinutesAgo} // dates *before* 30 minutes ago
|
||||
});
|
||||
});
|
||||
return numRemoved;
|
||||
};
|
||||
|
||||
SyncedCron.add({
|
||||
name: "Delete all soft removed items that haven't been restored",
|
||||
schedule: function(parser) {
|
||||
return parser.text('every 6 hours');
|
||||
},
|
||||
job: function() {
|
||||
deleteOldSoftRemovedDocs();
|
||||
}
|
||||
});
|
||||
|
||||
// Add a method to manually trigger removal
|
||||
Meteor.methods({
|
||||
deleteOldSoftRemovedDocs() {
|
||||
const user = Meteor.users.findOne(this.userId);
|
||||
if (user && _.contains(user.roles, "admin")){
|
||||
return deleteOldSoftRemovedDocs();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
8
app/server/lib/logRateError.js
Normal file
8
app/server/lib/logRateError.js
Normal file
@@ -0,0 +1,8 @@
|
||||
logRateError = function(reply, ruleInput){
|
||||
// reply = {allowed, timeToReset, numInvocationsLeft}
|
||||
// ruleInput = {userId, clientAddress, type, name, connectionId}
|
||||
console.log(
|
||||
`Limit hit for ${ruleInput.type} "${ruleInput.name}" ` +
|
||||
`by user ${ruleInput.userId} from ${ruleInput.clientAddress}`
|
||||
);
|
||||
}
|
||||
56
app/server/migrations/migrations.js
Normal file
56
app/server/migrations/migrations.js
Normal file
@@ -0,0 +1,56 @@
|
||||
Meteor.methods({
|
||||
getVersion: function() {
|
||||
return Migrations.getVersion();
|
||||
},
|
||||
migrateTo: function(versionNumber) {
|
||||
var user = Meteor.users.findOne(this.userId);
|
||||
if (!user){
|
||||
throw new Meteor.Error(
|
||||
"logged-out",
|
||||
"The user must be logged in to migrate the database"
|
||||
);
|
||||
}
|
||||
if (_.contains(user.roles, "admin")){
|
||||
Migrations.migrateTo(versionNumber);
|
||||
} else {
|
||||
throw new Meteor.Error(
|
||||
"not admin",
|
||||
"The user must be an administrator to migrate the database"
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Migrations.add({
|
||||
version: 1,
|
||||
name: "Gives all characters a URL name",
|
||||
up: function() {
|
||||
//update characters
|
||||
Characters.find({}).forEach(function(char){
|
||||
if (char.urlName) return;
|
||||
var urlName = getSlug(char.name, {maintainCase: true}) || "-";
|
||||
Characters.update(char._id, {$set: {urlName}});
|
||||
});
|
||||
},
|
||||
down: function(){
|
||||
return;
|
||||
},
|
||||
});
|
||||
|
||||
Migrations.add({
|
||||
version: 2,
|
||||
name: "Adds TempHP as a character attribute",
|
||||
up: function() {
|
||||
//update characters
|
||||
Characters.find({}).forEach(function(char){
|
||||
if (char.tempHP) return;
|
||||
Characters.update(char._id, {$set: {
|
||||
"tempHP.adjustment": 0,
|
||||
"tempHP.reset": "longRest",
|
||||
}});
|
||||
});
|
||||
},
|
||||
down: function(){
|
||||
return;
|
||||
},
|
||||
});
|
||||
3
app/server/publications/changeLog.js
Normal file
3
app/server/publications/changeLog.js
Normal file
@@ -0,0 +1,3 @@
|
||||
Meteor.publish("changeLog", function(){
|
||||
return ChangeLogs.find();
|
||||
});
|
||||
34
app/server/publications/characterList.js
Normal file
34
app/server/publications/characterList.js
Normal file
@@ -0,0 +1,34 @@
|
||||
Meteor.publish("characterList", function(){
|
||||
var userId = this.userId;
|
||||
if (!userId) {
|
||||
this.ready();
|
||||
return;
|
||||
}
|
||||
return [
|
||||
Characters.find(
|
||||
{$or: [{readers: userId}, {writers: userId}, {owner: userId}]},
|
||||
{
|
||||
fields: {
|
||||
name: 1,
|
||||
urlName: 1,
|
||||
race: 1,
|
||||
alignment: 1,
|
||||
gender: 1,
|
||||
readers: 1,
|
||||
writers:1,
|
||||
owner: 1,
|
||||
color: 1,
|
||||
picture: 1,
|
||||
}
|
||||
}
|
||||
),
|
||||
Parties.find({owner: userId}),
|
||||
];
|
||||
});
|
||||
|
||||
DDPRateLimiter.addRule({
|
||||
name: "characterList",
|
||||
type: "subscription",
|
||||
userId(){ return true; },
|
||||
connectionId(){ return true; },
|
||||
}, 8, 5000);
|
||||
25
app/server/publications/library.js
Normal file
25
app/server/publications/library.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const standardLibraryIds = [
|
||||
"SRDLibraryGA3XWsd",
|
||||
];
|
||||
|
||||
Meteor.publish("standardLibraries", function(){
|
||||
return Libraries.find({_id: {$in: standardLibraryIds}});
|
||||
});
|
||||
|
||||
Meteor.publish("standardLibraryItems", function(categoryKey){
|
||||
return LibraryItems.find({
|
||||
library: {$in: standardLibraryIds},
|
||||
"settings.category": categoryKey,
|
||||
}, {
|
||||
sort: {name: 1},
|
||||
});
|
||||
});
|
||||
|
||||
Meteor.publish("standardLibrarySpells", function(level){
|
||||
return LibrarySpells.find({
|
||||
library: {$in: standardLibraryIds},
|
||||
level,
|
||||
}, {
|
||||
sort: {name: 1},
|
||||
});
|
||||
});
|
||||
62
app/server/publications/singleCharacter.js
Normal file
62
app/server/publications/singleCharacter.js
Normal file
@@ -0,0 +1,62 @@
|
||||
Meteor.publish("singleCharacter", function(characterId){
|
||||
userId = this.userId;
|
||||
var char = Characters.findOne({
|
||||
_id: characterId,
|
||||
$or: [
|
||||
{readers: userId},
|
||||
{writers: userId},
|
||||
{owner: userId},
|
||||
{"settings.viewPermission": "public"},
|
||||
],
|
||||
});
|
||||
if (char){
|
||||
return [
|
||||
Characters.find({_id: characterId}),
|
||||
//get all the assets for this character including soft deleted ones
|
||||
Actions.find ({charId: characterId}, {removed: true}),
|
||||
Attacks.find ({charId: characterId}, {removed: true}),
|
||||
Buffs.find ({charId: characterId}, {removed: true}),
|
||||
Classes.find ({charId: characterId}, {removed: true}),
|
||||
Conditions.find ({charId: characterId}, {removed: true}),
|
||||
Containers.find ({charId: characterId}, {removed: true}),
|
||||
CustomBuffs.find ({charId: characterId}, {removed: true}),
|
||||
Effects.find ({charId: characterId}, {removed: true}),
|
||||
Experiences.find ({charId: characterId}, {removed: true}),
|
||||
Features.find ({charId: characterId}, {removed: true}),
|
||||
Items.find ({charId: characterId}, {removed: true}),
|
||||
Notes.find ({charId: characterId}, {removed: true}),
|
||||
Spells.find ({charId: characterId}, {removed: true}),
|
||||
SpellLists.find ({charId: characterId}, {removed: true}),
|
||||
TemporaryHitPoints.find ({charId: characterId}, {removed: true}),
|
||||
Proficiencies.find ({charId: characterId}, {removed: true}),
|
||||
];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
DDPRateLimiter.addRule({
|
||||
name: "singleCharacter",
|
||||
type: "subscription",
|
||||
userId: null,
|
||||
connectionId(){ return true; },
|
||||
}, 8, 10000, function(reply, ruleInput){
|
||||
if(!reply.allowed){
|
||||
logRateError(reply, ruleInput);
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.publish("singleCharacterName", function(characterId){
|
||||
userId = this.userId;
|
||||
return Characters.find({
|
||||
_id: characterId,
|
||||
$or: [
|
||||
{readers: userId},
|
||||
{writers: userId},
|
||||
{owner: userId},
|
||||
{"settings.viewPermission": "public"},
|
||||
],
|
||||
}, {
|
||||
fields:{"name": 1}
|
||||
});
|
||||
});
|
||||
8
app/server/publications/user.js
Normal file
8
app/server/publications/user.js
Normal file
@@ -0,0 +1,8 @@
|
||||
Meteor.publish("user", function(){
|
||||
return Meteor.users.find(this.userId, {fields: {
|
||||
roles: 1,
|
||||
username: 1,
|
||||
profile: 1,
|
||||
apiKey: 1,
|
||||
}});
|
||||
});
|
||||
7
app/server/publications/users.js
Normal file
7
app/server/publications/users.js
Normal file
@@ -0,0 +1,7 @@
|
||||
Meteor.publish("userNames", function(ids){
|
||||
if (!this.userId || !ids) return [];
|
||||
return Meteor.users.find(
|
||||
{_id: {$in: ids}},
|
||||
{fields: {username: 1}}
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user