Fix jwt-token
This commit is contained in:
@@ -25,6 +25,9 @@ COPY . .
|
||||
# Create logs directory
|
||||
RUN mkdir -p logs
|
||||
|
||||
# Create uploads directory for logos
|
||||
RUN mkdir -p uploads/logos
|
||||
|
||||
# Create non-root user
|
||||
RUN addgroup -g 1001 -S nodejs && \
|
||||
adduser -S nodejs -u 1001
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const express = require('express');
|
||||
const path = require('path');
|
||||
const cors = require('cors');
|
||||
const helmet = require('helmet');
|
||||
const morgan = require('morgan');
|
||||
@@ -73,6 +74,9 @@ app.use(cors({
|
||||
app.use(express.json({ limit: '10mb' }));
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
|
||||
// Serve uploaded files
|
||||
app.use('/uploads', express.static(path.join(__dirname, 'uploads')));
|
||||
|
||||
// API Debug logging (only when API_DEBUG=true)
|
||||
if (process.env.API_DEBUG === 'true') {
|
||||
console.log('🐛 API Debug logging enabled');
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
"passport-openidconnect": "^0.1.1",
|
||||
"ldapjs": "^3.0.7",
|
||||
"express-session": "^1.17.3",
|
||||
"umzug": "^3.4.0"
|
||||
"umzug": "^3.4.0",
|
||||
"multer": "^1.4.5-lts.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.0.1",
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
*/
|
||||
|
||||
const express = require('express');
|
||||
const multer = require('multer');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const router = express.Router();
|
||||
const { Tenant, User } = require('../models');
|
||||
const { authenticateToken } = require('../middleware/auth');
|
||||
@@ -13,6 +16,40 @@ const MultiTenantAuth = require('../middleware/multi-tenant-auth');
|
||||
// Initialize multi-tenant auth
|
||||
const multiAuth = new MultiTenantAuth();
|
||||
|
||||
// Configure multer for logo uploads
|
||||
const storage = multer.diskStorage({
|
||||
destination: function (req, file, cb) {
|
||||
const uploadDir = path.join(__dirname, '../uploads/logos');
|
||||
// Create directory if it doesn't exist
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true });
|
||||
}
|
||||
cb(null, uploadDir);
|
||||
},
|
||||
filename: function (req, file, cb) {
|
||||
// Use tenant ID and timestamp for unique filename
|
||||
const tenantId = req.user.tenant_id;
|
||||
const ext = path.extname(file.originalname);
|
||||
const filename = `tenant-${tenantId}-${Date.now()}${ext}`;
|
||||
cb(null, filename);
|
||||
}
|
||||
});
|
||||
|
||||
const upload = multer({
|
||||
storage: storage,
|
||||
limits: {
|
||||
fileSize: 5 * 1024 * 1024 // 5MB limit
|
||||
},
|
||||
fileFilter: function (req, file, cb) {
|
||||
// Accept only image files
|
||||
if (file.mimetype.startsWith('image/')) {
|
||||
cb(null, true);
|
||||
} else {
|
||||
cb(new Error('Only image files are allowed'), false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* GET /tenant/info
|
||||
* Get current tenant information
|
||||
@@ -71,6 +108,83 @@ router.get('/info', authenticateToken, requirePermissions(['tenant.view']), asyn
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /tenant/logo-upload
|
||||
* Upload tenant logo (branding admin or higher)
|
||||
*/
|
||||
router.post('/logo-upload', authenticateToken, requirePermissions(['branding.edit']), upload.single('logo'), async (req, res) => {
|
||||
try {
|
||||
if (!req.file) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'No file uploaded'
|
||||
});
|
||||
}
|
||||
|
||||
// Determine tenant from request
|
||||
const tenantId = await multiAuth.determineTenant(req);
|
||||
if (!tenantId) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Invalid tenant'
|
||||
});
|
||||
}
|
||||
|
||||
// Get tenant
|
||||
const tenant = await Tenant.findByPk(tenantId);
|
||||
if (!tenant) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Tenant not found'
|
||||
});
|
||||
}
|
||||
|
||||
// Clean up old logo file if it exists
|
||||
if (tenant.branding?.logo_url) {
|
||||
const oldLogoPath = tenant.branding.logo_url.replace('/uploads/logos/', '');
|
||||
const oldFilePath = path.join(__dirname, '../uploads/logos', oldLogoPath);
|
||||
if (fs.existsSync(oldFilePath)) {
|
||||
fs.unlinkSync(oldFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
// Create logo URL
|
||||
const logoUrl = `/uploads/logos/${req.file.filename}`;
|
||||
|
||||
// Update tenant branding with new logo
|
||||
const updatedBranding = {
|
||||
...tenant.branding,
|
||||
logo_url: logoUrl
|
||||
};
|
||||
|
||||
await tenant.update({ branding: updatedBranding });
|
||||
|
||||
console.log(`✅ Tenant "${tenantId}" logo uploaded by user "${req.user.username}"`);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Logo uploaded successfully',
|
||||
data: {
|
||||
logo_url: logoUrl,
|
||||
branding: updatedBranding
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error uploading logo:', error);
|
||||
|
||||
// Clean up uploaded file on error
|
||||
if (req.file && fs.existsSync(req.file.path)) {
|
||||
fs.unlinkSync(req.file.path);
|
||||
}
|
||||
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Failed to upload logo'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* PUT /tenant/branding
|
||||
* Update tenant branding (branding admin or higher)
|
||||
|
||||
Reference in New Issue
Block a user