Merge branch 'master' into master
This commit is contained in:
99
app/lib/functions/backupRestoreCharacter.js
Normal file
99
app/lib/functions/backupRestoreCharacter.js
Normal file
@@ -0,0 +1,99 @@
|
||||
import { saveAs } from 'file-saver';
|
||||
|
||||
let characterCollections = [];
|
||||
Meteor.startup(() => {
|
||||
characterCollections = [
|
||||
Actions,
|
||||
Attacks,
|
||||
Buffs,
|
||||
Classes,
|
||||
Conditions,
|
||||
CustomBuffs,
|
||||
Effects,
|
||||
Experiences,
|
||||
Features,
|
||||
Notes,
|
||||
Proficiencies,
|
||||
SpellLists,
|
||||
Spells,
|
||||
TemporaryHitPoints,
|
||||
Items,
|
||||
Containers,
|
||||
];
|
||||
});
|
||||
|
||||
dumpCharacter = function(charId){
|
||||
let characterDump = {collections: {}};
|
||||
characterDump.character = Characters.findOne(charId);
|
||||
characterCollections.forEach(c => {
|
||||
characterDump.collections[c._name] = c.find({charId}).fetch();
|
||||
});
|
||||
return characterDump;
|
||||
};
|
||||
|
||||
saveCharacterDump = function(charId){
|
||||
let dump = dumpCharacter(charId);
|
||||
let textDump = JSON.stringify(dump, null, 2);
|
||||
let charName = dump.character.name;
|
||||
let blob = new Blob([textDump], {type: "application/json;charset=utf-8"});
|
||||
saveAs(blob, `${charName}.JSON`);
|
||||
};
|
||||
|
||||
giveCharacterDumpNewIds = function(characterDump){
|
||||
// Give the character a new Id
|
||||
const oldCharId = characterDump.character._id;
|
||||
const newCharId = Random.id();
|
||||
characterDump.character._id = newCharId;
|
||||
|
||||
let idMap = {[oldCharId]: newCharId}; // {oldId: newId}
|
||||
|
||||
// Give all documents a new Id, and store the mapping from old to new
|
||||
for (let colName in characterDump.collections){
|
||||
for (let doc of characterDump.collections[colName]){
|
||||
let oldId = doc._id;
|
||||
let newId = Random.id();
|
||||
doc._id = newId;
|
||||
idMap[oldId] = newId;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace all references to old Ids with new ones
|
||||
for (let colName in characterDump.collections){
|
||||
for (let doc of characterDump.collections[colName]){
|
||||
// Replace the character Id with the new one
|
||||
doc.charId = newCharId;
|
||||
// Replace the parent reference id with a new id
|
||||
if (doc.parent && doc.parent.id){
|
||||
let newParentId = idMap[doc.parent.id];
|
||||
if(!newParentId) throw `Can't find the mapping for id ${doc.parent.id}`;
|
||||
doc.parent.id = newParentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
restoreCharacter = function(characterDump){
|
||||
Characters.direct.insert(characterDump.character);
|
||||
for (collectionName in characterDump.collections){
|
||||
let collection = Meteor.Collection.get(collectionName);
|
||||
for (doc of characterDump.collections[collectionName]){
|
||||
// delete problematic keys that shouldn't ever be available on insert
|
||||
delete doc.restoredAt;
|
||||
delete doc.restoredBy;
|
||||
// Insert the doc with no hooks
|
||||
collection.direct.insert(doc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Meteor.methods({
|
||||
restoreCharacter(characterDump){
|
||||
characterDump.character.name += " - Restored"
|
||||
characterDump.character.owner = Meteor.userId();
|
||||
characterDump.character.readers = [];
|
||||
characterDump.character.writers = [];
|
||||
giveCharacterDumpNewIds(characterDump);
|
||||
restoreCharacter(characterDump);
|
||||
return characterDump.character
|
||||
},
|
||||
});
|
||||
@@ -12,12 +12,14 @@ canEditCharacter = function(charId, userId){
|
||||
return (userId === char.owner || _.contains(char.writers, userId));
|
||||
};
|
||||
|
||||
canViewCharacter = function(charId, userId){
|
||||
canViewCharacter = function(char, userId){
|
||||
userId = userId || Meteor.userId();
|
||||
var char = Characters.findOne(
|
||||
charId,
|
||||
{fields: {owner: 1, writers: 1, readers: 1, "settings.viewPermission": 1}}
|
||||
);
|
||||
if (typeof char !== 'object'){
|
||||
char = Characters.findOne(
|
||||
char,
|
||||
{fields: {owner: 1, writers: 1, readers: 1, "settings.viewPermission": 1}}
|
||||
);
|
||||
}
|
||||
if (!char) return true;
|
||||
return userId === char.owner ||
|
||||
char.settings.viewPermission === "public" ||
|
||||
|
||||
26
app/lib/methods/characterCopyPaste.js
Normal file
26
app/lib/methods/characterCopyPaste.js
Normal file
@@ -0,0 +1,26 @@
|
||||
// Uses '/lib/functions/backupRestoreCharacter.js' to do most the work
|
||||
|
||||
Meteor.methods({
|
||||
copyCharacter: function(charId) {
|
||||
const userId = Meteor.userId();
|
||||
let character = Characters.findOne(charId);
|
||||
|
||||
// Need at least view level permission to make a copy for yourself
|
||||
if (!canViewCharacter(character, userId)) return;
|
||||
|
||||
let characterDump = dumpCharacter(charId);
|
||||
giveCharacterDumpNewIds(characterDump);
|
||||
|
||||
// Remove all readers and writers, make this user the new owner
|
||||
characterDump.character.readers = [];
|
||||
characterDump.character.writers = [];
|
||||
characterDump.character.owner = userId;
|
||||
|
||||
// Rename the character so it's obviously a copy
|
||||
characterDump.character.name += " - Copy";
|
||||
|
||||
// Write the character back to the database
|
||||
restoreCharacter(characterDump);
|
||||
return characterDump.character;
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user