Files
koin_ping_0.2.0/backend/controllers/AlertRuleController.js
2026-02-27 09:58:18 -05:00

186 lines
4.9 KiB
JavaScript

import * as AlertRuleModel from '../models/AlertRuleModel.js';
import * as AddressModel from '../models/AddressModel.js';
const VALID_ALERT_TYPES = ['incoming_tx', 'outgoing_tx', 'large_transfer', 'balance_below'];
const THRESHOLD_REQUIRED_TYPES = ['large_transfer', 'balance_below'];
/**
* Create a new alert rule
*/
export async function create(req, res) {
const addressId = parseInt(req.params.addressId);
const { type, threshold } = req.body;
const user_id = req.user_id; // From authenticate middleware
console.log(`User ${user_id} creating alert for address ID: ${addressId}`);
if (isNaN(addressId)) {
return res.status(400).json({
error: 'VALIDATION_ERROR',
message: 'Invalid address ID'
});
}
if (!type) {
return res.status(400).json({
error: 'VALIDATION_ERROR',
message: 'Alert type is required'
});
}
// Validation: type must be valid
if (!VALID_ALERT_TYPES.includes(type)) {
return res.status(400).json({
error: 'VALIDATION_ERROR',
message: `Invalid alert type. Must be one of: ${VALID_ALERT_TYPES.join(', ')}`
});
}
if (THRESHOLD_REQUIRED_TYPES.includes(type)) {
if (!threshold || threshold === '') {
return res.status(400).json({
error: 'VALIDATION_ERROR',
message: `Alert type '${type}' requires a threshold value`
});
}
const thresholdNum = parseFloat(threshold);
if (isNaN(thresholdNum) || thresholdNum <= 0) {
return res.status(400).json({
error: 'VALIDATION_ERROR',
message: 'Threshold must be a positive number'
});
}
}
try {
// Verify address exists AND belongs to this user
const address = await AddressModel.findById(addressId, user_id);
if (!address) {
console.log(`Address ${addressId} not found or not owned by user`);
return res.status(404).json({
error: 'NOT_FOUND',
message: 'Address not found'
});
}
const newAlert = await AlertRuleModel.create(
addressId,
type,
threshold || null
);
console.log(`Alert rule created with ID: ${newAlert.id}`);
return res.status(201).json(newAlert);
} catch (error) {
console.error(error);
return res.status(500).json({
error: 'INTERNAL_ERROR',
message: 'Failed to create alert rule'
});
}
}
export async function listByAddress(req, res) {
const addressId = parseInt(req.params.addressId);
const user_id = req.user_id; // From authenticate middleware
console.log(`User ${user_id} listing alerts for address ID: ${addressId}`);
if (isNaN(addressId)) {
return res.status(400).json({
error: 'VALIDATION_ERROR',
message: 'Invalid address ID'
});
}
const address = await AddressModel.findById(addressId, user_id);
if (!address) {
console.log(`Address ${addressId} not found or not owned by user`);
return res.status(404).json({
error: 'NOT_FOUND',
message: 'Address not found'
});
}
const alerts = await AlertRuleModel.listByAddress(addressId);
console.log(`Found ${alerts.length} alert rules`);
return res.json(alerts);
}
export async function updateStatus(req, res) {
const alertId = parseInt(req.params.alertId);
const { enabled } = req.body;
const user_id = req.user_id;
console.log(`User ${user_id} updating alert ID: ${alertId}`);
// Validation: alertId must be valid
if (isNaN(alertId)) {
return res.status(400).json({
error: 'VALIDATION_ERROR',
message: 'Invalid alert ID'
});
}
// Validation: enabled must be boolean
if (typeof enabled !== 'boolean') {
return res.status(400).json({
error: 'VALIDATION_ERROR',
message: 'enabled must be a boolean value'
});
}
// Verify user owns this alert (through address ownership)
const alert = await AlertRuleModel.findById(alertId, user_id);
if (!alert) {
console.log(`Alert ${alertId} not found or not owned by user`);
return res.status(404).json({
error: 'NOT_FOUND',
message: 'Alert rule not found'
});
}
const updatedAlert = await AlertRuleModel.updateEnabled(alertId, enabled);
console.log(`Alert ${alertId} updated: enabled=${enabled}`);
return res.json(updatedAlert);
}
export async function remove(req, res) {
const alertId = parseInt(req.params.alertId);
const user_id = req.user_id;
console.log(`User ${user_id} deleting alert ID: ${alertId}`);
if (isNaN(alertId)) {
return res.status(400).json({
error: 'VALIDATION_ERROR',
message: 'Invalid alert ID'
});
}
const alert = await AlertRuleModel.findById(alertId, user_id);
if (!alert) {
console.log(`Alert ${alertId} not found or not owned by user`);
return res.status(404).json({
error: 'NOT_FOUND',
message: 'Alert rule not found'
});
}
const deleted = await AlertRuleModel.remove(alertId);
console.log(`Alert ${alertId} deleted`);
return res.status(204).send();
}