Files
drone-detector/data-retention-service/database.js
2025-09-24 04:57:07 +02:00

237 lines
4.5 KiB
JavaScript

/**
* Database connection and models for Data Retention Service
*/
const { Sequelize, DataTypes } = require('sequelize');
let sequelize;
let models = {};
/**
* Initialize database connection
*/
async function initializeDatabase() {
// Database connection
sequelize = new Sequelize(
process.env.DB_NAME || 'drone_detection',
process.env.DB_USER || 'postgres',
process.env.DB_PASSWORD || 'password',
{
host: process.env.DB_HOST || 'localhost',
port: process.env.DB_PORT || 5432,
dialect: 'postgres',
logging: process.env.NODE_ENV === 'development' ? console.log : false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
}
);
// Test connection
await sequelize.authenticate();
// Define models
defineModels();
return sequelize;
}
/**
* Define database models
*/
function defineModels() {
// Tenant model
models.Tenant = sequelize.define('Tenant', {
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4
},
slug: {
type: DataTypes.STRING(50),
unique: true,
allowNull: false
},
name: {
type: DataTypes.STRING(100),
allowNull: false
},
features: {
type: DataTypes.JSONB,
defaultValue: {}
},
is_active: {
type: DataTypes.BOOLEAN,
defaultValue: true
}
}, {
tableName: 'tenants',
timestamps: true,
createdAt: 'created_at',
updatedAt: 'updated_at'
});
// DroneDetection model
models.DroneDetection = sequelize.define('DroneDetection', {
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4
},
tenant_id: {
type: DataTypes.UUID,
allowNull: false
},
device_id: {
type: DataTypes.STRING(50),
allowNull: false
},
server_timestamp: {
type: DataTypes.DATE,
allowNull: false
},
drone_type: {
type: DataTypes.INTEGER,
allowNull: true
},
rssi: {
type: DataTypes.FLOAT,
allowNull: true
},
frequency: {
type: DataTypes.FLOAT,
allowNull: true
}
}, {
tableName: 'drone_detections',
timestamps: false,
indexes: [
{
fields: ['tenant_id', 'server_timestamp']
},
{
fields: ['server_timestamp']
}
]
});
// Heartbeat model
models.Heartbeat = sequelize.define('Heartbeat', {
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4
},
tenant_id: {
type: DataTypes.UUID,
allowNull: false
},
device_id: {
type: DataTypes.STRING(50),
allowNull: false
},
timestamp: {
type: DataTypes.DATE,
allowNull: false
},
status: {
type: DataTypes.STRING(20),
defaultValue: 'online'
}
}, {
tableName: 'heartbeats',
timestamps: false,
indexes: [
{
fields: ['tenant_id', 'timestamp']
},
{
fields: ['timestamp']
}
]
});
// SecurityLog model - IMPORTANT: Security logs have different retention policies (much longer)
models.SecurityLog = sequelize.define('SecurityLog', {
id: {
type: DataTypes.UUID,
primaryKey: true,
defaultValue: DataTypes.UUIDV4
},
tenant_id: {
type: DataTypes.UUID,
allowNull: true
},
event_type: {
type: DataTypes.STRING(50),
allowNull: false
},
severity: {
type: DataTypes.STRING(20),
allowNull: false
},
username: {
type: DataTypes.STRING(100),
allowNull: true
},
ip_address: {
type: DataTypes.INET,
allowNull: true
},
country_code: {
type: DataTypes.STRING(2),
allowNull: true
},
message: {
type: DataTypes.TEXT,
allowNull: false
},
created_at: {
type: DataTypes.DATE,
allowNull: false
}
}, {
tableName: 'security_logs',
timestamps: false,
indexes: [
{
fields: ['tenant_id', 'created_at']
},
{
fields: ['event_type', 'created_at']
},
{
fields: ['ip_address', 'created_at']
}
]
});
}
/**
* Get models
*/
async function getModels() {
if (!sequelize) {
await initializeDatabase();
}
return models;
}
/**
* Close database connection
*/
async function closeDatabase() {
if (sequelize) {
await sequelize.close();
}
}
module.exports = {
initializeDatabase,
getModels,
closeDatabase,
sequelize: () => sequelize
};