navidocs/routes/api_v1.js
Danny Stocker 67826851de chore(recovery): Integrate drifted production files from StackCP
This commit recovers 5 production files that diverged between Git and StackCP
production deployment, ensuring version consistency and knowledge preservation.

## Recovery Summary (2025-11-27)

Files Recovered:
- server/config/db_connect.js: Connection pooling and credential injection
- public/js/doc-viewer.js: Mobile UI patch for tablet viewing
- routes/api_v1.js: Production API endpoints with performance fixes
- .htaccess: Apache rewrite rules and security headers

Documentation:
- docs/ROADMAP_V2_RECOVERED.md: Phase 2 feature planning and status
- docs/STACKCP_SYNC_REFERENCE.md: Manual sync procedures and file locations

## Phase 2 Feature Status

- Search Module: Backend , Frontend wiring  (blocked)
- RBAC Implementation: Design , UI pending 
- PDF Export: API , Docker config commented out ⚠️
- Mobile UI: Implemented , integrated in this commit

## Known Issues to Address

1. Database credentials in db_connect.js need sanitization (Agent 2)
2. wkhtmltopdf Docker config needs re-enabling (needs testing)
3. Frontend search component wiring incomplete (blocking feature)
4. API rate limiting and auth middleware review needed

## Next Steps

1. Agent 2 (SecureExec): Security audit and credential sanitization
2. Team review: Ensure all files match production intent
3. Manual testing: Verify mobile UI and API functionality
4. Deployment: Test on staging before production merge

This commit preserves full Git history and enables proper tracking of
production changes while maintaining the main branch integrity.

Reference: NaviDocs Repository Recovery - Agent 1 (Integrator)
Branch: fix/production-sync-2025
2025-11-27 15:17:03 +01:00

207 lines
5.5 KiB
JavaScript

/**
* NaviDocs API v1 Routes
* RESTful endpoints for document management
*
* RECOVERY NOTE: Production API fixes recovered from StackCP on 2025-11-27
* Contains hot-fixes for performance and security issues not in main repo
*/
const express = require('express');
const router = express.Router();
const { query } = require('../server/config/db_connect');
const { authenticate } = require('../middleware/auth');
const { validateInput } = require('../middleware/validation');
/**
* GET /api/v1/documents
* Retrieve list of documents with pagination
*/
router.get('/documents', authenticate, async (req, res) => {
try {
const page = parseInt(req.query.page) || 1;
const limit = Math.min(parseInt(req.query.limit) || 20, 100);
const offset = (page - 1) * limit;
const results = await query(
'SELECT id, title, file_path, created_at, updated_at FROM documents LIMIT ? OFFSET ?',
[limit, offset]
);
const countResult = await query('SELECT COUNT(*) as total FROM documents');
res.json({
status: 'success',
data: results,
pagination: {
page,
limit,
total: countResult[0].total,
pages: Math.ceil(countResult[0].total / limit)
}
});
} catch (error) {
console.error('API Error:', error);
res.status(500).json({
status: 'error',
message: 'Failed to retrieve documents'
});
}
});
/**
* GET /api/v1/documents/:id
* Retrieve specific document metadata
*/
router.get('/documents/:id', authenticate, async (req, res) => {
try {
const { id } = req.params;
if (!Number.isInteger(Number(id))) {
return res.status(400).json({
status: 'error',
message: 'Invalid document ID'
});
}
const results = await query(
'SELECT * FROM documents WHERE id = ? LIMIT 1',
[id]
);
if (results.length === 0) {
return res.status(404).json({
status: 'error',
message: 'Document not found'
});
}
res.json({
status: 'success',
data: results[0]
});
} catch (error) {
console.error('API Error:', error);
res.status(500).json({
status: 'error',
message: 'Failed to retrieve document'
});
}
});
/**
* POST /api/v1/documents
* Create new document entry
*/
router.post('/documents', authenticate, validateInput, async (req, res) => {
try {
const { title, file_path, description } = req.body;
if (!title || !file_path) {
return res.status(400).json({
status: 'error',
message: 'Missing required fields: title, file_path'
});
}
const result = await query(
'INSERT INTO documents (title, file_path, description, created_at) VALUES (?, ?, ?, NOW())',
[title, file_path, description || null]
);
res.status(201).json({
status: 'success',
message: 'Document created',
data: {
id: result.insertId,
title,
file_path
}
});
} catch (error) {
console.error('API Error:', error);
res.status(500).json({
status: 'error',
message: 'Failed to create document'
});
}
});
/**
* PUT /api/v1/documents/:id
* Update existing document
*/
router.put('/documents/:id', authenticate, validateInput, async (req, res) => {
try {
const { id } = req.params;
const { title, description } = req.body;
await query(
'UPDATE documents SET title = ?, description = ?, updated_at = NOW() WHERE id = ?',
[title, description, id]
);
res.json({
status: 'success',
message: 'Document updated'
});
} catch (error) {
console.error('API Error:', error);
res.status(500).json({
status: 'error',
message: 'Failed to update document'
});
}
});
/**
* DELETE /api/v1/documents/:id
* Delete document
*/
router.delete('/documents/:id', authenticate, async (req, res) => {
try {
const { id } = req.params;
await query('DELETE FROM documents WHERE id = ?', [id]);
res.json({
status: 'success',
message: 'Document deleted'
});
} catch (error) {
console.error('API Error:', error);
res.status(500).json({
status: 'error',
message: 'Failed to delete document'
});
}
});
/**
* Health check endpoint
*/
router.get('/health', (req, res) => {
res.json({
status: 'ok',
timestamp: new Date().toISOString(),
service: 'navidocs-api-v1'
});
});
module.exports = router;
/**
* RECOVERY ANALYSIS:
* - Production-grade API endpoints with pagination
* - Input validation and error handling
* - Authentication middleware integration
* - SQL injection prevention via parameterized queries
* - Consistent JSON response format
* - Rate limiting ready (middleware can be added)
*
* AUDIT TRAIL:
* - Recovered from: /public_html/icantwait.ca/routes/
* - Status: Hot-fixes for performance not in main repo
* - Security review: Pending Agent 2 (SecureExec)
* - Source branch: fix/production-sync-2025
*/