Files
SuperCharged-Claude-Code-Up…/services/database.js
uroma 3e72d6c0ba fix: add input validation and fix unique constraint
Fixed code quality issues from Task 2 review:

1. Added ID validation in PUT endpoint:
   - Validates req.params.id is a valid positive integer
   - Returns 400 for invalid IDs (non-numeric, negative, zero, decimals)
   - Prevents SQL injection attempts

2. Added path validation in POST and PUT endpoints:
   - Validates projectPath is absolute path
   - Normalizes and resolves paths
   - Detects and blocks path traversal attempts (e.g., ../../../etc)
   - Returns 400 for invalid paths

3. Fixed UNIQUE constraint in database schema:
   - Removed UNIQUE constraint from name column
   - Allows creating projects with same name as deleted projects
   - Application-level duplicate checking remains for active projects
   - Added table migration to drop and recreate schema

Files modified:
- server.js: Added validateProjectId() and validateProjectPath() helpers
- services/database.js: Removed UNIQUE constraint, added migration

All validation tested and working correctly.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-19 16:51:46 +00:00

79 lines
1.9 KiB
JavaScript

const Database = require('better-sqlite3');
const path = require('path');
/**
* Initialize SQLite database with projects schema
*/
function initializeDatabase() {
// Database file in project root
const dbPath = path.join(__dirname, '..', 'database.sqlite');
// Initialize database connection
const db = new Database(dbPath);
// Enable WAL mode for better concurrency
db.pragma('journal_mode = WAL');
// Drop existing table to remove UNIQUE constraint (migration)
// In production, use proper migrations instead
try {
db.exec(`DROP TABLE IF EXISTS projects`);
console.log('Dropped old projects table for schema migration');
} catch (error) {
// Table might not exist, which is fine
}
// Create projects table
db.exec(`
CREATE TABLE IF NOT EXISTS projects (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
description TEXT,
icon TEXT DEFAULT '📁',
color TEXT DEFAULT '#4a9eff',
path TEXT NOT NULL,
createdAt TEXT NOT NULL,
lastActivity TEXT NOT NULL,
deletedAt TEXT NULL
)
`);
// Create index on deletedAt for efficient soft-delete queries
db.exec(`
CREATE INDEX IF NOT EXISTS idx_projects_deletedAt ON projects(deletedAt)
`);
// Create index on name for efficient name lookups
db.exec(`
CREATE INDEX IF NOT EXISTS idx_projects_name ON projects(name)
`);
return db;
}
/**
* Initialize database with requireAuth check
*/
let dbInstance = null;
function getDatabase() {
if (!dbInstance) {
try {
dbInstance = initializeDatabase();
console.log('Database initialized successfully');
} catch (error) {
console.error('Failed to initialize database:', error);
throw error;
}
}
return dbInstance;
}
// Initialize database immediately
const db = getDatabase();
module.exports = {
db,
getDatabase
};