160 lines
3.9 KiB
JavaScript
160 lines
3.9 KiB
JavaScript
const { DataTypes } = require('sequelize');
|
|
|
|
module.exports = (sequelize) => {
|
|
const SecurityLog = sequelize.define('SecurityLog', {
|
|
id: {
|
|
type: DataTypes.UUID,
|
|
defaultValue: sequelize.Sequelize.UUIDV4,
|
|
primaryKey: true
|
|
},
|
|
tenant_id: {
|
|
type: DataTypes.UUID,
|
|
allowNull: true,
|
|
references: {
|
|
model: 'tenants',
|
|
key: 'id'
|
|
},
|
|
comment: 'Tenant ID for multi-tenant isolation (null for system-wide events)'
|
|
},
|
|
event_type: {
|
|
type: DataTypes.STRING(50),
|
|
allowNull: false,
|
|
comment: 'Type of security event (login_failed, login_success, suspicious_pattern, etc.)'
|
|
},
|
|
severity: {
|
|
type: DataTypes.STRING(20),
|
|
allowNull: false,
|
|
defaultValue: 'info',
|
|
validate: {
|
|
isIn: [['low', 'medium', 'high', 'critical']]
|
|
},
|
|
comment: 'Severity level of the security event'
|
|
},
|
|
user_id: {
|
|
type: DataTypes.UUID,
|
|
allowNull: true,
|
|
comment: 'User ID if applicable'
|
|
},
|
|
username: {
|
|
type: DataTypes.STRING(100),
|
|
allowNull: true,
|
|
comment: 'Username involved in the event'
|
|
},
|
|
ip_address: {
|
|
type: DataTypes.INET,
|
|
allowNull: true,
|
|
comment: 'Client IP address'
|
|
},
|
|
client_ip: {
|
|
type: DataTypes.INET,
|
|
allowNull: true,
|
|
comment: 'Real client IP (if behind proxy/load balancer)'
|
|
},
|
|
user_agent: {
|
|
type: DataTypes.TEXT,
|
|
allowNull: true,
|
|
comment: 'User agent string'
|
|
},
|
|
rdns: {
|
|
type: DataTypes.STRING(255),
|
|
allowNull: true,
|
|
comment: 'Reverse DNS lookup of IP address'
|
|
},
|
|
country_code: {
|
|
type: DataTypes.STRING(2),
|
|
allowNull: true,
|
|
comment: 'ISO country code from IP geolocation'
|
|
},
|
|
country_name: {
|
|
type: DataTypes.STRING(100),
|
|
allowNull: true,
|
|
comment: 'Country name from IP geolocation'
|
|
},
|
|
city: {
|
|
type: DataTypes.STRING(100),
|
|
allowNull: true,
|
|
comment: 'City from IP geolocation'
|
|
},
|
|
is_high_risk_country: {
|
|
type: DataTypes.BOOLEAN,
|
|
defaultValue: false,
|
|
comment: 'Whether the country is flagged as high-risk'
|
|
},
|
|
message: {
|
|
type: DataTypes.TEXT,
|
|
allowNull: false,
|
|
comment: 'Detailed description of the security event'
|
|
},
|
|
metadata: {
|
|
type: DataTypes.JSONB,
|
|
allowNull: true,
|
|
defaultValue: {},
|
|
comment: 'Additional event-specific data'
|
|
},
|
|
session_id: {
|
|
type: DataTypes.STRING(255),
|
|
allowNull: true,
|
|
comment: 'Session ID if applicable'
|
|
},
|
|
request_id: {
|
|
type: DataTypes.STRING(255),
|
|
allowNull: true,
|
|
comment: 'Request ID for correlation'
|
|
},
|
|
endpoint: {
|
|
type: DataTypes.STRING(255),
|
|
allowNull: true,
|
|
comment: 'API endpoint or URL involved'
|
|
},
|
|
method: {
|
|
type: DataTypes.STRING(10),
|
|
allowNull: true,
|
|
comment: 'HTTP method'
|
|
},
|
|
status_code: {
|
|
type: DataTypes.INTEGER,
|
|
allowNull: true,
|
|
comment: 'HTTP response status code'
|
|
},
|
|
alerted: {
|
|
type: DataTypes.BOOLEAN,
|
|
defaultValue: false,
|
|
comment: 'Whether super admins have been alerted about this event'
|
|
},
|
|
created_at: {
|
|
type: DataTypes.DATE,
|
|
defaultValue: sequelize.Sequelize.NOW,
|
|
comment: 'When the event occurred'
|
|
}
|
|
}, {
|
|
tableName: 'security_logs',
|
|
timestamps: true,
|
|
createdAt: 'created_at',
|
|
updatedAt: false, // Security logs should not be updated
|
|
indexes: [
|
|
{
|
|
fields: ['tenant_id', 'created_at']
|
|
},
|
|
{
|
|
fields: ['event_type', 'created_at']
|
|
},
|
|
{
|
|
fields: ['ip_address', 'created_at']
|
|
},
|
|
{
|
|
fields: ['username', 'created_at']
|
|
},
|
|
{
|
|
fields: ['severity', 'created_at']
|
|
},
|
|
{
|
|
fields: ['country_code', 'is_high_risk_country']
|
|
},
|
|
{
|
|
fields: ['alerted', 'severity', 'created_at']
|
|
}
|
|
]
|
|
});
|
|
|
|
return SecurityLog;
|
|
}; |