Files
DiceCloud/app/imports/server/publications/library.js
2024-04-30 12:51:34 +02:00

317 lines
7.3 KiB
JavaScript

import SimpleSchema from 'simpl-schema';
import Libraries from '/imports/api/library/Libraries';
import LibraryCollections from '/imports/api/library/LibraryCollections';
import LibraryNodes from '/imports/api/library/LibraryNodes';
import { assertViewPermission, assertDocViewPermission } from '/imports/api/sharing/sharingPermissions';
import { union } from 'lodash';
const LIBRARY_NODE_TREE_FIELDS = {
_id: 1,
name: 1,
type: 1,
icon: 1,
color: 1,
// Old tree fields
order: 1,
parent: 1,
ancestors: 1,
// Tree fields
parentId: 1,
left: 1,
right: 1,
root: 1,
removed: 1,
removedAt: 1,
// Actions
actionType: 1,
// SlotFillers
libraryTags: 1,
slotQuantityFilled: 1,
slotFillerType: 1,
slotFillerConditionNote: 1,
slotFillerCondition: 1,
fillSlots: 1,
searchable: 1,
slotFillImage: 1,
// Effect
operation: 1,
targetTags: 1,
stats: 1,
// Item
quantity: 1,
plural: 1,
equipped: 1,
// Branch
branchType: 1,
// Damage:
damageType: 1,
stat: 1,
amount: 1,
// Class level
level: 1,
variableName: 1,
// Proficiency
value: 1,
// Reference
cache: 1,
// Saving throw
dc: 1,
}
export { LIBRARY_NODE_TREE_FIELDS };
Meteor.publish('libraryCollection', function (libraryCollectionId) {
this.autorun(function () {
let userId = this.userId;
if (!userId) return [];
this.autorun(function () {
const libraryCollectionCursor = LibraryCollections.find({
_id: libraryCollectionId,
$or: [
{ owner: userId },
{ writers: userId },
{ readers: userId },
{ public: true },
]
});
const libraryCollection = libraryCollectionCursor.fetch()[0];
if (!libraryCollection) return [libraryCollectionCursor];
this.autorun(function () {
const libraryCursor = Libraries.find({
_id: { $in: libraryCollection.libraries },
$or: [
{ owner: userId },
{ writers: userId },
{ readers: userId },
{ public: true },
]
}, {
sort: { name: 1 }
});
return [
libraryCollectionCursor,
libraryCursor,
Meteor.users.find(
libraryCollection.owner,
{ fields: { username: 1 } }
),
];
});
});
})
});
Meteor.publish('libraries', function () {
this.autorun(function () {
let userId = this.userId;
if (!userId) {
return [];
}
const user = Meteor.users.findOne(userId, {
fields: { subscribedLibraries: 1, subscribedLibraryCollections: 1 }
});
this.autorun(function () {
// Get the collections the user is subscribed to
const subCollections = user && user.subscribedLibraryCollections || [];
const libraryCollectionsCursor = LibraryCollections.find({
$or: [
{ owner: userId },
{ writers: userId },
{ readers: userId },
{ _id: { $in: subCollections }, public: true },
]
}, {
sort: { name: 1 }
});
// Collate all the libraryIds in those collections
let collectionLibIds = [];
libraryCollectionsCursor.forEach(libCollection => {
collectionLibIds = union(collectionLibIds, libCollection.libraries);
});
// Get the libraries the user is subscribed to directly
const subs = user && user.subscribedLibraries || [];
// Combine all the library Ids
const libIds = union(collectionLibIds, subs);
this.autorun(function () {
const librariesCursor = Libraries.find({
$or: [
{ owner: userId },
{ writers: userId },
{ readers: userId },
{ _id: { $in: libIds }, public: true },
]
}, {
sort: { name: 1 }
});
return [librariesCursor, libraryCollectionsCursor];
});
});
});
});
Meteor.publish('browseLibraries', function () {
if (!this.userId) return [];
return [
Libraries.find({
showInMarket: true,
public: true,
}, {
sort: {
subscriberCount: 1,
name: 1,
},
limit: 500,
}),
LibraryCollections.find({
showInMarket: true,
public: true,
}, {
sort: {
subscriberCount: 1,
name: 1
},
limit: 500,
}),
];
});
Meteor.publish('library', function (libraryId) {
if (!libraryId) return [];
libraryIdSchema.validate({ libraryId });
this.autorun(function () {
let userId = this.userId;
let library = Libraries.findOne(libraryId);
try { assertViewPermission(library, userId) }
catch (e) {
return this.error(e);
}
return [
Libraries.find({
_id: libraryId,
}),
Meteor.users.find(
library.owner,
{ fields: { username: 1 } }
),
];
});
});
let libraryIdSchema = new SimpleSchema({
libraryId: {
type: String,
regEx: SimpleSchema.RegEx.Id,
},
});
const extraFieldsSchema = new SimpleSchema({
extraFields: {
type: Array,
optional: true,
},
'extraFields.$': {
type: String,
},
});
Meteor.publish('libraryNodes', function (libraryId, extraFields) {
if (!libraryId) return [];
try {
libraryIdSchema.validate({ libraryId });
extraFieldsSchema.validate({ extraFields });
} catch (e) {
return this.error(e);
}
this.autorun(function () {
let userId = this.userId;
let library = Libraries.findOne(libraryId);
try {
assertViewPermission(library, userId)
} catch (e) {
return this.error(e);
}
const fields = { ...LIBRARY_NODE_TREE_FIELDS };
extraFields?.forEach(field => {
fields[field] = 1;
});
return [
LibraryNodes.find({
'root.id': libraryId,
}, {
sort: { left: 1 },
fields,
}),
];
});
});
const nodeIdSchema = new SimpleSchema({
libraryNodeId: {
type: String,
regEx: SimpleSchema.RegEx.Id,
},
});
Meteor.publish('libraryNode', function (libraryNodeId) {
if (!libraryNodeId) return [];
nodeIdSchema.validate({ libraryNodeId });
this.autorun(function () {
const userId = this.userId;
const nodeCursor = LibraryNodes.find({ _id: libraryNodeId });
let node = nodeCursor.fetch()[0];
try { assertDocViewPermission(node, userId) }
catch (e) {
return this.error(e);
}
return [nodeCursor];
});
});
Meteor.publish('softRemovedLibraryNodes', function (libraryId) {
if (!libraryId) return [];
libraryIdSchema.validate({ libraryId });
this.autorun(function () {
let userId = this.userId;
let library = Libraries.findOne(libraryId);
try { assertViewPermission(library, userId) }
catch (e) {
return this.error(e);
}
return [
LibraryNodes.find({
'ancestors.0.id': libraryId,
removed: true,
removedWith: { $exists: false },
}, {
sort: { left: 1 },
}),
];
});
});
Meteor.publish('descendantLibraryNodes', function (nodeId) {
let node = LibraryNodes.findOne(nodeId);
let libraryId = node?.ancestors[0]?.id;
if (!libraryId) return [];
this.autorun(function () {
let userId = this.userId;
let library = Libraries.findOne(libraryId);
try { assertViewPermission(library, userId) }
catch (e) {
return this.error(e);
}
return [
LibraryNodes.find({
'ancestors.id': nodeId,
}, {
sort: { left: 1 },
}),
];
});
});