dt-common-device
Version:
A secure and robust device management library for IoT applications
196 lines (195 loc) • 7.95 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RateLimitUtils = void 0;
const redis_1 = require("../../db/redis");
const config_1 = require("../../config/config");
const constants_1 = require("../../constants");
class RateLimitUtils {
static async checkRateLimit(connectionId, provider, rateLimitConfigs) {
const config = rateLimitConfigs.get(provider);
if (!config) {
(0, config_1.getConfig)().LOGGER.warn(`No rate limit config found for provider: ${provider}`);
return true;
}
const key = `rate_limit:${provider}:${connectionId}`;
const now = Date.now();
const windowStart = now - config.windowMs;
try {
const data = await this.redisClient.get(key);
const requests = data
? JSON.parse(data).filter((t) => t > windowStart)
: [];
if (requests.length >= config.maxRequests)
return false;
requests.push(now);
await this.redisClient.setex(key, Math.ceil(config.windowMs / 1000), JSON.stringify(requests));
return true;
}
catch (error) {
(0, config_1.getConfig)().LOGGER.error(`Rate limit check error: ${error}`);
return true;
}
}
static initializeRateLimitConfigs() {
const configs = new Map();
// Configure rate limits for different providers
configs.set(constants_1.CONNECTION_PROVIDERS.SENSIBO, {
maxRequests: 10,
windowMs: 10000, // 10 seconds
provider: constants_1.CONNECTION_PROVIDERS.SENSIBO,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.CLOUDBEDS, {
maxRequests: 8,
windowMs: 1000, // 1 second - CloudBed allows 10 requests per second
provider: constants_1.CONNECTION_PROVIDERS.CLOUDBEDS,
maxTimeoutWindowMs: 1800000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.STAYNTOUCH, {
maxRequests: 10,
windowMs: 10000, // 10 seconds
provider: constants_1.CONNECTION_PROVIDERS.STAYNTOUCH,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.HOTELKEY, {
maxRequests: 10,
windowMs: 10000, // 10 seconds
provider: constants_1.CONNECTION_PROVIDERS.HOTELKEY,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.TTLOCK, {
maxRequests: 15,
windowMs: 60000, // 1 minute
provider: constants_1.CONNECTION_PROVIDERS.TTLOCK,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.LOCKLY, {
maxRequests: 10,
windowMs: 60000, // 1 minute
provider: constants_1.CONNECTION_PROVIDERS.LOCKLY,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.SCHLAGE, {
maxRequests: 120,
windowMs: 60000, // 1 minute
provider: constants_1.CONNECTION_PROVIDERS.SCHLAGE,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.SMARTTHINGS, {
maxRequests: 30,
windowMs: 60000, // 1 minute
provider: constants_1.CONNECTION_PROVIDERS.SMARTTHINGS,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.YALEWIFI, {
maxRequests: 5,
windowMs: 60000,
provider: constants_1.CONNECTION_PROVIDERS.YALEWIFI,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.TUYA, {
maxRequests: 5,
windowMs: 1000,
provider: constants_1.CONNECTION_PROVIDERS.TUYA,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.SALTOKS, {
maxRequests: 5,
windowMs: 60000,
provider: constants_1.CONNECTION_PROVIDERS.SALTOKS,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.SALTOSPACE, {
maxRequests: 5,
windowMs: 60000,
provider: constants_1.CONNECTION_PROVIDERS.SALTOSPACE,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.VERDANT, {
maxRequests: 5,
windowMs: 60000,
provider: constants_1.CONNECTION_PROVIDERS.VERDANT,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.SMOOBU, {
maxRequests: 1000,
windowMs: 60000,
provider: constants_1.CONNECTION_PROVIDERS.SMOOBU,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.WEBREZPRO, {
maxRequests: 10,
windowMs: 60000,
provider: constants_1.CONNECTION_PROVIDERS.WEBREZPRO,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.CHECKFRONT, {
maxRequests: 10,
windowMs: 60000,
provider: constants_1.CONNECTION_PROVIDERS.CHECKFRONT,
maxTimeoutWindowMs: 120000,
});
configs.set(constants_1.CONNECTION_PROVIDERS.MEWS, {
maxRequests: 200,
windowMs: 30000, // 30 seconds - 200 requests per AccessToken within 30 seconds
provider: constants_1.CONNECTION_PROVIDERS.MEWS,
maxTimeoutWindowMs: 120000,
});
return configs;
}
static async isRateLimitAllowed(connectionId, provider, rateLimitConfigs) {
const config = rateLimitConfigs.get(provider);
if (!config) {
(0, config_1.getConfig)().LOGGER.warn(`No rate limit config found for provider: ${provider}`);
return true;
}
const key = `rate_limit:${provider}:${connectionId}`;
const now = Date.now();
const windowStart = now - config.windowMs;
try {
const data = await this.redisClient.get(key);
const requests = data
? JSON.parse(data).filter((t) => t > windowStart)
: [];
return requests.length < config.maxRequests;
}
catch (error) {
(0, config_1.getConfig)().LOGGER.error(`Rate limit check error: ${error}`);
return true;
}
}
static async recordRequest(connectionId, provider) {
const config = this.getRateLimitConfig(provider);
if (!config)
return;
const key = `rate_limit:${provider}:${connectionId}`;
const now = Date.now();
const windowStart = now - config.windowMs;
try {
const data = await this.redisClient.get(key);
const requests = data
? JSON.parse(data).filter((t) => t > windowStart)
: [];
requests.push(now);
await this.redisClient.setex(key, Math.ceil(config.windowMs / 1000), JSON.stringify(requests));
}
catch (error) {
(0, config_1.getConfig)().LOGGER.error(`Rate limit record error: ${error}`);
}
}
static async getRawRequestTimestamps(key) {
try {
const data = await this.redisClient.get(key);
return data ? JSON.parse(data) : [];
}
catch (error) {
(0, config_1.getConfig)().LOGGER.error(`Error fetching raw request timestamps: ${error}`);
return [];
}
}
static getRateLimitConfig(provider) {
return this.initializeRateLimitConfigs().get(provider);
}
}
exports.RateLimitUtils = RateLimitUtils;
RateLimitUtils.redisClient = (0, redis_1.getRedisClient)();