This commit is contained in:
seb
2026-11-03 06:20:06 +01:00
parent 24563964a6
commit da785da2dd
21 changed files with 273 additions and 29 deletions

View File

@@ -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' });
}

View File

@@ -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 });