Documentation Index
Fetch the complete documentation index at: https://docs.db.matsushiba.co/llms.txt
Use this file to discover all available pages before exploring further.
Security
Implement robust security measures in MatsushibaDB to protect your data and applications from threats and vulnerabilities.Authentication
User Authentication
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const MatsushibaDB = require('matsushibadb');
const db = new MatsushibaDB('app.db');
// User registration with password hashing
async function registerUser(userData) {
try {
// Hash password
const saltRounds = 12;
const passwordHash = await bcrypt.hash(userData.password, saltRounds);
// Store user
const result = db.run(`
INSERT INTO users (username, email, password_hash, created_at)
VALUES (?, ?, ?, CURRENT_TIMESTAMP)
`, [userData.username, userData.email, passwordHash]);
return {
success: true,
userId: result.lastInsertRowid,
message: 'User registered successfully'
};
} catch (error) {
if (error.message.includes('UNIQUE constraint failed')) {
return { success: false, error: 'Username or email already exists' };
}
throw error;
}
}
// User login with password verification
async function loginUser(credentials) {
try {
const user = db.get(`
SELECT id, username, email, password_hash, status
FROM users
WHERE username = ? OR email = ?
`, [credentials.username, credentials.username]);
if (!user) {
return { success: false, error: 'Invalid credentials' };
}
if (user.status !== 'active') {
return { success: false, error: 'Account is not active' };
}
// Verify password
const isValidPassword = await bcrypt.compare(credentials.password, user.password_hash);
if (!isValidPassword) {
return { success: false, error: 'Invalid credentials' };
}
// Generate JWT token
const token = jwt.sign(
{
userId: user.id,
username: user.username,
email: user.email
},
process.env.JWT_SECRET,
{ expiresIn: '24h' }
);
// Update last login
db.run('UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE id = ?', [user.id]);
return {
success: true,
token: token,
user: {
id: user.id,
username: user.username,
email: user.email
}
};
} catch (error) {
throw error;
}
}
// Token verification middleware
function verifyToken(req, res, next) {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (error) {
return res.status(401).json({ error: 'Invalid token' });
}
}
Multi-Factor Authentication (MFA)
const speakeasy = require('speakeasy');
const QRCode = require('qrcode');
// Enable MFA for user
function enableMFA(userId) {
try {
// Generate secret
const secret = speakeasy.generateSecret({
name: 'MatsushibaDB App',
issuer: 'MatsushibaDB',
length: 32
});
// Store secret in database
db.run(`
INSERT OR REPLACE INTO user_mfa (user_id, secret, enabled, created_at)
VALUES (?, ?, 0, CURRENT_TIMESTAMP)
`, [userId, secret.base32]);
// Generate QR code
const qrCodeUrl = QRCode.toDataURL(secret.otpauth_url);
return {
success: true,
secret: secret.base32,
qrCode: qrCodeUrl,
manualEntryKey: secret.base32
};
} catch (error) {
throw error;
}
}
// Verify MFA token
function verifyMFAToken(userId, token) {
try {
const mfaRecord = db.get(`
SELECT secret FROM user_mfa
WHERE user_id = ? AND enabled = 1
`, [userId]);
if (!mfaRecord) {
return { success: false, error: 'MFA not enabled' };
}
const verified = speakeasy.totp.verify({
secret: mfaRecord.secret,
encoding: 'base32',
token: token,
window: 2 // Allow 2 time steps before/after
});
if (verified) {
// Log successful MFA verification
db.run(`
INSERT INTO security_logs (user_id, event_type, description, ip_address)
VALUES (?, ?, ?, ?)
`, [userId, 'mfa_success', 'MFA verification successful', req.ip]);
return { success: true, message: 'MFA verified' };
} else {
// Log failed MFA attempt
db.run(`
INSERT INTO security_logs (user_id, event_type, description, ip_address)
VALUES (?, ?, ?, ?)
`, [userId, 'mfa_failure', 'MFA verification failed', req.ip]);
return { success: false, error: 'Invalid MFA token' };
}
} catch (error) {
throw error;
}
}
// Complete login with MFA
async function loginWithMFA(credentials, mfaToken) {
try {
// First verify credentials
const loginResult = await loginUser(credentials);
if (!loginResult.success) {
return loginResult;
}
// Check if MFA is enabled
const mfaEnabled = db.get(`
SELECT enabled FROM user_mfa WHERE user_id = ?
`, [loginResult.user.id]);
if (mfaEnabled && mfaEnabled.enabled) {
// Verify MFA token
const mfaResult = verifyMFAToken(loginResult.user.id, mfaToken);
if (!mfaResult.success) {
return mfaResult;
}
}
return loginResult;
} catch (error) {
throw error;
}
}
Authorization
Role-Based Access Control (RBAC)
// Create roles and permissions
function initializeRBAC() {
// Create roles
const roles = [
{ name: 'admin', description: 'Administrator with full access' },
{ name: 'moderator', description: 'Moderator with limited admin access' },
{ name: 'user', description: 'Regular user' },
{ name: 'guest', description: 'Guest user with read-only access' }
];
roles.forEach(role => {
db.run(`
INSERT OR IGNORE INTO roles (name, description, created_at)
VALUES (?, ?, CURRENT_TIMESTAMP)
`, [role.name, role.description]);
});
// Create permissions
const permissions = [
{ name: 'read_users', description: 'Read user data' },
{ name: 'write_users', description: 'Create/update users' },
{ name: 'delete_users', description: 'Delete users' },
{ name: 'read_posts', description: 'Read posts' },
{ name: 'write_posts', description: 'Create/update posts' },
{ name: 'delete_posts', description: 'Delete posts' },
{ name: 'moderate_content', description: 'Moderate content' },
{ name: 'admin_access', description: 'Full admin access' }
];
permissions.forEach(permission => {
db.run(`
INSERT OR IGNORE INTO permissions (name, description, created_at)
VALUES (?, ?, CURRENT_TIMESTAMP)
`, [permission.name, permission.description]);
});
// Assign permissions to roles
const rolePermissions = [
// Admin gets all permissions
{ role: 'admin', permissions: ['read_users', 'write_users', 'delete_users', 'read_posts', 'write_posts', 'delete_posts', 'moderate_content', 'admin_access'] },
// Moderator gets moderation and content permissions
{ role: 'moderator', permissions: ['read_users', 'read_posts', 'write_posts', 'moderate_content'] },
// User gets basic permissions
{ role: 'user', permissions: ['read_posts', 'write_posts'] },
// Guest gets read-only permissions
{ role: 'guest', permissions: ['read_posts'] }
];
rolePermissions.forEach(({ role, permissions }) => {
const roleId = db.get('SELECT id FROM roles WHERE name = ?', [role]).id;
permissions.forEach(permissionName => {
const permissionId = db.get('SELECT id FROM permissions WHERE name = ?', [permissionName]).id;
db.run(`
INSERT OR IGNORE INTO role_permissions (role_id, permission_id)
VALUES (?, ?)
`, [roleId, permissionId]);
});
});
}
// Assign role to user
function assignUserRole(userId, roleName) {
try {
const role = db.get('SELECT id FROM roles WHERE name = ?', [roleName]);
if (!role) {
return { success: false, error: 'Role not found' };
}
db.run(`
INSERT OR REPLACE INTO user_roles (user_id, role_id, assigned_at)
VALUES (?, ?, CURRENT_TIMESTAMP)
`, [userId, role.id]);
return { success: true, message: `Role ${roleName} assigned to user` };
} catch (error) {
throw error;
}
}
// Check user permission
function hasPermission(userId, permissionName) {
try {
const result = db.get(`
SELECT COUNT(*) as count
FROM user_roles ur
JOIN role_permissions rp ON ur.role_id = rp.role_id
JOIN permissions p ON rp.permission_id = p.id
WHERE ur.user_id = ? AND p.name = ?
`, [userId, permissionName]);
return result.count > 0;
} catch (error) {
return false;
}
}
// Authorization middleware
function requirePermission(permission) {
return (req, res, next) => {
if (!req.user) {
return res.status(401).json({ error: 'Authentication required' });
}
if (!hasPermission(req.user.userId, permission)) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
next();
};
}
Data Encryption
Database-Level Encryption
const crypto = require('crypto');
// Encryption configuration
const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY || crypto.randomBytes(32);
const ALGORITHM = 'aes-256-gcm';
// Encrypt sensitive data
function encryptData(text) {
try {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipher(ALGORITHM, ENCRYPTION_KEY);
cipher.setAAD(Buffer.from('matsushiba-db', 'utf8'));
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return {
encrypted: encrypted,
iv: iv.toString('hex'),
authTag: authTag.toString('hex')
};
} catch (error) {
throw new Error('Encryption failed: ' + error.message);
}
}
// Decrypt sensitive data
function decryptData(encryptedData) {
try {
const decipher = crypto.createDecipher(ALGORITHM, ENCRYPTION_KEY);
decipher.setAAD(Buffer.from('matsushiba-db', 'utf8'));
decipher.setAuthTag(Buffer.from(encryptedData.authTag, 'hex'));
let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
} catch (error) {
throw new Error('Decryption failed: ' + error.message);
}
}
// Store encrypted sensitive data
function storeSensitiveData(userId, sensitiveData) {
try {
const encrypted = encryptData(JSON.stringify(sensitiveData));
db.run(`
INSERT INTO sensitive_data (user_id, encrypted_data, iv, auth_tag, created_at)
VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)
`, [userId, encrypted.encrypted, encrypted.iv, encrypted.authTag]);
return { success: true, message: 'Sensitive data stored securely' };
} catch (error) {
throw error;
}
}
// Retrieve and decrypt sensitive data
function getSensitiveData(userId) {
try {
const record = db.get(`
SELECT encrypted_data, iv, auth_tag
FROM sensitive_data
WHERE user_id = ?
`, [userId]);
if (!record) {
return { success: false, error: 'No sensitive data found' };
}
const decrypted = decryptData({
encrypted: record.encrypted_data,
iv: record.iv,
authTag: record.auth_tag
});
return {
success: true,
data: JSON.parse(decrypted)
};
} catch (error) {
throw error;
}
}
Security Monitoring
Audit Logging
// Security event logging
function logSecurityEvent(userId, eventType, description, metadata = {}) {
try {
db.run(`
INSERT INTO security_logs (
user_id, event_type, description, metadata,
ip_address, user_agent, created_at
) VALUES (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
`, [
userId,
eventType,
description,
JSON.stringify(metadata),
req?.ip || 'unknown',
req?.get('User-Agent') || 'unknown'
]);
} catch (error) {
console.error('Failed to log security event:', error);
}
}
// Failed login attempt tracking
function trackFailedLogin(username, ipAddress) {
try {
// Log failed attempt
logSecurityEvent(null, 'login_failed', `Failed login attempt for ${username}`, {
username: username,
ip_address: ipAddress
});
// Check for suspicious activity
const recentFailures = db.get(`
SELECT COUNT(*) as count
FROM security_logs
WHERE event_type = 'login_failed'
AND ip_address = ?
AND created_at > datetime('now', '-15 minutes')
`, [ipAddress]);
if (recentFailures.count >= 5) {
// Block IP temporarily
db.run(`
INSERT INTO blocked_ips (ip_address, reason, blocked_until)
VALUES (?, ?, datetime('now', '+1 hour'))
`, [ipAddress, 'Multiple failed login attempts']);
logSecurityEvent(null, 'ip_blocked', `IP ${ipAddress} blocked due to suspicious activity`);
}
} catch (error) {
console.error('Failed to track failed login:', error);
}
}
// Security monitoring dashboard
function getSecurityMetrics() {
try {
const metrics = {};
// Failed login attempts in last 24 hours
metrics.failedLogins = db.get(`
SELECT COUNT(*) as count
FROM security_logs
WHERE event_type = 'login_failed'
AND created_at > datetime('now', '-24 hours')
`).count;
// Active blocked IPs
metrics.blockedIPs = db.get(`
SELECT COUNT(*) as count
FROM blocked_ips
WHERE blocked_until > datetime('now')
`).count;
// MFA usage
metrics.mfaUsage = db.get(`
SELECT COUNT(*) as count
FROM security_logs
WHERE event_type = 'mfa_success'
AND created_at > datetime('now', '-24 hours')
`).count;
// Recent security events
metrics.recentEvents = db.all(`
SELECT event_type, description, created_at
FROM security_logs
WHERE created_at > datetime('now', '-1 hour')
ORDER BY created_at DESC
LIMIT 10
`);
return metrics;
} catch (error) {
throw error;
}
}
Security Best Practices
Input Validation and Sanitization
const validator = require('validator');
const xss = require('xss');
// Input validation
function validateInput(data, rules) {
const errors = [];
for (const [field, rule] of Object.entries(rules)) {
const value = data[field];
if (rule.required && (!value || value.trim() === '')) {
errors.push(`${field} is required`);
continue;
}
if (value) {
if (rule.type === 'email' && !validator.isEmail(value)) {
errors.push(`${field} must be a valid email`);
}
if (rule.type === 'password' && !validator.isStrongPassword(value)) {
errors.push(`${field} must be a strong password`);
}
if (rule.minLength && value.length < rule.minLength) {
errors.push(`${field} must be at least ${rule.minLength} characters`);
}
if (rule.maxLength && value.length > rule.maxLength) {
errors.push(`${field} must be no more than ${rule.maxLength} characters`);
}
}
}
return errors;
}
// Sanitize input
function sanitizeInput(input) {
if (typeof input === 'string') {
// Remove XSS
return xss(input, {
whiteList: {},
stripIgnoreTag: true,
stripIgnoreTagBody: ['script']
});
}
if (typeof input === 'object' && input !== null) {
const sanitized = {};
for (const [key, value] of Object.entries(input)) {
sanitized[key] = sanitizeInput(value);
}
return sanitized;
}
return input;
}
// Secure user creation
function createUserSecurely(userData) {
try {
// Validate input
const validationRules = {
username: { required: true, minLength: 3, maxLength: 50 },
email: { required: true, type: 'email' },
password: { required: true, type: 'password' }
};
const validationErrors = validateInput(userData, validationRules);
if (validationErrors.length > 0) {
return { success: false, errors: validationErrors };
}
// Sanitize input
const sanitizedData = sanitizeInput(userData);
// Hash password
const passwordHash = bcrypt.hashSync(sanitizedData.password, 12);
// Store user
const result = db.run(`
INSERT INTO users (username, email, password_hash, created_at)
VALUES (?, ?, ?, CURRENT_TIMESTAMP)
`, [sanitizedData.username, sanitizedData.email, passwordHash]);
return {
success: true,
userId: result.lastInsertRowid,
message: 'User created successfully'
};
} catch (error) {
throw error;
}
}
Security Configuration
Database Security Settings
-- Enable foreign key constraints
PRAGMA foreign_keys = ON;
-- Set secure journal mode
PRAGMA journal_mode = WAL;
-- Enable secure delete
PRAGMA secure_delete = ON;
-- Set synchronous mode for data integrity
PRAGMA synchronous = FULL;
-- Enable query-only mode for read operations
PRAGMA query_only = ON;
-- Set cache size for performance
PRAGMA cache_size = 2000;
-- Enable integrity check
PRAGMA integrity_check;
Security Tables Schema
-- Users table with security fields
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username TEXT UNIQUE NOT NULL,
email TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
status TEXT DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'suspended', 'banned')),
failed_login_attempts INTEGER DEFAULT 0,
last_login DATETIME,
password_changed_at DATETIME DEFAULT CURRENT_TIMESTAMP,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Roles table
CREATE TABLE roles (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
description TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Permissions table
CREATE TABLE permissions (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
description TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- User roles junction table
CREATE TABLE user_roles (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
role_id INTEGER NOT NULL,
assigned_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE,
UNIQUE(user_id, role_id)
);
-- Role permissions junction table
CREATE TABLE role_permissions (
id INTEGER PRIMARY KEY,
role_id INTEGER NOT NULL,
permission_id INTEGER NOT NULL,
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE,
FOREIGN KEY (permission_id) REFERENCES permissions(id) ON DELETE CASCADE,
UNIQUE(role_id, permission_id)
);
-- MFA table
CREATE TABLE user_mfa (
id INTEGER PRIMARY KEY,
user_id INTEGER UNIQUE NOT NULL,
secret TEXT NOT NULL,
enabled BOOLEAN DEFAULT 0,
backup_codes TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
-- Security logs table
CREATE TABLE security_logs (
id INTEGER PRIMARY KEY,
user_id INTEGER,
event_type TEXT NOT NULL,
description TEXT NOT NULL,
metadata TEXT,
ip_address TEXT,
user_agent TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
);
-- Blocked IPs table
CREATE TABLE blocked_ips (
id INTEGER PRIMARY KEY,
ip_address TEXT UNIQUE NOT NULL,
reason TEXT NOT NULL,
blocked_until DATETIME NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Sensitive data table
CREATE TABLE sensitive_data (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
encrypted_data TEXT NOT NULL,
iv TEXT,
auth_tag TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
Best Practices
Encrypt Sensitive Data
Encrypt sensitive data at rest and in transit using strong encryption algorithms.
Security is a critical aspect of any database application. Always implement multiple layers of security and regularly audit your security measures to ensure they remain effective.