mirror of
https://github.com/bckelley/cgm-remote-monitor.git
synced 2026-08-24 03:14:12 -05:00
137 lines
3.6 KiB
JavaScript
137 lines
3.6 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* Test Database Safety Guards (GAP-SYNC-046)
|
|
*
|
|
* Prevents destructive operations (deleteMany, drop) from running
|
|
* against production databases when NODE_ENV is not 'test'.
|
|
*
|
|
* Usage in tests:
|
|
* const { requireTestEnv, guardedDeleteMany } = require('./fixtures/test-guard');
|
|
*
|
|
* before(function() {
|
|
* requireTestEnv(); // Throws if NODE_ENV !== 'test'
|
|
* });
|
|
*
|
|
* afterEach(function(done) {
|
|
* guardedDeleteMany(collection, {}, done);
|
|
* });
|
|
*/
|
|
|
|
const ALLOWED_TEST_DB_PATTERNS = [
|
|
/nightscout.*test/i,
|
|
/test.*nightscout/i,
|
|
/localhost.*test/i,
|
|
/127\.0\.0\.1.*test/i
|
|
];
|
|
|
|
/**
|
|
* Throws if NODE_ENV is not 'test'
|
|
* Call this at the start of test files that perform destructive operations
|
|
*/
|
|
function requireTestEnv() {
|
|
if (process.env.NODE_ENV !== 'test') {
|
|
throw new Error(
|
|
'SAFETY: Tests require NODE_ENV=test to prevent accidental production data loss.\n' +
|
|
'Current NODE_ENV: ' + (process.env.NODE_ENV || '(not set)') + '\n' +
|
|
'Fix: Set NODE_ENV=test in your test environment or use ci.test.env'
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validates that MONGO_CONNECTION points to a test database
|
|
*/
|
|
function requireTestDatabase() {
|
|
const mongoConn = process.env.MONGO_CONNECTION || '';
|
|
const isTestDb = ALLOWED_TEST_DB_PATTERNS.some(pattern => pattern.test(mongoConn));
|
|
|
|
if (!isTestDb && process.env.NODE_ENV === 'test') {
|
|
console.warn(
|
|
'WARNING: MONGO_CONNECTION does not appear to be a test database: ' + mongoConn + '\n' +
|
|
'Expected patterns: ' + ALLOWED_TEST_DB_PATTERNS.map(p => p.toString()).join(', ')
|
|
);
|
|
}
|
|
|
|
return isTestDb;
|
|
}
|
|
|
|
/**
|
|
* Guarded deleteMany - only executes if NODE_ENV=test
|
|
* @param {Collection} collection - MongoDB collection
|
|
* @param {Object} filter - Delete filter (usually {})
|
|
* @param {Function} callback - Callback when complete
|
|
*/
|
|
function guardedDeleteMany(collection, filter, callback) {
|
|
if (process.env.NODE_ENV !== 'test') {
|
|
const err = new Error(
|
|
'SAFETY: deleteMany({}) blocked - NODE_ENV is not "test".\n' +
|
|
'This prevents accidental deletion of production data.'
|
|
);
|
|
if (callback) {
|
|
return callback(err);
|
|
}
|
|
throw err;
|
|
}
|
|
|
|
// Safe to proceed
|
|
const promise = collection.deleteMany(filter);
|
|
if (callback) {
|
|
promise.then(
|
|
function onSuccess(result) { callback(null, result); },
|
|
function onError(err) { callback(err); }
|
|
);
|
|
}
|
|
return promise;
|
|
}
|
|
|
|
/**
|
|
* Guarded drop - only executes if NODE_ENV=test
|
|
* @param {Collection} collection - MongoDB collection
|
|
* @param {Function} callback - Callback when complete
|
|
*/
|
|
function guardedDrop(collection, callback) {
|
|
if (process.env.NODE_ENV !== 'test') {
|
|
const err = new Error(
|
|
'SAFETY: drop() blocked - NODE_ENV is not "test".\n' +
|
|
'This prevents accidental deletion of production data.'
|
|
);
|
|
if (callback) {
|
|
return callback(err);
|
|
}
|
|
throw err;
|
|
}
|
|
|
|
const promise = collection.drop();
|
|
if (callback) {
|
|
promise.then(
|
|
function onSuccess(result) { callback(null, result); },
|
|
function onError(err) { callback(err); }
|
|
);
|
|
}
|
|
return promise;
|
|
}
|
|
|
|
/**
|
|
* Check test environment at module load time
|
|
* Prints warning if not in test mode
|
|
*/
|
|
function checkTestEnvironment() {
|
|
if (process.env.NODE_ENV !== 'test') {
|
|
console.warn('\n⚠️ WARNING: NODE_ENV is not "test"');
|
|
console.warn(' Destructive test operations may be blocked.\n');
|
|
}
|
|
}
|
|
|
|
// Check on require
|
|
checkTestEnvironment();
|
|
|
|
module.exports = {
|
|
requireTestEnv,
|
|
requireTestDatabase,
|
|
guardedDeleteMany,
|
|
guardedDrop,
|
|
checkTestEnvironment,
|
|
ALLOWED_TEST_DB_PATTERNS
|
|
};
|