u
This commit is contained in:
@@ -4,6 +4,7 @@ import multer from 'multer';
|
||||
import JSZip from 'jszip';
|
||||
import env from '../../config/env.js';
|
||||
import * as db from '../../db/company.js';
|
||||
import { requireCompanyAdmin } from '../../db/companyuser.js';
|
||||
import * as googleAuth from '../../db/googleAuth.js';
|
||||
import { clearCachedUser } from '../middleware/auth.js';
|
||||
import { emit } from '../sse.js';
|
||||
@@ -499,13 +500,25 @@ export function register(app, basePath = '') {
|
||||
|
||||
app.post(
|
||||
`${basePath}/company/import`,
|
||||
async (req, res, next) => {
|
||||
try {
|
||||
const companyId = requireSelectedCompany(req);
|
||||
await requireCompanyAdmin(req.user.id, companyId);
|
||||
next();
|
||||
} catch (error) {
|
||||
const status = companyErrorStatus(error);
|
||||
return res.status(status).json({ error: error.message });
|
||||
}
|
||||
},
|
||||
uploadCompanyImportFile,
|
||||
async (req, res) => {
|
||||
let companyId;
|
||||
try {
|
||||
companyId = requireSelectedCompany(req);
|
||||
await requireCompanyAdmin(req.user.id, companyId);
|
||||
} catch (error) {
|
||||
return res.status(error.statusCode || 400).json({ error: error.message });
|
||||
const status = companyErrorStatus(error);
|
||||
return res.status(status).json({ error: error.message });
|
||||
}
|
||||
|
||||
if (activeImportsByCompany.has(companyId)) {
|
||||
@@ -968,7 +981,7 @@ export function register(app, basePath = '') {
|
||||
}
|
||||
|
||||
try {
|
||||
const company = await db.updateCompany(parsedId.companyId, body);
|
||||
const company = await db.updateCompany(parsedId.companyId, body, req.user.id);
|
||||
emit('company', { companyId: parsedId.companyId, data: { companyId: parsedId.companyId } });
|
||||
res.status(200).json({ company });
|
||||
} catch (error) {
|
||||
@@ -989,10 +1002,14 @@ export function register(app, basePath = '') {
|
||||
}
|
||||
|
||||
try {
|
||||
await db.deleteCompany(parsedId.companyId);
|
||||
await db.deleteCompany(parsedId.companyId, req.user.id);
|
||||
clearCompanyPrinters(parsedId.companyId);
|
||||
res.sendStatus(204);
|
||||
} catch (error) {
|
||||
const status = companyErrorStatus(error);
|
||||
if (status !== 500) {
|
||||
return res.status(status).json({ error: error.message });
|
||||
}
|
||||
console.error('Delete company failed:', error);
|
||||
res.status(500).json({ error: 'Failed to delete company' });
|
||||
}
|
||||
|
||||
@@ -2,10 +2,13 @@ import fs from 'fs';
|
||||
import path from 'path';
|
||||
import multer from 'multer';
|
||||
import { emit } from '../sse.js';
|
||||
import { requireCompanyAdmin } from '../../db/companyuser.js';
|
||||
import {
|
||||
prepareVfs,
|
||||
resolveVfsRoot,
|
||||
isReadOnlyDatabasePath,
|
||||
isProtectedAdminVfsPath,
|
||||
directoryContainsProtectedAdminVfsFile,
|
||||
getMimeType,
|
||||
restoreDefaultSkills,
|
||||
restoreDefaultApplets,
|
||||
@@ -586,6 +589,8 @@ export function register(app, basePath = '') {
|
||||
: '';
|
||||
const uploaded = [];
|
||||
|
||||
const parsedEntries = [];
|
||||
let touchesProtected = false;
|
||||
for (const f of files) {
|
||||
const origName = (f.originalname || 'upload').replace(/[\0\\]/g, '/');
|
||||
const relPath = targetDir ? `${targetDir}/${origName}` : origName;
|
||||
@@ -596,6 +601,18 @@ export function register(app, basePath = '') {
|
||||
|
||||
const absPath = path.resolve(vfsRoot, parsed.name);
|
||||
if (!absPath.startsWith(vfsRoot)) continue;
|
||||
|
||||
if (isProtectedAdminVfsPath(parsed.name)) {
|
||||
touchesProtected = true;
|
||||
}
|
||||
parsedEntries.push({ f, parsed, absPath });
|
||||
}
|
||||
|
||||
if (touchesProtected) {
|
||||
await requireCompanyAdmin(req.user.id, selected.companyId);
|
||||
}
|
||||
|
||||
for (const { f, parsed, absPath } of parsedEntries) {
|
||||
fs.mkdirSync(path.dirname(absPath), { recursive: true });
|
||||
fs.writeFileSync(absPath, f.buffer);
|
||||
|
||||
@@ -815,6 +832,15 @@ export function register(app, basePath = '') {
|
||||
return res.status(404).json({ error: 'Source file or directory not found' });
|
||||
}
|
||||
|
||||
if (
|
||||
isProtectedAdminVfsPath(parsedOld.name) ||
|
||||
isProtectedAdminVfsPath(parsedNew.name) ||
|
||||
directoryContainsProtectedAdminVfsFile(absOld) ||
|
||||
directoryContainsProtectedAdminVfsFile(absNew)
|
||||
) {
|
||||
await requireCompanyAdmin(req.user.id, selected.companyId);
|
||||
}
|
||||
|
||||
fs.mkdirSync(path.dirname(absNew), { recursive: true });
|
||||
fs.renameSync(absOld, absNew);
|
||||
|
||||
@@ -961,6 +987,9 @@ export function register(app, basePath = '') {
|
||||
}
|
||||
|
||||
try {
|
||||
if (isProtectedAdminVfsPath(parsed.name)) {
|
||||
await requireCompanyAdmin(req.user.id, selected.companyId);
|
||||
}
|
||||
const vfsRoot = await resolveVfsRoot(req.user.id);
|
||||
const absPath = path.resolve(vfsRoot, parsed.name);
|
||||
if (!absPath.startsWith(vfsRoot)) {
|
||||
@@ -1058,6 +1087,9 @@ export function register(app, basePath = '') {
|
||||
}
|
||||
|
||||
try {
|
||||
if (isProtectedAdminVfsPath(parsed.name)) {
|
||||
await requireCompanyAdmin(req.user.id, selected.companyId);
|
||||
}
|
||||
const vfsRoot = await resolveVfsRoot(req.user.id);
|
||||
const absPath = path.resolve(vfsRoot, parsed.name);
|
||||
if (!absPath.startsWith(vfsRoot)) {
|
||||
@@ -1066,6 +1098,9 @@ export function register(app, basePath = '') {
|
||||
if (!fs.existsSync(absPath)) {
|
||||
return res.status(404).json({ error: 'File not found' });
|
||||
}
|
||||
if (directoryContainsProtectedAdminVfsFile(absPath)) {
|
||||
await requireCompanyAdmin(req.user.id, selected.companyId);
|
||||
}
|
||||
const stat = fs.statSync(absPath);
|
||||
if (stat.isDirectory()) {
|
||||
fs.rmSync(absPath, { recursive: true, force: true });
|
||||
|
||||
Reference in New Issue
Block a user