360 lines
11 KiB
JavaScript
360 lines
11 KiB
JavaScript
const { Sequelize } = require('sequelize');
|
||
const bcrypt = require('bcryptjs');
|
||
const runMigrations = require('./migrate');
|
||
|
||
// Import models from the main models index
|
||
const {
|
||
sequelize,
|
||
Device,
|
||
DroneDetection,
|
||
Heartbeat,
|
||
User,
|
||
AlertRule,
|
||
AlertLog,
|
||
Tenant
|
||
} = require('../models');
|
||
|
||
const setupDatabase = async () => {
|
||
try {
|
||
console.log('🚀 Starting database setup...\n');
|
||
|
||
// Test database connection
|
||
console.log('📡 Testing database connection...');
|
||
await sequelize.authenticate();
|
||
console.log('✅ Database connection established successfully.\n');
|
||
|
||
// Models are already initialized through the imports
|
||
console.log('<27> Models loaded and ready...');
|
||
|
||
// Run migrations first to create proper schema
|
||
console.log('🏗️ Running database migrations...');
|
||
await runMigrations();
|
||
console.log('✅ Database migrations completed successfully.\n');
|
||
|
||
// Check if sample data already exists
|
||
const existingTenants = await Tenant.count();
|
||
if (existingTenants > 0) {
|
||
console.log('📊 Sample data already exists, skipping data creation...\n');
|
||
console.log('🎉 Database setup completed successfully!\n');
|
||
await sequelize.close();
|
||
return;
|
||
}
|
||
|
||
// Create sample data
|
||
console.log('📊 Creating sample data...\n');
|
||
|
||
// Create default tenant
|
||
console.log('🏢 Creating default tenant...');
|
||
const defaultTenant = await Tenant.create({
|
||
name: 'Default Organization',
|
||
slug: 'default',
|
||
subscription_type: 'enterprise',
|
||
is_active: true,
|
||
auth_provider: 'local',
|
||
features: {
|
||
max_devices: -1,
|
||
max_users: -1,
|
||
api_rate_limit: 50000,
|
||
data_retention_days: -1,
|
||
features: ['all']
|
||
}
|
||
});
|
||
console.log(`✅ Default tenant created: ${defaultTenant.name}`);
|
||
|
||
// Create admin user
|
||
console.log('👤 Creating admin user...');
|
||
const adminUser = await User.create({
|
||
username: 'admin',
|
||
email: 'admin@example.com',
|
||
password_hash: await bcrypt.hash('admin123', 10),
|
||
role: 'admin',
|
||
tenant_id: defaultTenant.id
|
||
});
|
||
console.log(`✅ Admin user created: ${adminUser.username}`);
|
||
|
||
// Create operator user
|
||
console.log('👤 Creating operator user...');
|
||
const operatorUser = await User.create({
|
||
username: 'operator',
|
||
email: 'operator@example.com',
|
||
password_hash: await bcrypt.hash('operator123', 10),
|
||
role: 'operator',
|
||
tenant_id: defaultTenant.id
|
||
});
|
||
console.log(`✅ Operator user created: ${operatorUser.username}`);
|
||
|
||
// Create sample devices
|
||
console.log('📡 Creating sample devices...');
|
||
const devices = await Device.bulkCreate([
|
||
{
|
||
id: 'device-alpha-001',
|
||
name: 'Drone Detector Alpha',
|
||
location_description: 'Stockholm Central',
|
||
geo_lat: 59.3293,
|
||
geo_lon: 18.0686,
|
||
is_active: true,
|
||
is_approved: false,
|
||
last_heartbeat: new Date(),
|
||
heartbeat_interval: 300,
|
||
tenant_id: defaultTenant.id
|
||
},
|
||
{
|
||
id: 'device-beta-002',
|
||
name: 'Drone Detector Beta',
|
||
location_description: 'Gothenburg Port',
|
||
geo_lat: 57.7089,
|
||
geo_lon: 11.9746,
|
||
is_active: true,
|
||
is_approved: false,
|
||
last_heartbeat: new Date(),
|
||
heartbeat_interval: 300,
|
||
tenant_id: defaultTenant.id
|
||
},
|
||
{
|
||
id: 'device-gamma-003',
|
||
name: 'Drone Detector Gamma',
|
||
location_description: 'Malmö Airport',
|
||
geo_lat: 55.6050,
|
||
geo_lon: 13.0038,
|
||
is_active: false,
|
||
is_approved: false,
|
||
last_heartbeat: new Date(Date.now() - 2 * 60 * 60 * 1000), // 2 hours ago
|
||
heartbeat_interval: 300,
|
||
tenant_id: defaultTenant.id
|
||
}
|
||
]);
|
||
console.log(`✅ Created ${devices.length} sample devices`);
|
||
|
||
// Create sample heartbeats
|
||
console.log('💓 Creating sample heartbeats...');
|
||
const heartbeats = await Heartbeat.bulkCreate([
|
||
{
|
||
device_id: 'device-alpha-001',
|
||
status: 'active',
|
||
timestamp: new Date(),
|
||
tenant_id: defaultTenant.id
|
||
},
|
||
{
|
||
device_id: 'device-beta-002',
|
||
status: 'active',
|
||
timestamp: new Date(),
|
||
tenant_id: defaultTenant.id
|
||
}
|
||
]);
|
||
console.log(`✅ Created ${heartbeats.length} sample heartbeats`);
|
||
|
||
// Create sample drone detections
|
||
console.log('🚁 Creating sample drone detections...');
|
||
const detections = await DroneDetection.bulkCreate([
|
||
{
|
||
device_id: 'device-alpha-001',
|
||
geo_lat: 59.3293,
|
||
geo_lon: 18.0686,
|
||
device_timestamp: Math.floor(Date.now() / 1000),
|
||
drone_type: 0,
|
||
rssi: -45,
|
||
freq: 20,
|
||
drone_id: 1001,
|
||
timestamp: new Date(),
|
||
threat_level: 'high',
|
||
estimated_distance: 150,
|
||
requires_action: true,
|
||
tenant_id: defaultTenant.id
|
||
},
|
||
{
|
||
device_id: 'device-beta-002',
|
||
geo_lat: 57.7089,
|
||
geo_lon: 11.9746,
|
||
device_timestamp: Math.floor(Date.now() / 1000) - 3600,
|
||
drone_type: 1,
|
||
rssi: -52,
|
||
freq: 25,
|
||
drone_id: 1002,
|
||
timestamp: new Date(Date.now() - 60 * 60 * 1000),
|
||
threat_level: 'medium',
|
||
estimated_distance: 800,
|
||
requires_action: false,
|
||
tenant_id: defaultTenant.id
|
||
},
|
||
{
|
||
device_id: 'device-alpha-001',
|
||
geo_lat: 59.3295,
|
||
geo_lon: 18.0690,
|
||
device_timestamp: Math.floor(Date.now() / 1000) - 7200,
|
||
drone_type: 0,
|
||
rssi: -75,
|
||
freq: 22,
|
||
drone_id: 1003,
|
||
timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000),
|
||
threat_level: 'low',
|
||
estimated_distance: 2500,
|
||
requires_action: false,
|
||
tenant_id: defaultTenant.id
|
||
}
|
||
]);
|
||
console.log(`✅ Created ${detections.length} sample drone detections`);
|
||
|
||
// Create sample alert rules
|
||
console.log('🚨 Creating sample alert rules...');
|
||
const alertRules = await AlertRule.bulkCreate([
|
||
{
|
||
user_id: adminUser.id,
|
||
tenant_id: defaultTenant.id,
|
||
name: 'Critical Security Threat',
|
||
description: 'Immediate alert for critical and high threats to government facilities',
|
||
conditions: {
|
||
min_rssi: -55,
|
||
drone_types: [0, 1, 2],
|
||
time_window: 300,
|
||
min_detections: 1
|
||
},
|
||
actions: {
|
||
alert_channels: ['sms', 'email'],
|
||
sms_phone_number: '+46701234567',
|
||
priority: 'high'
|
||
},
|
||
is_active: true,
|
||
device_ids: [],
|
||
drone_types: [0, 1, 2],
|
||
min_rssi: -55,
|
||
max_rssi: null,
|
||
frequency_ranges: null,
|
||
time_window: 300,
|
||
min_detections: 1,
|
||
cooldown_period: 120,
|
||
alert_channels: ['sms', 'email'],
|
||
sms_phone_number: '+46701234567',
|
||
webhook_url: null,
|
||
active_hours: null,
|
||
active_days: [1, 2, 3, 4, 5, 6, 7],
|
||
priority: 'high',
|
||
min_threat_level: 'high'
|
||
},
|
||
{
|
||
user_id: operatorUser.id,
|
||
tenant_id: defaultTenant.id,
|
||
name: 'Medium Threat Monitoring',
|
||
description: 'Monitor medium threat drones in facility vicinity',
|
||
|
||
is_active: true,
|
||
device_ids: ['device-alpha-001', 'device-beta-002'],
|
||
drone_types: [1, 2],
|
||
min_rssi: -70,
|
||
max_rssi: null,
|
||
frequency_ranges: null,
|
||
time_window: 300,
|
||
min_detections: 1,
|
||
cooldown_period: 600,
|
||
alert_channels: ['sms'],
|
||
sms_phone_number: '+46709876543',
|
||
webhook_url: null,
|
||
active_hours: null,
|
||
active_days: [1, 2, 3, 4, 5, 6, 7],
|
||
priority: 'medium',
|
||
min_threat_level: 'medium'
|
||
},
|
||
{
|
||
user_id: adminUser.id,
|
||
tenant_id: defaultTenant.id,
|
||
name: 'Device Offline Alert',
|
||
description: 'Alert when security devices go offline',
|
||
conditions: {
|
||
device_ids: ['device-alpha-001', 'device-beta-002', 'device-gamma-003'],
|
||
time_window: 300,
|
||
min_detections: 1
|
||
},
|
||
actions: {
|
||
alert_channels: ['sms'],
|
||
sms_phone_number: '+46701234567',
|
||
priority: 'medium'
|
||
},
|
||
is_active: true,
|
||
device_ids: ['device-alpha-001', 'device-beta-002', 'device-gamma-003'],
|
||
drone_types: null,
|
||
min_rssi: null,
|
||
max_rssi: null,
|
||
frequency_ranges: null,
|
||
time_window: 300,
|
||
min_detections: 1,
|
||
cooldown_period: 1800,
|
||
alert_channels: ['sms'],
|
||
sms_phone_number: '+46701234567',
|
||
webhook_url: null,
|
||
active_hours: null,
|
||
active_days: [1, 2, 3, 4, 5, 6, 7],
|
||
priority: 'medium',
|
||
min_threat_level: null
|
||
}
|
||
]);
|
||
console.log(`✅ Created ${alertRules.length} sample alert rules`);
|
||
|
||
// Create sample alert logs
|
||
console.log('📝 Creating sample alert logs...');
|
||
const alertLogs = await AlertLog.bulkCreate([
|
||
{
|
||
user_id: adminUser.id,
|
||
alert_rule_id: alertRules[0].id,
|
||
detection_id: detections[0].id,
|
||
message: 'Drone detected with strong signal',
|
||
status: 'sent',
|
||
sent_at: new Date()
|
||
},
|
||
{
|
||
user_id: operatorUser.id,
|
||
alert_rule_id: alertRules[1].id,
|
||
detection_id: null,
|
||
message: 'Device device-gamma-003 went offline',
|
||
status: 'sent',
|
||
sent_at: new Date(Date.now() - 30 * 60 * 1000)
|
||
}
|
||
]);
|
||
console.log(`✅ Created ${alertLogs.length} sample alert logs\n`);
|
||
|
||
// Create database indexes for performance
|
||
console.log('🚀 Creating database indexes...');
|
||
|
||
await sequelize.query(`
|
||
CREATE INDEX IF NOT EXISTS idx_drone_detections_device_timestamp
|
||
ON "drone_detections" (device_id, server_timestamp);
|
||
`);
|
||
|
||
await sequelize.query(`
|
||
CREATE INDEX IF NOT EXISTS idx_heartbeats_device_timestamp
|
||
ON "heartbeats" (device_id, received_at);
|
||
`);
|
||
|
||
await sequelize.query(`
|
||
CREATE INDEX IF NOT EXISTS idx_alert_logs_rule_created
|
||
ON "alert_logs" (alert_rule_id, "created_at");
|
||
`);
|
||
|
||
console.log('✅ Database indexes created\n');
|
||
|
||
console.log('🎉 Database setup completed successfully!\n');
|
||
console.log('📋 Summary:');
|
||
console.log(` • Users created: 2 (admin, operator)`);
|
||
console.log(` • Devices created: ${devices.length}`);
|
||
console.log(` • Heartbeats created: ${heartbeats.length}`);
|
||
console.log(` • Detections created: ${detections.length}`);
|
||
console.log(` • Alert rules created: ${alertRules.length}`);
|
||
console.log(` • Alert logs created: ${alertLogs.length}`);
|
||
console.log('\n📝 Default login credentials:');
|
||
console.log(' Admin: admin / admin123');
|
||
console.log(' Operator: operator / operator123\n');
|
||
|
||
// Close connection
|
||
await sequelize.close();
|
||
|
||
} catch (error) {
|
||
console.error('❌ Database setup failed:', error);
|
||
process.exit(1);
|
||
}
|
||
};
|
||
|
||
// Run setup if called directly
|
||
if (require.main === module) {
|
||
setupDatabase();
|
||
}
|
||
|
||
module.exports = setupDatabase;
|