-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
213 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
const Promise = require('bluebird'); | ||
const { LockAcquisitionError } = require('ioredis-lock'); | ||
|
||
const { getInternalData } = require('./userData'); | ||
const removeUser = require('./removeUser'); | ||
|
||
const { USERS_ACTIVATE, | ||
USERS_ACTIVATE_AUDIENCE, | ||
} = require('../constants'); | ||
|
||
const lockKey = `${USERS_ACTIVATE}:data-lock`; | ||
|
||
// Get user ids having score lt current time - interval | ||
async function getInactiveUsers(redis, interval) { | ||
const start = '-inf'; | ||
const end = Date.now() - (interval * 1000); | ||
return redis.zrangebyscore(USERS_ACTIVATE, start, end); | ||
} | ||
|
||
async function getAudience(redis, userId) { | ||
const audience = await redis.hget(USERS_ACTIVATE_AUDIENCE, userId); | ||
return audience; | ||
} | ||
|
||
async function deleteUser(userId, audience) { | ||
const { redis } = this; | ||
const context = { redis, audience }; | ||
|
||
const internal = await Promise | ||
.bind(context, userId) | ||
.then(getInternalData); | ||
|
||
const transaction = redis.multi(); | ||
|
||
removeUser(transaction, internal, audience); | ||
return transaction.exec(); | ||
} | ||
|
||
/** | ||
* Add user id to inacive users list | ||
* @param {ioredis} redis | ||
* @param {userId} userId | ||
* @param {audience[]} audience | ||
*/ | ||
function addInactiveUser(redis, userId, audience) { | ||
const created = Date.now(); | ||
redis.zadd(USERS_ACTIVATE, userId, created); | ||
redis.hset(USERS_ACTIVATE_AUDIENCE, userId, JSON.stringify(audience)); | ||
} | ||
|
||
/** | ||
* Remove user id from inactive users list | ||
* @param {ioredis} redis | ||
* @param {userId} userId | ||
*/ | ||
function removeInactiveUser(redis, userId) { | ||
redis.zrem(USERS_ACTIVATE, userId); | ||
redis.hdel(USERS_ACTIVATE_AUDIENCE, userId); | ||
} | ||
|
||
/** | ||
* Clean all users, who did't pass activation | ||
* Call in `service` context | ||
*/ | ||
async function cleanInactiveUsers() { | ||
const { redis } = this; | ||
const { deleteInactiveAccounts } = this.config; | ||
|
||
const lock = await this.dlock.once(lockKey); | ||
const inactiveAccounts = await getInactiveUsers(redis, deleteInactiveAccounts); | ||
|
||
inactiveAccounts.forEach(async (acc) => { | ||
const accAudiences = getAudience(redis, acc); | ||
await deleteUser.bind(this, acc, accAudiences); | ||
await removeInactiveUser(redis, acc); | ||
}); | ||
|
||
lock.release().reflect(); | ||
} | ||
|
||
/** | ||
* Returns inactive users cleanup task | ||
* @param {Mfleet} service | ||
* @returns {NodeJS.Timeout} | ||
*/ | ||
function getCleanerTask(service) { | ||
const { deleteInactiveAccountsInterval: interval } = service.config; | ||
|
||
return setInterval(() => { | ||
cleanInactiveUsers.call(service) | ||
.catch(LockAcquisitionError, () => {}) | ||
.catch((error) => { | ||
service.log.error('Inactive User Clean task error', error); | ||
}); | ||
}, interval * 1000); | ||
} | ||
|
||
/** | ||
* Stops currently running task | ||
* @param {NodeJS.Timeout} task | ||
*/ | ||
function stopCleanerTask(task) { | ||
clearInterval(task); | ||
} | ||
|
||
|
||
module.exports = { | ||
addInactiveUser, | ||
removeInactiveUser, | ||
cleanInactiveUsers, | ||
getCleanerTask, | ||
stopCleanerTask, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
const get = require('../utils/get-value'); | ||
const key = require('../utils/key'); | ||
|
||
const { USERS_ALIAS_FIELD, | ||
USERS_ID_FIELD, | ||
USERS_ALIAS_TO_ID, | ||
USERS_USERNAME_TO_ID, | ||
USERS_USERNAME_FIELD, | ||
USERS_PUBLIC_INDEX, | ||
USERS_INDEX, | ||
USERS_DATA, | ||
USERS_METADATA, | ||
USERS_TOKENS, | ||
SSO_PROVIDERS, | ||
THROTTLE_PREFIX, | ||
USERS_ACTION_ACTIVATE, | ||
USERS_ACTION_REGISTER, | ||
USERS_ACTION_PASSWORD, | ||
USERS_ACTION_RESET, | ||
USERS_SSO_TO_ID } = require('../constants'); | ||
|
||
/** | ||
* Assigns common user remove logic into passed transaction | ||
* @param {ioredis} transaction | ||
* @param {ms-user data} internal | ||
* @param {ms-user audience/[]} _audiences | ||
*/ | ||
function removeUser(transaction, internal, _audiences) { | ||
const audiences = Array.isArray(_audiences) ? _audiences : [_audiences]; | ||
|
||
const alias = internal[USERS_ALIAS_FIELD]; | ||
const userId = internal[USERS_ID_FIELD]; | ||
const resolvedUsername = internal[USERS_USERNAME_FIELD]; | ||
|
||
if (alias) { | ||
transaction.hdel(USERS_ALIAS_TO_ID, alias.toLowerCase(), alias); | ||
} | ||
|
||
transaction.hdel(USERS_USERNAME_TO_ID, resolvedUsername); | ||
|
||
// remove refs to SSO account | ||
for (const provider of SSO_PROVIDERS) { | ||
const uid = get(internal, `${provider}.uid`, { default: false }); | ||
|
||
if (uid) { | ||
transaction.hdel(USERS_SSO_TO_ID, uid); | ||
} | ||
} | ||
|
||
// clean indices | ||
transaction.srem(USERS_PUBLIC_INDEX, userId); | ||
transaction.srem(USERS_INDEX, userId); | ||
|
||
// remove metadata & internal data | ||
transaction.del(key(userId, USERS_DATA)); | ||
|
||
audiences.forEach((audience) => { | ||
transaction.del(key(userId, USERS_METADATA, audience)); | ||
}); | ||
|
||
// remove auth tokens | ||
transaction.del(key(userId, USERS_TOKENS)); | ||
|
||
// remove throttling on actions | ||
transaction.del(key(THROTTLE_PREFIX, USERS_ACTION_ACTIVATE, userId)); | ||
transaction.del(key(THROTTLE_PREFIX, USERS_ACTION_PASSWORD, userId)); | ||
transaction.del(key(THROTTLE_PREFIX, USERS_ACTION_REGISTER, userId)); | ||
transaction.del(key(THROTTLE_PREFIX, USERS_ACTION_RESET, userId)); | ||
|
||
return transaction; | ||
} | ||
|
||
module.exports = removeUser; |