Fix Bug: WeKan v8.50 WRITABLE_PATH.
Thanks to snowsky and xet7 ! Fixes #6242
This commit is contained in:
1 parent
60657c6e94
commit
edc6b18b5f
6 files changed
+124
-2
No files matched your search
@@ -1,14 +1,33 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { FilesCollection } from 'meteor/ostrio:files';
|
||||
import { generateUniversalAttachmentUrl } from '/models/lib/universalUrlGenerator';
|
||||
import path from 'path';
|
||||
|
||||
// XXX Enforce a schema for the Attachments FilesCollection
|
||||
// see: https://github.com/VeliovGroup/Meteor-Files/wiki/Schema
|
||||
|
||||
// Compute storage path:
|
||||
// - Docker (WRITABLE_PATH=/data): /data/files/attachments
|
||||
// - Snap (WRITABLE_PATH=$SNAP_COMMON/files): $SNAP_COMMON/files/attachments
|
||||
const computeAttachmentStoragePath = () => {
|
||||
const basePath = process.env.WRITABLE_PATH || process.cwd();
|
||||
const endsWithFiles = basePath.endsWith('/files') || basePath.endsWith('\\files');
|
||||
if (endsWithFiles) {
|
||||
// Snap: WRITABLE_PATH already includes /files
|
||||
return basePath + '/attachments';
|
||||
} else {
|
||||
// Docker & Dev: append /files/attachments
|
||||
return basePath + '/files/attachments';
|
||||
}
|
||||
};
|
||||
|
||||
const storagePath = Meteor.isServer ? computeAttachmentStoragePath() : 'assets/app/uploads/attachments';
|
||||
|
||||
const Attachments = new FilesCollection({
|
||||
debug: false, // Change to `true` for debugging
|
||||
collectionName: 'attachments',
|
||||
allowClientCode: true,
|
||||
storagePath: storagePath,
|
||||
namingFunction(opts) {
|
||||
let filenameWithoutExtension = ""
|
||||
let fileId = "";
|
||||
|
||||
@@ -22,7 +22,15 @@ let attachmentUploadMimeTypes = [];
|
||||
let attachmentUploadSize = 0;
|
||||
|
||||
const attachmentBucket = createBucket('attachments');
|
||||
const storagePath = path.join(process.env.WRITABLE_PATH || process.cwd(), 'files', 'attachments');
|
||||
|
||||
// Compute storage path:
|
||||
// - Docker (WRITABLE_PATH=/data): /data/files/attachments
|
||||
// - Snap (WRITABLE_PATH=$SNAP_COMMON/files): $SNAP_COMMON/files/attachments
|
||||
const basePath = process.env.WRITABLE_PATH || process.cwd();
|
||||
const endsWithFiles = basePath.endsWith('/files') || basePath.endsWith('\\files');
|
||||
const storagePath = endsWithFiles
|
||||
? path.join(basePath, 'attachments')
|
||||
: path.join(basePath, 'files', 'attachments');
|
||||
|
||||
if (process.env.ATTACHMENTS_UPLOAD_MIME_TYPES) {
|
||||
attachmentUploadMimeTypes = process.env.ATTACHMENTS_UPLOAD_MIME_TYPES.split(',');
|
||||
|
||||
@@ -1,16 +1,35 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { FilesCollection } from 'meteor/ostrio:files';
|
||||
import { generateUniversalAvatarUrl } from '/models/lib/universalUrlGenerator';
|
||||
import path from 'path';
|
||||
|
||||
const { filesize } = require('filesize');
|
||||
const getTAPi18n = () => require('/imports/i18n').TAPi18n;
|
||||
|
||||
let avatarsUploadSize = 72000;
|
||||
|
||||
// Compute storage path:
|
||||
// - Docker (WRITABLE_PATH=/data): /data/files/avatars
|
||||
// - Snap (WRITABLE_PATH=$SNAP_COMMON/files): $SNAP_COMMON/files/avatars
|
||||
const computeAvatarStoragePath = () => {
|
||||
const basePath = process.env.WRITABLE_PATH || process.cwd();
|
||||
const endsWithFiles = basePath.endsWith('/files') || basePath.endsWith('\\files');
|
||||
if (endsWithFiles) {
|
||||
// Snap: WRITABLE_PATH already includes /files
|
||||
return basePath + '/avatars';
|
||||
} else {
|
||||
// Docker & Dev: append /files/avatars
|
||||
return basePath + '/files/avatars';
|
||||
}
|
||||
};
|
||||
|
||||
const storagePath = Meteor.isServer ? computeAvatarStoragePath() : 'assets/app/uploads/avatars';
|
||||
|
||||
const Avatars = new FilesCollection({
|
||||
debug: false, // Change to `true` for debugging
|
||||
collectionName: 'avatars',
|
||||
allowClientCode: true,
|
||||
storagePath: storagePath,
|
||||
namingFunction(opts) {
|
||||
let filenameWithoutExtension = ""
|
||||
let fileId = "";
|
||||
|
||||
@@ -40,7 +40,15 @@ if (process.env.AVATARS_UPLOAD_EXTERNAL_PROGRAM) {
|
||||
}
|
||||
|
||||
const avatarsBucket = createBucket('avatars');
|
||||
const storagePath = path.join(process.env.WRITABLE_PATH || process.cwd(), 'files', 'avatars');
|
||||
|
||||
// Compute storage path:
|
||||
// - Docker (WRITABLE_PATH=/data): /data/files/avatars
|
||||
// - Snap (WRITABLE_PATH=$SNAP_COMMON/files): $SNAP_COMMON/files/avatars
|
||||
const basePath = process.env.WRITABLE_PATH || process.cwd();
|
||||
const endsWithFiles = basePath.endsWith('/files') || basePath.endsWith('\\files');
|
||||
const storagePath = endsWithFiles
|
||||
? path.join(basePath, 'avatars')
|
||||
: path.join(basePath, 'files', 'avatars');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// File store strategy factory
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
// Loaded by server/main.js after bootstrap (collectionHelpers) completes.
|
||||
// ============================================================================
|
||||
|
||||
// ****IMPORTANT**** Initialize upload directories BEFORE models are loaded
|
||||
// This ensures ostrio:files can create necessary directories without permission errors
|
||||
import '/server/initializeDirs';
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// 0. API middleware & auth routes (must register before model routes)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// ============================================================================
|
||||
// Initialize Upload Directories
|
||||
// Runs at server startup before models are loaded to ensure ostrio:files
|
||||
// can create necessary upload directories without permission errors.
|
||||
// ============================================================================
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
// Compute upload subdirectory path:
|
||||
// - On Docker (WRITABLE_PATH=/data): /data/files/attachments, /data/files/avatars
|
||||
// - On Snap (WRITABLE_PATH=$SNAP_COMMON/files): $SNAP_COMMON/files/attachments, $SNAP_COMMON/files/avatars
|
||||
// - On dev (WRITABLE_PATH=..): ../files/attachments, ../files/avatars
|
||||
//
|
||||
// Snap already appends '/files' to WRITABLE_PATH, so we detect and handle that case.
|
||||
function getUploadPaths() {
|
||||
const basePath = process.env.WRITABLE_PATH || process.cwd();
|
||||
|
||||
// Check if basePath already ends with '/files' (Snap case)
|
||||
const endsWithFiles = basePath.endsWith('/files') || basePath.endsWith('\\files');
|
||||
|
||||
if (endsWithFiles) {
|
||||
// Snap: WRITABLE_PATH is already $SNAP_COMMON/files, so append subdirectories directly
|
||||
return {
|
||||
attachments: path.join(basePath, 'attachments'),
|
||||
avatars: path.join(basePath, 'avatars'),
|
||||
};
|
||||
} else {
|
||||
// Docker & Dev: WRITABLE_PATH is /data or .., so append /files/{subdir}
|
||||
return {
|
||||
attachments: path.join(basePath, 'files', 'attachments'),
|
||||
avatars: path.join(basePath, 'files', 'avatars'),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const uploadPaths = getUploadPaths();
|
||||
const dirsToCreate = [uploadPaths.attachments, uploadPaths.avatars];
|
||||
|
||||
dirsToCreate.forEach(dirPath => {
|
||||
try {
|
||||
// Create directory recursively with proper permissions (0o755)
|
||||
// Ignore error if it already exists
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
fs.mkdirSync(dirPath, { recursive: true, mode: 0o755 });
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.info(`[initializeDirs] Created directory: ${dirPath}`);
|
||||
}
|
||||
} else {
|
||||
// Verify the directory is writable
|
||||
try {
|
||||
fs.accessSync(dirPath, fs.constants.W_OK);
|
||||
if (process.env.DEBUG === 'true') {
|
||||
console.info(`[initializeDirs] Directory exists and is writable: ${dirPath}`);
|
||||
}
|
||||
} catch (accessError) {
|
||||
console.warn(`[initializeDirs] WARNING: Directory exists but may not be writable: ${dirPath}`, accessError.message);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[initializeDirs] FAILED to initialize directory: ${dirPath}`, error.message);
|
||||
throw new Error(`Cannot create or access upload directory: ${dirPath}\n${error.message}`);
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user