Skip to content

Commit

Permalink
subdomain change rate limit check
Browse files Browse the repository at this point in the history
  • Loading branch information
tugrul committed Jul 8, 2021
1 parent 46ae922 commit b5f6416
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 2 deletions.
2 changes: 2 additions & 0 deletions .env.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ REDIS_URL=redis://db
CRYPTLEX_API_BASE_URL=https://api.cryptlex.com
CRYPTLEX_API_ACCESS_TOKEN=
CRYPTLEX_API_CACHE_SECONDS=300
SUBDOMAIN_CHANGE_RATE_LIMIT_COUNT=5
SUBDOMAIN_CHANGE_RATE_LIMIT_RELEASE_SECONDS=1800
LOGS_DIR=logs
26 changes: 25 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ const {
ADMIN_TOKEN,
SUB_DOMAIN_TTL,
ROOT_DOMAIN,
APP_PORT
APP_PORT,
SUBDOMAIN_CHANGE_RATE_LIMIT_COUNT,
SUBDOMAIN_CHANGE_RATE_LIMIT_RELEASE_SECONDS
} = process.env;

const redis = require('redis');
Expand Down Expand Up @@ -161,10 +163,32 @@ async function destroyActualClientConfig(authToken) {
await redisClient.hdel('client_subdomains_last', authToken);
}

async function subdomainRateLimitCheck(subdomain, authToken) {

const actualSubdomain = await redisClient.hget('client_subdomains_last', authToken);

if (actualSubdomain && actualSubdomain === subdomain) {
return;
}

const key = 'client_rate_limit:' + authToken;

if (!await redisClient.exists(key)) {
await redisClient.setex(key, SUBDOMAIN_CHANGE_RATE_LIMIT_RELEASE_SECONDS, 0);
}

const currentLimit = parseInt(await redisClient.incr(key));

if (currentLimit > SUBDOMAIN_CHANGE_RATE_LIMIT_COUNT) {
throw new Error('Subdomain name change rate limit is exceeded');
}
}

async function applySubdomainRecord(type, authToken, subdomain, data, prefix = '') {
const lock = await redlock.lock('subdomain_record_attempt:' + subdomain, 50000);

try {
await subdomainRateLimitCheck(subdomain, authToken);
await isSubdomainAvailable(subdomain, authToken)
await updateSubdomainRecord(type, authToken, subdomain, data, prefix);
await updateLatestSubdomainBook(type, authToken, subdomain);
Expand Down
3 changes: 2 additions & 1 deletion lib/redis-promise.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@

const { promisify } = require('util');

const methods = ['get', 'set', 'exists', 'sadd', 'sismember', 'hexists', 'hget', 'hgetall', 'hset', 'hsetnx', 'hdel', 'smembers'];
const methods = ['get', 'set', 'exists', 'sadd', 'sismember', 'hexists', 'hget',
'hgetall', 'hset', 'hsetnx', 'hdel', 'smembers', 'incr', 'expire', 'setex'];

class RedisPromise {
constructor(redisClient) {
Expand Down

0 comments on commit b5f6416

Please sign in to comment.