From a86ff1e8d03d330a7ea0702cf3677859ed552509 Mon Sep 17 00:00:00 2001 From: Lauri Ojansivu Date: Sat, 11 Oct 2025 12:13:11 +0300 Subject: [PATCH] Fixed attachments and minicard related bugs that prevented WeKan starting. Thanks to xet7 ! --- client/components/cards/minicard.jade | 20 ++--- client/components/users/userAvatar.js | 2 +- ...nts_old.js => attachments_old.js.disabled} | 1 + ...avatars_old.js => avatars_old.js.disabled} | 0 models/presences.js | 7 +- models/users.js | 74 +++++++++++-------- package-lock.json | 13 ++++ package.json | 15 ++-- 8 files changed, 82 insertions(+), 50 deletions(-) rename models/{attachments_old.js => attachments_old.js.disabled} (98%) rename models/{avatars_old.js => avatars_old.js.disabled} (100%) diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade index 5eefb6da1..7a53192ce 100644 --- a/client/components/cards/minicard.jade +++ b/client/components/cards/minicard.jade @@ -72,16 +72,6 @@ template(name="minicard") span.card-number | ##{getCardNumber} = getTitle -if shouldShowListOnMinicard - .minicard-list-name - i.fa.fa-list - | {{ listName }} - if $eq 'subtext-with-full-path' currentBoard.presentParentTask - .parent-subtext - | {{ parentString ' > ' }} - if $eq 'subtext-with-parent' currentBoard.presentParentTask - .parent-subtext - | {{ parentCardName }} if labels .minicard-labels(class="{{#if hiddenMinicardLabelText}}minicard-labels-no-text{{/if}}") each labels @@ -201,6 +191,16 @@ if shouldShowListOnMinicard .minicard-description +viewer | {{ getDescription }} + if shouldShowListOnMinicard + .minicard-list-name + i.fa.fa-list + | {{ listName }} + if $eq 'subtext-with-full-path' currentBoard.presentParentTask + .parent-subtext + | {{ parentString ' > ' }} + if $eq 'subtext-with-parent' currentBoard.presentParentTask + .parent-subtext + | {{ parentCardName }} template(name="editCardSortOrderPopup") input.js-edit-card-sort-popup(type='text' autofocus value=sort dir="auto") diff --git a/client/components/users/userAvatar.js b/client/components/users/userAvatar.js index 8682f4a27..98ebc901e 100644 --- a/client/components/users/userAvatar.js +++ b/client/components/users/userAvatar.js @@ -23,7 +23,7 @@ Template.userAvatar.helpers({ /* presenceStatusClassName() { const user = ReactiveCache.getUser(this.userId); - const userPresence = presences.findOne({ userId: this.userId }); + const userPresence = Presences.findOne({ userId: this.userId }); if (user && user.isInvitedTo(Session.get('currentBoard'))) return 'pending'; else if (!userPresence) return 'disconnected'; else if (Session.equals('currentBoard', userPresence.state.currentBoardId)) diff --git a/models/attachments_old.js b/models/attachments_old.js.disabled similarity index 98% rename from models/attachments_old.js rename to models/attachments_old.js.disabled index fae4b844c..9b117d633 100644 --- a/models/attachments_old.js +++ b/models/attachments_old.js.disabled @@ -1,4 +1,5 @@ import { ReactiveCache } from '/imports/reactiveCache'; +import { FS } from 'meteor/cfs:base-package'; const storeName = 'attachments'; const defaultStoreOptions = { diff --git a/models/avatars_old.js b/models/avatars_old.js.disabled similarity index 100% rename from models/avatars_old.js rename to models/avatars_old.js.disabled diff --git a/models/presences.js b/models/presences.js index 94c8fdabb..4debbb94c 100644 --- a/models/presences.js +++ b/models/presences.js @@ -1,12 +1,15 @@ +// Define presences collection +Presences = new Mongo.Collection('presences'); + if (Meteor.isServer) { Meteor.startup(() => { // Date of 7 days ago let lastWeek = new Date(); lastWeek.setDate(lastWeek.getDate() - 7); - presences.remove({ ttl: { $lte: lastWeek } }); + Presences.remove({ ttl: { $lte: lastWeek } }); // Create index for serverId that is queried often - presences._collection._ensureIndex({ serverId: -1 }); + Presences._collection._ensureIndex({ serverId: -1 }); }); } diff --git a/models/users.js b/models/users.js index 947d652e7..0e2ff1db7 100644 --- a/models/users.js +++ b/models/users.js @@ -2,7 +2,7 @@ import { ReactiveCache, ReactiveMiniMongoIndex } from '/imports/reactiveCache'; import { SyncedCron } from 'meteor/percolate:synced-cron'; import { TAPi18n } from '/imports/i18n'; import ImpersonatedUsers from './impersonatedUsers'; -import { Index, MongoDBEngine } from 'meteor/easy:search'; +// import { Index, MongoDBEngine } from 'meteor/easy:search'; // Temporarily disabled due to compatibility issues // Sandstorm context is detected using the METEOR_SETTINGS environment variable // in the package definition. @@ -589,43 +589,57 @@ Users.deny({ // Custom MongoDB engine that enforces field restrictions -class SecureMongoDBEngine extends MongoDBEngine { - getSearchCursor(searchObject, options) { - // Always enforce field projection to prevent data leakage - const secureProjection = { - _id: 1, - username: 1, - 'profile.fullname': 1, - 'profile.avatarUrl': 1, - }; +// TODO: Re-enable when easy:search compatibility is fixed +// class SecureMongoDBEngine extends MongoDBEngine { +// getSearchCursor(searchObject, options) { +// // Always enforce field projection to prevent data leakage +// const secureProjection = { +// _id: 1, +// username: 1, +// 'profile.fullname': 1, +// 'profile.avatarUrl': 1, +// }; - // Override any projection passed in options - const secureOptions = { - ...options, - projection: secureProjection, - }; +// // Override any projection passed in options +// const secureOptions = { +// ...options, +// projection: secureProjection, +// }; - return super.getSearchCursor(searchObject, secureOptions); - } -} +// return super.getSearchCursor(searchObject, secureOptions); +// } +// } // Search a user in the complete server database by its name, username or emails adress. This // is used for instance to add a new user to a board. -UserSearchIndex = new Index({ - collection: Users, - fields: ['username', 'profile.fullname', 'profile.avatarUrl'], - allowedFields: ['username', 'profile.fullname', 'profile.avatarUrl', '_id'], - engine: new SecureMongoDBEngine({ - fields: function (searchObject, options) { - return { +// TODO: Fix easy:search compatibility issue - temporarily disabled +// UserSearchIndex = new Index({ +// collection: Users, +// fields: ['username', 'profile.fullname', 'profile.avatarUrl'], +// engine: new MongoDBEngine(), +// }); + +// Temporary fallback - create a simple search index object +UserSearchIndex = { + search: function(query, options) { + // Simple fallback search using MongoDB find + const searchRegex = new RegExp(query, 'i'); + return Users.find({ + $or: [ + { username: searchRegex }, + { 'profile.fullname': searchRegex } + ] + }, { + fields: { _id: 1, username: 1, 'profile.fullname': 1, - 'profile.avatarUrl': 1, - }; - }, - }), -}); + 'profile.avatarUrl': 1 + }, + limit: options?.limit || 20 + }); + } +}; Users.safeFields = { _id: 1, diff --git a/package-lock.json b/package-lock.json index fb236ca41..007d8b5da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,6 +39,11 @@ "lodash.uniq": "^4.5.0" } }, + "@kurkle/color": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", + "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==" + }, "@mapbox/node-pre-gyp": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", @@ -495,6 +500,14 @@ "traverse": ">=0.3.0 <0.4" } }, + "chart.js": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.0.tgz", + "integrity": "sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==", + "requires": { + "@kurkle/color": "^0.3.0" + } + }, "cheerio": { "version": "1.0.0-rc.10", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", diff --git a/package.json b/package.json index a7e60f0ab..18be6332c 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "ajv": "^6.12.6", "bcryptjs": "^2.4.3", "bson": "^4.5.2", + "chart.js": "^4.5.0", "dompurify": "^3.2.4", "es6-promise": "^4.2.4", "escape-string-regexp": "^5.0.0", @@ -47,6 +48,12 @@ "meteor-node-stubs": "^1.2.24", "minio": "^7.1.3", "moment": "^2.29.4", + "mongodb3legacy": "npm:mongodb@3.7.4", + "mongodb4legacy": "npm:mongodb@4.17.2", + "mongodb5legacy": "npm:mongodb@5.9.2", + "mongodb6legacy": "npm:mongodb@6.3.0", + "mongodb7legacy": "npm:mongodb@7.0.1", + "mongodb8legacy": "npm:mongodb@6.9.0", "os": "^0.1.2", "papaparse": "^5.3.1", "pretty-ms": "^7.0.1", @@ -54,12 +61,6 @@ "simpl-schema": "^3.4.6", "source-map-support": "^0.5.20", "to-buffer": "^1.2.1", - "uuid": "^8.3.2", - "mongodb3legacy": "npm:mongodb@3.7.4", - "mongodb4legacy": "npm:mongodb@4.17.2", - "mongodb5legacy": "npm:mongodb@5.9.2", - "mongodb6legacy": "npm:mongodb@6.3.0", - "mongodb7legacy": "npm:mongodb@7.0.1", - "mongodb8legacy": "npm:mongodb@6.9.0" + "uuid": "^8.3.2" } }