237 lines
4.5 KiB
JavaScript
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
|
|
}; |