mirror of
https://github.com/wekan/wekan.git
synced 2026-03-04 04:40:16 +01:00
Update ReactiveCache call sites to use async/await for Meteor 3.0
Part 3 of ReactiveCache async migration: - Add await before all ReactiveCache.getX() calls - Make functions containing ReactiveCache calls async - Convert forEach/map/filter loops with async callbacks to for...of - Update model helpers, Meteor methods, JsonRoutes handlers - Update collection hooks (.before/.after insert/update/remove) - Update .allow() callbacks to async Files updated across models/ and server/ directories: - Model files: cards, boards, lists, swimlanes, activities, users, checklists, checklistItems, customFields, attachments, integrations, cardComments, settings files, creators, exporters, and more - Server files: publications, methods, notifications, routes, migrations
This commit is contained in:
parent
2f6e34c5f5
commit
71eb01e233
81 changed files with 2218 additions and 2148 deletions
|
|
@ -48,7 +48,7 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
// Upload attachment endpoint
|
||||
WebApp.connectHandlers.use('/api/attachment/upload', (req, res, next) => {
|
||||
WebApp.connectHandlers.use('/api/attachment/upload', async (req, res, next) => {
|
||||
if (req.method !== 'POST') {
|
||||
return next();
|
||||
}
|
||||
|
|
@ -75,11 +75,11 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
req.on('end', () => {
|
||||
req.on('end', async () => {
|
||||
if (bodyComplete) return; // Already processed
|
||||
bodyComplete = true;
|
||||
clearTimeout(timeout);
|
||||
|
||||
|
||||
try {
|
||||
const data = JSON.parse(body);
|
||||
const { boardId, swimlaneId, listId, cardId, fileData, fileName, fileType, storageBackend } = data;
|
||||
|
|
@ -90,12 +90,12 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
// Check if user has permission to modify the card
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
const card = await ReactiveCache.getCard(cardId);
|
||||
if (!card) {
|
||||
return sendErrorResponse(res, 404, 'Card not found');
|
||||
}
|
||||
|
||||
const board = ReactiveCache.getBoard(boardId);
|
||||
const board = await ReactiveCache.getBoard(boardId);
|
||||
if (!board) {
|
||||
return sendErrorResponse(res, 404, 'Board not found');
|
||||
}
|
||||
|
|
@ -207,7 +207,7 @@ if (Meteor.isServer) {
|
|||
});
|
||||
|
||||
// Download attachment endpoint
|
||||
WebApp.connectHandlers.use('/api/attachment/download/([^/]+)', (req, res, next) => {
|
||||
WebApp.connectHandlers.use('/api/attachment/download/([^/]+)', async (req, res, next) => {
|
||||
if (req.method !== 'GET') {
|
||||
return next();
|
||||
}
|
||||
|
|
@ -217,13 +217,13 @@ if (Meteor.isServer) {
|
|||
const attachmentId = req.params[0];
|
||||
|
||||
// Get attachment
|
||||
const attachment = ReactiveCache.getAttachment(attachmentId);
|
||||
const attachment = await ReactiveCache.getAttachment(attachmentId);
|
||||
if (!attachment) {
|
||||
return sendErrorResponse(res, 404, 'Attachment not found');
|
||||
}
|
||||
|
||||
// Check permissions
|
||||
const board = ReactiveCache.getBoard(attachment.meta.boardId);
|
||||
const board = await ReactiveCache.getBoard(attachment.meta.boardId);
|
||||
if (!board || !board.isBoardMember(userId)) {
|
||||
return sendErrorResponse(res, 403, 'You do not have permission to access this attachment');
|
||||
}
|
||||
|
|
@ -267,7 +267,7 @@ if (Meteor.isServer) {
|
|||
});
|
||||
|
||||
// List attachments endpoint
|
||||
WebApp.connectHandlers.use('/api/attachment/list/([^/]+)/([^/]+)/([^/]+)/([^/]+)', (req, res, next) => {
|
||||
WebApp.connectHandlers.use('/api/attachment/list/([^/]+)/([^/]+)/([^/]+)/([^/]+)', async (req, res, next) => {
|
||||
if (req.method !== 'GET') {
|
||||
return next();
|
||||
}
|
||||
|
|
@ -280,14 +280,14 @@ if (Meteor.isServer) {
|
|||
const cardId = req.params[3];
|
||||
|
||||
// Check permissions
|
||||
const board = ReactiveCache.getBoard(boardId);
|
||||
const board = await ReactiveCache.getBoard(boardId);
|
||||
if (!board || !board.isBoardMember(userId)) {
|
||||
return sendErrorResponse(res, 403, 'You do not have permission to access this board');
|
||||
}
|
||||
|
||||
// If cardId is provided, verify it belongs to the board
|
||||
if (cardId && cardId !== 'null') {
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
const card = await ReactiveCache.getCard(cardId);
|
||||
if (!card || card.boardId !== boardId) {
|
||||
return sendErrorResponse(res, 404, 'Card not found or does not belong to the specified board');
|
||||
}
|
||||
|
|
@ -307,7 +307,7 @@ if (Meteor.isServer) {
|
|||
query['meta.cardId'] = cardId;
|
||||
}
|
||||
|
||||
const attachments = ReactiveCache.getAttachments(query);
|
||||
const attachments = await ReactiveCache.getAttachments(query);
|
||||
|
||||
const attachmentList = attachments.map(attachment => {
|
||||
const strategy = fileStoreStrategyFactory.getFileStrategy(attachment, 'original');
|
||||
|
|
@ -337,7 +337,7 @@ if (Meteor.isServer) {
|
|||
});
|
||||
|
||||
// Copy attachment endpoint
|
||||
WebApp.connectHandlers.use('/api/attachment/copy', (req, res, next) => {
|
||||
WebApp.connectHandlers.use('/api/attachment/copy', async (req, res, next) => {
|
||||
if (req.method !== 'POST') {
|
||||
return next();
|
||||
}
|
||||
|
|
@ -350,10 +350,10 @@ if (Meteor.isServer) {
|
|||
|
||||
try {
|
||||
const userId = authenticateApiRequest(req);
|
||||
|
||||
|
||||
let body = '';
|
||||
let bodyComplete = false;
|
||||
|
||||
|
||||
req.on('data', chunk => {
|
||||
body += chunk.toString();
|
||||
if (body.length > 10 * 1024 * 1024) { // 10MB limit for metadata
|
||||
|
|
@ -362,35 +362,35 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
req.on('end', () => {
|
||||
req.on('end', async () => {
|
||||
if (bodyComplete) return;
|
||||
bodyComplete = true;
|
||||
clearTimeout(timeout);
|
||||
|
||||
|
||||
try {
|
||||
const data = JSON.parse(body);
|
||||
const { attachmentId, targetBoardId, targetSwimlaneId, targetListId, targetCardId } = data;
|
||||
|
||||
// Get source attachment
|
||||
const sourceAttachment = ReactiveCache.getAttachment(attachmentId);
|
||||
const sourceAttachment = await ReactiveCache.getAttachment(attachmentId);
|
||||
if (!sourceAttachment) {
|
||||
return sendErrorResponse(res, 404, 'Source attachment not found');
|
||||
}
|
||||
|
||||
// Check source permissions
|
||||
const sourceBoard = ReactiveCache.getBoard(sourceAttachment.meta.boardId);
|
||||
const sourceBoard = await ReactiveCache.getBoard(sourceAttachment.meta.boardId);
|
||||
if (!sourceBoard || !sourceBoard.isBoardMember(userId)) {
|
||||
return sendErrorResponse(res, 403, 'You do not have permission to access the source attachment');
|
||||
}
|
||||
|
||||
// Check target permissions
|
||||
const targetBoard = ReactiveCache.getBoard(targetBoardId);
|
||||
const targetBoard = await ReactiveCache.getBoard(targetBoardId);
|
||||
if (!targetBoard || !targetBoard.isBoardMember(userId)) {
|
||||
return sendErrorResponse(res, 403, 'You do not have permission to modify the target card');
|
||||
}
|
||||
|
||||
// Verify that the target card belongs to the target board
|
||||
const targetCard = ReactiveCache.getCard(targetCardId);
|
||||
const targetCard = await ReactiveCache.getCard(targetCardId);
|
||||
if (!targetCard) {
|
||||
return sendErrorResponse(res, 404, 'Target card not found');
|
||||
}
|
||||
|
|
@ -493,7 +493,7 @@ if (Meteor.isServer) {
|
|||
});
|
||||
|
||||
// Move attachment endpoint
|
||||
WebApp.connectHandlers.use('/api/attachment/move', (req, res, next) => {
|
||||
WebApp.connectHandlers.use('/api/attachment/move', async (req, res, next) => {
|
||||
if (req.method !== 'POST') {
|
||||
return next();
|
||||
}
|
||||
|
|
@ -506,10 +506,10 @@ if (Meteor.isServer) {
|
|||
|
||||
try {
|
||||
const userId = authenticateApiRequest(req);
|
||||
|
||||
|
||||
let body = '';
|
||||
let bodyComplete = false;
|
||||
|
||||
|
||||
req.on('data', chunk => {
|
||||
body += chunk.toString();
|
||||
if (body.length > 10 * 1024 * 1024) {
|
||||
|
|
@ -518,35 +518,35 @@ if (Meteor.isServer) {
|
|||
}
|
||||
});
|
||||
|
||||
req.on('end', () => {
|
||||
req.on('end', async () => {
|
||||
if (bodyComplete) return;
|
||||
bodyComplete = true;
|
||||
clearTimeout(timeout);
|
||||
|
||||
|
||||
try {
|
||||
const data = JSON.parse(body);
|
||||
const { attachmentId, targetBoardId, targetSwimlaneId, targetListId, targetCardId } = data;
|
||||
|
||||
// Get source attachment
|
||||
const sourceAttachment = ReactiveCache.getAttachment(attachmentId);
|
||||
const sourceAttachment = await ReactiveCache.getAttachment(attachmentId);
|
||||
if (!sourceAttachment) {
|
||||
return sendErrorResponse(res, 404, 'Source attachment not found');
|
||||
}
|
||||
|
||||
// Check source permissions
|
||||
const sourceBoard = ReactiveCache.getBoard(sourceAttachment.meta.boardId);
|
||||
const sourceBoard = await ReactiveCache.getBoard(sourceAttachment.meta.boardId);
|
||||
if (!sourceBoard || !sourceBoard.isBoardMember(userId)) {
|
||||
return sendErrorResponse(res, 403, 'You do not have permission to access the source attachment');
|
||||
}
|
||||
|
||||
// Check target permissions
|
||||
const targetBoard = ReactiveCache.getBoard(targetBoardId);
|
||||
const targetBoard = await ReactiveCache.getBoard(targetBoardId);
|
||||
if (!targetBoard || !targetBoard.isBoardMember(userId)) {
|
||||
return sendErrorResponse(res, 403, 'You do not have permission to modify the target card');
|
||||
}
|
||||
|
||||
// Verify that the target card belongs to the target board
|
||||
const targetCard = ReactiveCache.getCard(targetCardId);
|
||||
const targetCard = await ReactiveCache.getCard(targetCardId);
|
||||
if (!targetCard) {
|
||||
return sendErrorResponse(res, 404, 'Target card not found');
|
||||
}
|
||||
|
|
@ -610,7 +610,7 @@ if (Meteor.isServer) {
|
|||
});
|
||||
|
||||
// Delete attachment endpoint
|
||||
WebApp.connectHandlers.use('/api/attachment/delete/([^/]+)', (req, res, next) => {
|
||||
WebApp.connectHandlers.use('/api/attachment/delete/([^/]+)', async (req, res, next) => {
|
||||
if (req.method !== 'DELETE') {
|
||||
return next();
|
||||
}
|
||||
|
|
@ -620,13 +620,13 @@ if (Meteor.isServer) {
|
|||
const attachmentId = req.params[0];
|
||||
|
||||
// Get attachment
|
||||
const attachment = ReactiveCache.getAttachment(attachmentId);
|
||||
const attachment = await ReactiveCache.getAttachment(attachmentId);
|
||||
if (!attachment) {
|
||||
return sendErrorResponse(res, 404, 'Attachment not found');
|
||||
}
|
||||
|
||||
// Check permissions
|
||||
const board = ReactiveCache.getBoard(attachment.meta.boardId);
|
||||
const board = await ReactiveCache.getBoard(attachment.meta.boardId);
|
||||
if (!board || !board.isBoardMember(userId)) {
|
||||
return sendErrorResponse(res, 403, 'You do not have permission to delete this attachment');
|
||||
}
|
||||
|
|
@ -646,7 +646,7 @@ if (Meteor.isServer) {
|
|||
});
|
||||
|
||||
// Get attachment info endpoint
|
||||
WebApp.connectHandlers.use('/api/attachment/info/([^/]+)', (req, res, next) => {
|
||||
WebApp.connectHandlers.use('/api/attachment/info/([^/]+)', async (req, res, next) => {
|
||||
if (req.method !== 'GET') {
|
||||
return next();
|
||||
}
|
||||
|
|
@ -656,13 +656,13 @@ if (Meteor.isServer) {
|
|||
const attachmentId = req.params[0];
|
||||
|
||||
// Get attachment
|
||||
const attachment = ReactiveCache.getAttachment(attachmentId);
|
||||
const attachment = await ReactiveCache.getAttachment(attachmentId);
|
||||
if (!attachment) {
|
||||
return sendErrorResponse(res, 404, 'Attachment not found');
|
||||
}
|
||||
|
||||
// Check permissions
|
||||
const board = ReactiveCache.getBoard(attachment.meta.boardId);
|
||||
const board = await ReactiveCache.getBoard(attachment.meta.boardId);
|
||||
if (!board || !board.isBoardMember(userId)) {
|
||||
return sendErrorResponse(res, 403, 'You do not have permission to access this attachment');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,14 +13,14 @@ import path from 'path';
|
|||
|
||||
if (Meteor.isServer) {
|
||||
// Handle avatar file downloads
|
||||
WebApp.connectHandlers.use('/cdn/storage/avatars/([^/]+)', (req, res, next) => {
|
||||
WebApp.connectHandlers.use('/cdn/storage/avatars/([^/]+)', async (req, res, next) => {
|
||||
if (req.method !== 'GET') {
|
||||
return next();
|
||||
}
|
||||
|
||||
try {
|
||||
const fileName = req.params[0];
|
||||
|
||||
|
||||
if (!fileName) {
|
||||
res.writeHead(400);
|
||||
res.end('Invalid avatar file name');
|
||||
|
|
@ -29,7 +29,7 @@ if (Meteor.isServer) {
|
|||
|
||||
// Extract file ID from filename (format: fileId-original-filename)
|
||||
const fileId = fileName.split('-original-')[0];
|
||||
|
||||
|
||||
if (!fileId) {
|
||||
res.writeHead(400);
|
||||
res.end('Invalid avatar file format');
|
||||
|
|
@ -37,7 +37,7 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
// Get avatar file from database
|
||||
const avatar = ReactiveCache.getAvatar(fileId);
|
||||
const avatar = await ReactiveCache.getAvatar(fileId);
|
||||
if (!avatar) {
|
||||
res.writeHead(404);
|
||||
res.end('Avatar not found');
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ function buildContentDispositionHeader(disposition, sanitizedFilename) {
|
|||
|
||||
if (Meteor.isServer) {
|
||||
// Handle legacy attachment downloads
|
||||
WebApp.connectHandlers.use('/cfs/files/attachments', (req, res, next) => {
|
||||
WebApp.connectHandlers.use('/cfs/files/attachments', async (req, res, next) => {
|
||||
const attachmentId = req.url.split('/').pop();
|
||||
|
||||
if (!attachmentId) {
|
||||
|
|
@ -78,7 +78,7 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
// Check permissions
|
||||
const board = ReactiveCache.getBoard(attachment.meta.boardId);
|
||||
const board = await ReactiveCache.getBoard(attachment.meta.boardId);
|
||||
if (!board) {
|
||||
res.writeHead(404);
|
||||
res.end('Board not found');
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ if (Meteor.isServer) {
|
|||
* - Else if avatar's owner belongs to at least one public board -> allow
|
||||
* - Otherwise -> deny
|
||||
*/
|
||||
function isAuthorizedForAvatar(req, avatar) {
|
||||
async function isAuthorizedForAvatar(req, avatar) {
|
||||
try {
|
||||
if (!avatar) return false;
|
||||
|
||||
|
|
@ -180,7 +180,7 @@ if (Meteor.isServer) {
|
|||
const q = parseQuery(req);
|
||||
const boardId = q.boardId || q.board || q.b;
|
||||
if (boardId) {
|
||||
const board = ReactiveCache.getBoard(boardId);
|
||||
const board = await ReactiveCache.getBoard(boardId);
|
||||
if (board && board.isPublic && board.isPublic()) return true;
|
||||
|
||||
// If private board is specified, require membership of requester
|
||||
|
|
@ -297,7 +297,7 @@ if (Meteor.isServer) {
|
|||
* - Public boards: allow
|
||||
* - Private boards: require valid user who is a member
|
||||
*/
|
||||
function isAuthorizedForBoard(req, board) {
|
||||
async function isAuthorizedForBoard(req, board) {
|
||||
try {
|
||||
if (!board) return false;
|
||||
if (board.isPublic && board.isPublic()) return true;
|
||||
|
|
@ -389,14 +389,14 @@ if (Meteor.isServer) {
|
|||
* Serve attachments from new Meteor-Files structure
|
||||
* Route: /cdn/storage/attachments/{fileId} or /cdn/storage/attachments/{fileId}/original/{filename}
|
||||
*/
|
||||
WebApp.connectHandlers.use('/cdn/storage/attachments', (req, res, next) => {
|
||||
WebApp.connectHandlers.use('/cdn/storage/attachments', async (req, res, next) => {
|
||||
if (req.method !== 'GET') {
|
||||
return next();
|
||||
}
|
||||
|
||||
try {
|
||||
const fileId = extractFirstIdFromUrl(req, '/cdn/storage/attachments');
|
||||
|
||||
|
||||
if (!fileId) {
|
||||
res.writeHead(400);
|
||||
res.end('Invalid attachment file ID');
|
||||
|
|
@ -412,7 +412,7 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
// Check permissions
|
||||
const board = ReactiveCache.getBoard(attachment.meta.boardId);
|
||||
const board = await ReactiveCache.getBoard(attachment.meta.boardId);
|
||||
if (!board) {
|
||||
res.writeHead(404);
|
||||
res.end('Board not found');
|
||||
|
|
@ -420,7 +420,7 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
// Enforce cookie/header/query-based auth for private boards
|
||||
if (!isAuthorizedForBoard(req, board)) {
|
||||
if (!(await isAuthorizedForBoard(req, board))) {
|
||||
res.writeHead(403);
|
||||
res.end('Access denied');
|
||||
return;
|
||||
|
|
@ -476,14 +476,14 @@ if (Meteor.isServer) {
|
|||
* Serve avatars from new Meteor-Files structure
|
||||
* Route: /cdn/storage/avatars/{fileId} or /cdn/storage/avatars/{fileId}/original/{filename}
|
||||
*/
|
||||
WebApp.connectHandlers.use('/cdn/storage/avatars', (req, res, next) => {
|
||||
WebApp.connectHandlers.use('/cdn/storage/avatars', async (req, res, next) => {
|
||||
if (req.method !== 'GET') {
|
||||
return next();
|
||||
}
|
||||
|
||||
try {
|
||||
const fileId = extractFirstIdFromUrl(req, '/cdn/storage/avatars');
|
||||
|
||||
|
||||
if (!fileId) {
|
||||
res.writeHead(400);
|
||||
res.end('Invalid avatar file ID');
|
||||
|
|
@ -491,7 +491,7 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
// Get avatar from database
|
||||
const avatar = ReactiveCache.getAvatar(fileId);
|
||||
const avatar = await ReactiveCache.getAvatar(fileId);
|
||||
if (!avatar) {
|
||||
res.writeHead(404);
|
||||
res.end('Avatar not found');
|
||||
|
|
@ -499,7 +499,7 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
// Enforce visibility: avatars are public only in the context of public boards
|
||||
if (!isAuthorizedForAvatar(req, avatar)) {
|
||||
if (!(await isAuthorizedForAvatar(req, avatar))) {
|
||||
res.writeHead(403);
|
||||
res.end('Access denied');
|
||||
return;
|
||||
|
|
@ -541,14 +541,14 @@ if (Meteor.isServer) {
|
|||
* Serve legacy attachments from CollectionFS structure
|
||||
* Route: /cfs/files/attachments/{attachmentId}
|
||||
*/
|
||||
WebApp.connectHandlers.use('/cfs/files/attachments', (req, res, next) => {
|
||||
WebApp.connectHandlers.use('/cfs/files/attachments', async (req, res, next) => {
|
||||
if (req.method !== 'GET') {
|
||||
return next();
|
||||
}
|
||||
|
||||
try {
|
||||
const attachmentId = extractFirstIdFromUrl(req, '/cfs/files/attachments');
|
||||
|
||||
|
||||
if (!attachmentId) {
|
||||
res.writeHead(400);
|
||||
res.end('Invalid attachment ID');
|
||||
|
|
@ -564,7 +564,7 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
// Check permissions
|
||||
const board = ReactiveCache.getBoard(attachment.meta.boardId);
|
||||
const board = await ReactiveCache.getBoard(attachment.meta.boardId);
|
||||
if (!board) {
|
||||
res.writeHead(404);
|
||||
res.end('Board not found');
|
||||
|
|
@ -572,7 +572,7 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
// Enforce cookie/header/query-based auth for private boards
|
||||
if (!isAuthorizedForBoard(req, board)) {
|
||||
if (!(await isAuthorizedForBoard(req, board))) {
|
||||
res.writeHead(403);
|
||||
res.end('Access denied');
|
||||
return;
|
||||
|
|
@ -617,14 +617,14 @@ if (Meteor.isServer) {
|
|||
* Serve legacy avatars from CollectionFS structure
|
||||
* Route: /cfs/files/avatars/{avatarId}
|
||||
*/
|
||||
WebApp.connectHandlers.use('/cfs/files/avatars', (req, res, next) => {
|
||||
WebApp.connectHandlers.use('/cfs/files/avatars', async (req, res, next) => {
|
||||
if (req.method !== 'GET') {
|
||||
return next();
|
||||
}
|
||||
|
||||
try {
|
||||
const avatarId = extractFirstIdFromUrl(req, '/cfs/files/avatars');
|
||||
|
||||
|
||||
if (!avatarId) {
|
||||
res.writeHead(400);
|
||||
res.end('Invalid avatar ID');
|
||||
|
|
@ -632,8 +632,8 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
// Try to get avatar from database (new structure first)
|
||||
let avatar = ReactiveCache.getAvatar(avatarId);
|
||||
|
||||
let avatar = await ReactiveCache.getAvatar(avatarId);
|
||||
|
||||
// If not found in new structure, try to handle legacy format
|
||||
if (!avatar) {
|
||||
// For legacy avatars, we might need to handle different ID formats
|
||||
|
|
@ -644,7 +644,7 @@ if (Meteor.isServer) {
|
|||
}
|
||||
|
||||
// Enforce visibility for legacy avatars as well
|
||||
if (!isAuthorizedForAvatar(req, avatar)) {
|
||||
if (!(await isAuthorizedForAvatar(req, avatar))) {
|
||||
res.writeHead(403);
|
||||
res.end('Access denied');
|
||||
return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue