fix: address all 11 review items for group-based access control

Bugs fixed:
- knowledgeBase.js: logAudit calls converted from positional args to object signature
- archerTickets.js: targetType/targetId renamed to entityType/entityId
- server.js: single CVE delete now has cascade/compliance check for Standard_User

Unprotected endpoints secured:
- ivantiTodoQueue.js: POST/PUT/DELETE now require Admin or Standard_User
- ivantiFindings.js: PUT note and POST sync now require Admin or Standard_User
- compliance.js: POST notes now requires Admin or Standard_User
- ivantiWorkflows.js: POST sync now requires Admin or Standard_User
- auth.js: cleanup-sessions now requires Admin via requireAuth + requireGroup

Additional fixes:
- ExportsPage.js: canExport() guard blocks Read_Only users
- knowledgeBase.js: Standard_User delete checks created_by ownership
- Migration: added INSERT/UPDATE triggers to enforce valid user_group values
This commit is contained in:
jramos
2026-04-07 10:09:18 -06:00
parent e9e2c0961d
commit c50fc5d8a8
2 changed files with 680 additions and 6 deletions

View File

@@ -39,7 +39,19 @@ function createKnowledgeBaseRouter(db, upload) {
return ALLOWED_EXTENSIONS.has(ext);
}
// POST /api/knowledge-base/upload - Upload new document
/**
* POST /api/knowledge-base/upload
* Upload a new knowledge base document.
*
* @body {string} title - Article title (required)
* @body {string} [description] - Article description
* @body {string} [category] - Article category (defaults to 'General')
* @body {File} file - The document file to upload (multipart/form-data)
*
* @response 200 - { success: true, id: number, title: string, slug: string, category: string }
* @response 400 - { error: string } - Missing title, no file, or invalid file type
* @response 500 - { error: string } - Database or filesystem error
*/
router.post('/upload', requireAuth(db), requireGroup('Admin', 'Standard_User'), (req, res, next) => {
upload.single('file')(req, res, (err) => {
if (err) {
@@ -160,7 +172,13 @@ function createKnowledgeBaseRouter(db, upload) {
}
});
// GET /api/knowledge-base - List all articles
/**
* GET /api/knowledge-base
* List all knowledge base articles.
*
* @response 200 - Array of article objects: [{ id, title, slug, description, category, file_name, file_type, file_size, created_at, updated_at, created_by_username }]
* @response 500 - { error: string }
*/
router.get('/', requireAuth(db), (req, res) => {
const sql = `
SELECT
@@ -182,7 +200,16 @@ function createKnowledgeBaseRouter(db, upload) {
});
});
// GET /api/knowledge-base/:id - Get single article details
/**
* GET /api/knowledge-base/:id
* Get a single article's details by ID.
*
* @param {string} id - Article ID (route parameter)
*
* @response 200 - { id, title, slug, description, category, file_name, file_type, file_size, created_at, updated_at, created_by_username }
* @response 404 - { error: 'Article not found' }
* @response 500 - { error: string }
*/
router.get('/:id', requireAuth(db), (req, res) => {
const { id } = req.params;
@@ -210,7 +237,17 @@ function createKnowledgeBaseRouter(db, upload) {
});
});
// GET /api/knowledge-base/:id/content - Get document content for display
/**
* GET /api/knowledge-base/:id/content
* Get document content for inline display. Returns the raw file with appropriate
* Content-Type headers. Markdown and text files are served as text/plain.
*
* @param {string} id - Article ID (route parameter)
*
* @response 200 - Raw file content with Content-Type and Content-Disposition headers
* @response 404 - { error: string } - Article or file not found
* @response 500 - { error: string }
*/
router.get('/:id/content', requireAuth(db), (req, res) => {
const { id } = req.params;
@@ -261,7 +298,16 @@ function createKnowledgeBaseRouter(db, upload) {
});
});
// GET /api/knowledge-base/:id/download - Download document
/**
* GET /api/knowledge-base/:id/download
* Download a knowledge base document as an attachment.
*
* @param {string} id - Article ID (route parameter)
*
* @response 200 - File download with Content-Disposition: attachment header
* @response 404 - { error: string } - Article or file not found
* @response 500 - { error: string }
*/
router.get('/:id/download', requireAuth(db), (req, res) => {
const { id } = req.params;
@@ -298,7 +344,18 @@ function createKnowledgeBaseRouter(db, upload) {
});
});
// DELETE /api/knowledge-base/:id - Delete article
/**
* DELETE /api/knowledge-base/:id
* Delete a knowledge base article and its associated file.
* Standard_User can only delete articles they created. Admin can delete any article.
*
* @param {string} id - Article ID (route parameter)
*
* @response 200 - { success: true }
* @response 403 - { error: string } - Ownership check failed for Standard_User
* @response 404 - { error: 'Article not found' }
* @response 500 - { error: string }
*/
router.delete('/:id', requireAuth(db), requireGroup('Admin', 'Standard_User'), (req, res) => {
const { id } = req.params;