From e0e26ee3ccdbb1ab39cc817787b4ab80e3e8f781 Mon Sep 17 00:00:00 2001 From: Oleg Tokar Date: Thu, 17 Jun 2021 07:11:54 +0300 Subject: [PATCH 1/2] feat: user data abstraction --- bin/password.js | 4 +- src/actions/activate.js | 14 +-- src/actions/alias.js | 5 +- src/actions/ban.js | 16 +-- src/actions/mfa/attach.js | 10 +- src/actions/mfa/detach.js | 10 +- src/actions/register.js | 10 +- src/actions/remove.js | 8 +- src/actions/token/create.js | 4 +- src/actions/token/erase.js | 4 +- src/actions/token/list.js | 4 +- src/actions/updatePassword.js | 7 +- src/auth/oauth/utils/attach.js | 8 +- src/auth/oauth/utils/detach.js | 10 +- src/auth/oauth/utils/refresh.js | 14 +-- .../05-referrals-users-ids/index.js | 4 +- src/users.js | 3 + src/utils/data/user.js | 111 ++++++++++++++++++ src/utils/mfa.js | 4 +- .../organization/get-organization-members.js | 4 +- .../register-organization-members.js | 6 +- src/utils/userData/get-internal-data.js | 4 +- src/utils/userData/resolve-user-id.js | 22 +--- 23 files changed, 164 insertions(+), 122 deletions(-) create mode 100644 src/utils/data/user.js diff --git a/bin/password.js b/bin/password.js index 9bb4cffb5..33ccd433e 100755 --- a/bin/password.js +++ b/bin/password.js @@ -4,6 +4,7 @@ const Redis = require('ioredis'); const assert = require('assert'); const conf = require('../lib/config'); +const UserData = require('../lib/utils/data/user'); const { updatePassword } = require('../lib/actions/updatePassword'); const config = conf.get('/', { env: process.env.NODE_ENV }); @@ -32,7 +33,8 @@ const main = async (username, password) => { try { await redis.connect(); - await updatePassword({ redis }, username, password); + const userData = new UserData(redis); + await updatePassword({ userData }, username, password); } catch (err) { setImmediate(() => { throw err; diff --git a/src/actions/activate.js b/src/actions/activate.js index f74475cce..28581fec6 100644 --- a/src/actions/activate.js +++ b/src/actions/activate.js @@ -1,7 +1,6 @@ const { ActionTransport } = require('@microfleet/core'); const { HttpStatusError } = require('common-errors'); const Promise = require('bluebird'); -const redisKey = require('../utils/key.js'); const jwt = require('../utils/jwt.js'); const { getInternalData } = require('../utils/userData'); const getMetadata = require('../utils/get-metadata'); @@ -10,7 +9,6 @@ const UserMetadata = require('../utils/metadata/user'); const { USERS_INDEX, - USERS_DATA, USERS_REFERRAL_INDEX, USERS_PUBLIC_INDEX, USERS_ACTIVE_FLAG, @@ -119,17 +117,9 @@ async function activateAccount(data, metadata) { const userId = data[USERS_ID_FIELD]; const alias = data[USERS_ALIAS_FIELD]; const referral = metadata[USERS_REFERRAL_FIELD]; - const userKey = redisKey(userId, USERS_DATA); const { defaultAudience, service } = this; - const { redis } = service; - // WARNING: `persist` is very important, otherwise we will lose user's information in 30 days - // set to active & persist - const pipeline = redis - .pipeline() - .hget(userKey, USERS_ACTIVE_FLAG) - .hset(userKey, USERS_ACTIVE_FLAG, 'true') - .persist(userKey) - .sadd(USERS_INDEX, userId); + const pipeline = service.userData.activate(userId); + pipeline.sadd(USERS_INDEX, userId); UserMetadata .using(userId, defaultAudience, pipeline) diff --git a/src/actions/alias.js b/src/actions/alias.js index 28f842bc1..e252d29d0 100644 --- a/src/actions/alias.js +++ b/src/actions/alias.js @@ -5,12 +5,10 @@ const { getInternalData } = require('../utils/userData'); const isActive = require('../utils/is-active'); const isBanned = require('../utils/is-banned'); const DetailedHttpStatusError = require('../utils/detailed-error'); -const key = require('../utils/key'); const handlePipeline = require('../utils/pipeline-error'); const UserMetadata = require('../utils/metadata/user'); const { - USERS_DATA, USERS_ALIAS_TO_ID, USERS_ID_FIELD, USERS_ALIAS_FIELD, @@ -72,9 +70,8 @@ async function assignAlias({ params }) { return Promise.reject(err); } - const pipeline = redis.pipeline(); + const pipeline = this.userData.setAlias(userId, alias); - pipeline.hset(key(userId, USERS_DATA), USERS_ALIAS_FIELD, alias); UserMetadata .using(userId, defaultAudience, pipeline) .update(USERS_ALIAS_FIELD, JSON.stringify(alias)); diff --git a/src/actions/ban.js b/src/actions/ban.js index 9ff92c1b5..35dab35de 100644 --- a/src/actions/ban.js +++ b/src/actions/ban.js @@ -6,9 +6,7 @@ const { getInternalData } = require('../utils/userData'); const handlePipeline = require('../utils/pipeline-error'); const UserMetadata = require('../utils/metadata/user'); -const { - USERS_DATA, USERS_BANNED_FLAG, USERS_TOKENS, USERS_BANNED_DATA, -} = require('../constants.js'); +const { USERS_TOKENS, USERS_BANNED_DATA } = require('../constants.js'); // helper const stringify = (data) => JSON.stringify(data); @@ -16,7 +14,7 @@ const stringify = (data) => JSON.stringify(data); function lockUser({ id, reason, whom, remoteip, }) { - const { redis, config } = this; + const { config } = this; const { jwt: { defaultAudience } } = config; const data = { banned: true, @@ -26,9 +24,7 @@ function lockUser({ remoteip: remoteip || '', }, }; - const pipeline = redis.pipeline(); - - pipeline.hset(redisKey(id, USERS_DATA), USERS_BANNED_FLAG, 'true'); + const pipeline = this.userData.lock(id); // set .banned on metadata for filtering & sorting users by that field UserMetadata .using(id, defaultAudience, pipeline) @@ -39,11 +35,9 @@ function lockUser({ } function unlockUser({ id }) { - const { redis, config } = this; + const { config } = this; const { jwt: { defaultAudience } } = config; - const pipeline = redis.pipeline(); - - pipeline.hdel(redisKey(id, USERS_DATA), USERS_BANNED_FLAG); + const pipeline = this.userData.unLock(id); // remove .banned on metadata for filtering & sorting users by that field UserMetadata .using(id, defaultAudience, pipeline) diff --git a/src/actions/mfa/attach.js b/src/actions/mfa/attach.js index b9c7720bf..d87c2181b 100644 --- a/src/actions/mfa/attach.js +++ b/src/actions/mfa/attach.js @@ -3,10 +3,9 @@ const Promise = require('bluebird'); const redisKey = require('../../utils/key'); const handlePipeline = require('../../utils/pipeline-error'); +const UserData = require('../../utils/data/user'); const { checkMFA, generateRecoveryCodes } = require('../../utils/mfa'); const { - USERS_DATA, - USERS_MFA_FLAG, USERS_MFA_RECOVERY, MFA_TYPE_DISABLED, } = require('../../constants'); @@ -15,11 +14,12 @@ async function storeData(userId) { const { redis, secret } = this; const recoveryCodes = generateRecoveryCodes(); - return redis + const pipeline = redis .pipeline() .del(redisKey(userId, USERS_MFA_RECOVERY)) - .sadd(redisKey(userId, USERS_MFA_RECOVERY), recoveryCodes) - .hset(redisKey(userId, USERS_DATA), USERS_MFA_FLAG, secret) + .sadd(redisKey(userId, USERS_MFA_RECOVERY), recoveryCodes); + + return UserData.setMFA(userId, pipeline, secret) .exec() .then(handlePipeline) .return({ recoveryCodes, enabled: true }); diff --git a/src/actions/mfa/detach.js b/src/actions/mfa/detach.js index 11597ef5b..4ac6b714e 100644 --- a/src/actions/mfa/detach.js +++ b/src/actions/mfa/detach.js @@ -2,19 +2,19 @@ const { ActionTransport } = require('@microfleet/core'); const Promise = require('bluebird'); const redisKey = require('../../utils/key'); const handlePipeline = require('../../utils/pipeline-error'); +const UserData = require('../../utils/data/user'); const { checkMFA } = require('../../utils/mfa'); const { - USERS_DATA, - USERS_MFA_FLAG, USERS_MFA_RECOVERY, MFA_TYPE_REQUIRED, } = require('../../constants'); async function removeData(userId) { - return this.redis + const pipeline = this.redis .pipeline() - .del(redisKey(userId, USERS_MFA_RECOVERY)) - .hdel(redisKey(userId, USERS_DATA), USERS_MFA_FLAG) + .del(redisKey(userId, USERS_MFA_RECOVERY)); + + return UserData.delMFA(userId, pipeline) .exec() .then(handlePipeline) .return({ enabled: false }); diff --git a/src/actions/register.js b/src/actions/register.js index 036b4357b..760af957e 100644 --- a/src/actions/register.js +++ b/src/actions/register.js @@ -22,12 +22,12 @@ const checkLimits = require('../utils/check-ip-limits'); const challenge = require('../utils/challenges/challenge'); const handlePipeline = require('../utils/pipeline-error'); const hashPassword = require('../utils/register/password/hash'); +const UserData = require('../utils/data/user'); const { USERS_REF, USERS_REF_METADATA, USERS_INDEX, USERS_SSO_TO_ID, - USERS_DATA, USERS_USERNAME_TO_ID, USERS_ACTIVE_FLAG, USERS_ID_FIELD, @@ -211,13 +211,9 @@ async function performRegistration({ service, params }) { pipeline.hset(USERS_SSO_TO_ID, uid, userId); } - const userDataKey = redisKey(userId, USERS_DATA); - pipeline.hmset(userDataKey, basicInfo); - pipeline.hset(USERS_USERNAME_TO_ID, username, userId); + UserData.register(userId, pipeline, basicInfo, activate, config.deleteInactiveAccounts); - if (activate === false && config.deleteInactiveAccounts >= 0) { - pipeline.expire(userDataKey, config.deleteInactiveAccounts); - } + pipeline.hset(USERS_USERNAME_TO_ID, username, userId); handlePipeline(await pipeline.exec()); diff --git a/src/actions/remove.js b/src/actions/remove.js index 71d44f20e..cc2ebf0c6 100644 --- a/src/actions/remove.js +++ b/src/actions/remove.js @@ -8,6 +8,7 @@ const { getInternalData } = require('../utils/userData'); const getMetadata = require('../utils/get-metadata'); const handlePipeline = require('../utils/pipeline-error'); const UserMetadata = require('../utils/metadata/user'); +const UserData = require('../utils/data/user'); const { USERS_INDEX, USERS_PUBLIC_INDEX, @@ -15,7 +16,6 @@ const { USERS_SSO_TO_ID, USERS_USERNAME_TO_ID, USERS_USERNAME_FIELD, - USERS_DATA, USERS_METADATA, USERS_TOKENS, USERS_ID_FIELD, @@ -75,8 +75,8 @@ async function removeOrganizationUser(userId) { */ async function removeUser({ params }) { const audience = this.config.jwt.defaultAudience; - const { redis } = this; - const context = { redis, audience }; + const { redis, userData } = this; + const context = { redis, audience, userData }; const { username } = params; const [internal, meta] = await Promise @@ -116,7 +116,7 @@ async function removeUser({ params }) { transaction.srem(USERS_INDEX, userId); // remove metadata & internal data - transaction.del(key(userId, USERS_DATA)); + UserData.deleteUserData(userId, transaction); for (const metaAudience of metaAudiences) { userMetadata.deleteMetadata(metaAudience); } diff --git a/src/actions/token/create.js b/src/actions/token/create.js index caefcfa55..43ccc3d36 100644 --- a/src/actions/token/create.js +++ b/src/actions/token/create.js @@ -49,8 +49,8 @@ function storeData(userId) { */ function createToken({ params }) { const { username, name } = params; - const { redis, config } = this; - const context = { name, redis, config }; + const { redis, config, userData } = this; + const context = { name, redis, config, userData }; return Promise .bind(context, username) diff --git a/src/actions/token/erase.js b/src/actions/token/erase.js index a3081a93a..0ccf21b2a 100644 --- a/src/actions/token/erase.js +++ b/src/actions/token/erase.js @@ -35,8 +35,8 @@ function eraseData(userId) { */ function eraseToken({ params }) { const { username, token } = params; - const { redis, config } = this; - const context = { token, redis, config }; + const { redis, config, userData } = this; + const context = { token, redis, config, userData }; return Promise .bind(context, username) diff --git a/src/actions/token/list.js b/src/actions/token/list.js index 8c1f16613..6aeea82a1 100644 --- a/src/actions/token/list.js +++ b/src/actions/token/list.js @@ -81,9 +81,9 @@ function getList(userId) { */ function listTokens({ params }) { const { username, page, pageSize } = params; - const { redis, config } = this; + const { redis, config, userData } = this; const context = { - redis, config, page, pageSize, + redis, config, page, pageSize, userData, }; return Promise diff --git a/src/actions/updatePassword.js b/src/actions/updatePassword.js index 3a97fb5c2..3744883b2 100644 --- a/src/actions/updatePassword.js +++ b/src/actions/updatePassword.js @@ -1,7 +1,6 @@ const { HttpStatusError } = require('common-errors'); const scrypt = require('../utils/scrypt'); -const redisKey = require('../utils/key'); const jwt = require('../utils/jwt'); const { getInternalData } = require('../utils/userData'); const isActive = require('../utils/is-active'); @@ -9,9 +8,7 @@ const isBanned = require('../utils/is-banned'); const hasPassword = require('../utils/has-password'); const { getUserId } = require('../utils/userData'); const { - USERS_DATA, USERS_ACTION_RESET, - USERS_PASSWORD_FIELD, USERS_ID_FIELD, } = require('../constants'); const UserLoginRateLimiter = require('../utils/rate-limiters/user-login-rate-limiter'); @@ -44,10 +41,8 @@ async function usernamePasswordReset(service, username, password) { * @param {String} password */ async function setPassword(service, userId, password) { - const { redis } = service; const hash = await scrypt.hash(password); - - return redis.hset(redisKey(userId, USERS_DATA), USERS_PASSWORD_FIELD, hash); + return service.userData.setPassword(userId, hash); } /** diff --git a/src/auth/oauth/utils/attach.js b/src/auth/oauth/utils/attach.js index 0344b607f..0eb731469 100644 --- a/src/auth/oauth/utils/attach.js +++ b/src/auth/oauth/utils/attach.js @@ -1,10 +1,8 @@ const get = require('lodash/get'); -const redisKey = require('../../../utils/key'); const UserMetadata = require('../../../utils/metadata/user'); const handlePipeline = require('../../../utils/pipeline-error'); const { USERS_SSO_TO_ID, - USERS_DATA, } = require('../../../constants'); module.exports = async function attach(account, user) { @@ -14,11 +12,7 @@ module.exports = async function attach(account, user) { uid, provider, internals, profile, } = account; const audience = get(config, 'jwt.defaultAudience'); - const userDataKey = redisKey(userId, USERS_DATA); - const pipeline = redis.pipeline(); - - // inject private info to user internal data - pipeline.hset(userDataKey, provider, JSON.stringify(internals)); + const pipeline = this.userData.attachProvider(userId, provider, internals); // link uid to user id pipeline.hset(USERS_SSO_TO_ID, uid, userId); diff --git a/src/auth/oauth/utils/detach.js b/src/auth/oauth/utils/detach.js index 300a08468..f5b9e5d0b 100644 --- a/src/auth/oauth/utils/detach.js +++ b/src/auth/oauth/utils/detach.js @@ -1,21 +1,15 @@ const Errors = require('common-errors'); const get = require('../../../utils/get-value'); -const redisKey = require('../../../utils/key'); const UserMetadata = require('../../../utils/metadata/user'); const handlePipeline = require('../../../utils/pipeline-error'); -const { - USERS_SSO_TO_ID, - USERS_DATA, -} = require('../../../constants'); +const { USERS_SSO_TO_ID } = require('../../../constants'); module.exports = async function detach(provider, userData) { const { id: userId } = userData; const { redis, config } = this; const audience = get(config, 'jwt.defaultAudience'); - const userDataKey = redisKey(userId, USERS_DATA); - const pipeline = redis.pipeline(); const uid = get(userData, [provider, 'uid'], { default: false }); if (!uid) { @@ -23,7 +17,7 @@ module.exports = async function detach(provider, userData) { } // delete internal account data - pipeline.hdel(userDataKey, provider); + const pipeline = this.userData.delProvider(userId, provider); // delete account reference pipeline.hdel(USERS_SSO_TO_ID, uid); diff --git a/src/auth/oauth/utils/refresh.js b/src/auth/oauth/utils/refresh.js index 4aa47da8e..987cf4f82 100644 --- a/src/auth/oauth/utils/refresh.js +++ b/src/auth/oauth/utils/refresh.js @@ -1,13 +1,3 @@ -const redisKey = require('../../../utils/key'); -const { USERS_DATA } = require('../../../constants'); - -module.exports = function refresh(account, user) { - const { redis } = this; - const { userId } = user; - const { provider, internals } = account; - const userDataKey = redisKey(userId, USERS_DATA); - - return redis - .hset(userDataKey, provider, JSON.stringify(internals)) - .return(true); +module.exports = function refresh({ provider, internals }, { userId }) { + return this.userData.refresh(userId, provider, internals); }; diff --git a/src/migrations/05-referrals-users-ids/index.js b/src/migrations/05-referrals-users-ids/index.js index 12af467b7..631e21f24 100644 --- a/src/migrations/05-referrals-users-ids/index.js +++ b/src/migrations/05-referrals-users-ids/index.js @@ -2,6 +2,7 @@ const Promise = require('bluebird'); const { USERS_REFERRAL_INDEX } = require('../../constants.js'); const { getUserId } = require('../../utils/userData'); const getRedisMasterNode = require('../utils/get-redis-master-node'); +const UserData = require('../../../lib/utils/data/user'); /** * @@ -10,6 +11,7 @@ function referralsUsersIds({ redis, config, log }) { const { keyPrefix } = config.redis.options; const masterNode = getRedisMasterNode(redis, config); const pipeline = redis.pipeline(); + const userData = new UserData(redis); return masterNode .keys(`${keyPrefix}${USERS_REFERRAL_INDEX}:*`) @@ -28,7 +30,7 @@ function referralsUsersIds({ redis, config, log }) { (username) => { log.info('Resolve user id for:', username); - return Promise.join(username, getUserId.call({ redis }, username)); + return Promise.join(username, getUserId.call({ userData }, username)); } ) // swap username to user id diff --git a/src/users.js b/src/users.js index 83e4428eb..df8a53f29 100644 --- a/src/users.js +++ b/src/users.js @@ -10,6 +10,7 @@ const Flakeless = require('ms-flakeless'); const conf = require('./config'); const get = require('./utils/get-value'); const attachPasswordKeyword = require('./utils/password-validator'); +const UserData = require('./utils/data/user'); const { CloudflareWorker } = require('./utils/cloudflare/worker'); /** @@ -80,6 +81,7 @@ class Users extends Microfleet { const tmOpts = merge({}, config.tokenManager, tokenManagerOpts); this.tokenManager = new TokenManager(tmOpts); + this.userData = new UserData(redis); }); this.on('plugin:start:http', (server) => { @@ -100,6 +102,7 @@ class Users extends Microfleet { this.on(`plugin:close:${this.redisType}`, () => { this.dlock = null; this.tokenManager = null; + this.userData = null; }); // add migration connector diff --git a/src/utils/data/user.js b/src/utils/data/user.js new file mode 100644 index 000000000..a3997465d --- /dev/null +++ b/src/utils/data/user.js @@ -0,0 +1,111 @@ +const redisKey = require('../key.js'); +const { + USERS_DATA, + USERS_ACTIVE_FLAG, + USERS_BANNED_FLAG, + USERS_MFA_FLAG, + USERS_ALIAS_FIELD, + USERS_ALIAS_TO_ID, + USERS_SSO_TO_ID, + USERS_USERNAME_TO_ID, + USERS_PASSWORD_FIELD, +} = require('../../constants'); + +/** + * User data abstraction + */ +class UserData { + constructor(redis) { + this.redis = redis; + } + + static register(userId, pipeline, basicInfo, activate, deleteInactiveAccounts) { + const userDataKey = redisKey(userId, USERS_DATA); + pipeline.hmset(userDataKey, basicInfo); + if (activate === false && deleteInactiveAccounts >= 0) { + pipeline.expire(userDataKey, deleteInactiveAccounts); + } + } + + static setMFA(userId, pipeline, secret) { + return pipeline.hset(redisKey(userId, USERS_DATA), USERS_MFA_FLAG, secret); + } + + static delMFA(userId, pipeline) { + return pipeline.hdel(redisKey(userId, USERS_DATA), USERS_MFA_FLAG); + } + + static deleteUserData(userId, pipeline) { + pipeline.del(redisKey(userId, USERS_DATA)); + } + + lock(userId) { + return this.redis.pipeline().hset(redisKey(userId, USERS_DATA), USERS_BANNED_FLAG, 'true'); + } + + activate(userId) { + const userKey = redisKey(userId, USERS_DATA); + return this.redis.pipeline() + .hget(userKey, USERS_ACTIVE_FLAG) + .hset(userKey, USERS_ACTIVE_FLAG, 'true') + // WARNING: `persist` is very important, otherwise we will lose user's information in 30 days + // set to active & persist + .persist(userKey); + } + + unLock(userId) { + return this.redis.pipeline().hdel(redisKey(userId, USERS_DATA), USERS_BANNED_FLAG); + } + + refresh(userId, provider, internals) { + return this.redis.hset(redisKey(userId, USERS_DATA), provider, JSON.stringify(internals)).return(true); + } + + getMFA(userId) { + return this.redis.hget(redisKey(userId, USERS_DATA), USERS_MFA_FLAG); + } + + setAlias(userId, alias) { + return this.redis.pipeline().hset(redisKey(userId, USERS_DATA), USERS_ALIAS_FIELD, alias); + } + + delProvider(userId, provider) { + return this.redis.pipeline().hdel(redisKey(userId, USERS_DATA), provider); + } + + attachProvider(userId, provider, internals) { + // inject private info to user internal data + return this.redis.pipeline().hset(redisKey(userId, USERS_DATA), provider, JSON.stringify(internals)); + } + + setPassword(userId, password) { + return this.redis.hset(redisKey(userId, USERS_DATA), USERS_PASSWORD_FIELD, password); + } + + getBanned(userId) { + return this.redis.hget(redisKey(userId, USERS_DATA), USERS_BANNED_FLAG); + } + + registerInOrganization(userId, organizationData) { + return this.redis.pipeline().hmset(redisKey(userId, USERS_DATA), organizationData); + } + + resolveUserIdBuffer(id, fetchData) { + const indexPlaceholder = 'userId'; + const userDataIndex = redisKey(indexPlaceholder, USERS_DATA); + const numberOfKeys = 4; + return this.redis + .resolveUserIdBuffer( + numberOfKeys, + userDataIndex, + USERS_USERNAME_TO_ID, + USERS_ALIAS_TO_ID, + USERS_SSO_TO_ID, + id, + fetchData === true ? 1 : 0, + indexPlaceholder + ); + } +} + +module.exports = UserData; diff --git a/src/utils/mfa.js b/src/utils/mfa.js index b759c66ba..5013859c6 100644 --- a/src/utils/mfa.js +++ b/src/utils/mfa.js @@ -9,7 +9,6 @@ const { ErrorTotpRequired, ErrorTotpInvalid, ErrorSecretRequired, - USERS_DATA, USERS_MFA_FLAG, USERS_MFA_RECOVERY, MFA_TYPE_REQUIRED, @@ -31,8 +30,7 @@ function generateRecoveryCodes(length = 10) { * @returns {Boolean} */ async function isMFAEnabled(userId) { - const secret = await this.redis - .hget(redisKey(userId, USERS_DATA), USERS_MFA_FLAG); + const secret = await this.userData.getMFA(userId); if (secret) { return secret; diff --git a/src/utils/organization/get-organization-members.js b/src/utils/organization/get-organization-members.js index 6cb71e98f..961a30b5d 100644 --- a/src/utils/organization/get-organization-members.js +++ b/src/utils/organization/get-organization-members.js @@ -1,6 +1,6 @@ const Promise = require('bluebird'); const mapValues = require('lodash/mapValues'); -const { ORGANIZATIONS_MEMBERS, USERS_DATA, USERS_BANNED_FLAG } = require('../../constants'); +const { ORGANIZATIONS_MEMBERS } = require('../../constants'); const redisKey = require('../key'); const JSONParse = (d) => JSON.parse(d); @@ -8,7 +8,7 @@ const JSONParse = (d) => JSON.parse(d); async function getMemberData(organizationMemberId) { const [, , userId] = organizationMemberId.split('!'); const organization = await this.redis.hgetall(organizationMemberId); - const banned = await this.redis.hget(redisKey(userId, USERS_DATA), USERS_BANNED_FLAG); + const banned = await this.userData.getBanned(userId); return mapValues({ ...organization, banned }, JSONParse); } diff --git a/src/utils/organization/register-organization-members.js b/src/utils/organization/register-organization-members.js index c352d1f85..fedb61df4 100644 --- a/src/utils/organization/register-organization-members.js +++ b/src/utils/organization/register-organization-members.js @@ -1,7 +1,6 @@ /* eslint-disable no-mixed-operators */ const Promise = require('bluebird'); const generatePassword = require('password-generator'); -const redisKey = require('../key.js'); const handlePipeline = require('../pipeline-error'); const { USERS_CREATED_FIELD, @@ -9,7 +8,6 @@ const { USERS_ACTIVE_FLAG, USERS_PASSWORD_FIELD, USERS_ACTIVATED_FIELD, - USERS_DATA, USERS_USERNAME_TO_ID, USERS_INDEX, USERS_ID_FIELD, @@ -23,7 +21,6 @@ async function registerOrganizationMember(member) { const { email } = member; const userId = this.flake.next(); - const pipeline = redis.pipeline(); const createdAt = Date.now(); const basicInfo = { [USERS_CREATED_FIELD]: createdAt, @@ -33,8 +30,7 @@ async function registerOrganizationMember(member) { const password = member.password || generatePassword(pwdReset.length, pwdReset.memorable); basicInfo[USERS_PASSWORD_FIELD] = await scrypt.hash(password); - const userDataKey = redisKey(userId, USERS_DATA); - pipeline.hmset(userDataKey, basicInfo); + const pipeline = this.userData.registerInOrganization(userId, basicInfo); pipeline.hset(USERS_USERNAME_TO_ID, email, userId); handlePipeline(await pipeline.exec()); diff --git a/src/utils/userData/get-internal-data.js b/src/utils/userData/get-internal-data.js index 26f1f1704..9561577db 100644 --- a/src/utils/userData/get-internal-data.js +++ b/src/utils/userData/get-internal-data.js @@ -53,8 +53,8 @@ function reduceData(data) { } function getInternalData(userKey, fetchData = true) { - const { redis } = this; - const context = { redis, userKey }; + const { userData } = this; + const context = { userData, userKey }; return Promise .bind(context, [userKey, fetchData]) diff --git a/src/utils/userData/resolve-user-id.js b/src/utils/userData/resolve-user-id.js index 556c49fee..c091eab46 100644 --- a/src/utils/userData/resolve-user-id.js +++ b/src/utils/userData/resolve-user-id.js @@ -1,10 +1,5 @@ -const makeKey = require('../key.js'); const { USERS_ID_FIELD, - USERS_ALIAS_TO_ID, - USERS_DATA, - USERS_SSO_TO_ID, - USERS_USERNAME_TO_ID, } = require('../../constants'); function resolveUserData(response) { @@ -36,22 +31,7 @@ function resolveUserData(response) { * @returns {null|object} */ function resolveUserId(id, fetchData = false) { - const { redis } = this; - const indexPlaceholder = 'userId'; - const userDataIndex = makeKey(indexPlaceholder, USERS_DATA); - const numberOfKeys = 4; - - return redis - .resolveUserIdBuffer( - numberOfKeys, - userDataIndex, - USERS_USERNAME_TO_ID, - USERS_ALIAS_TO_ID, - USERS_SSO_TO_ID, - id, - fetchData === true ? 1 : 0, - indexPlaceholder - ) + return this.userData.resolveUserIdBuffer(id, fetchData) .then(resolveUserData); } From 8fd6b44e706befbe6f105c6bcd8feae504a25852 Mon Sep 17 00:00:00 2001 From: Oleg Tokar Date: Fri, 18 Jun 2021 07:01:25 +0300 Subject: [PATCH 2/2] feat: user data abstraction --- src/migrations/05-referrals-users-ids/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/migrations/05-referrals-users-ids/index.js b/src/migrations/05-referrals-users-ids/index.js index 631e21f24..a29a2b4fe 100644 --- a/src/migrations/05-referrals-users-ids/index.js +++ b/src/migrations/05-referrals-users-ids/index.js @@ -2,7 +2,7 @@ const Promise = require('bluebird'); const { USERS_REFERRAL_INDEX } = require('../../constants.js'); const { getUserId } = require('../../utils/userData'); const getRedisMasterNode = require('../utils/get-redis-master-node'); -const UserData = require('../../../lib/utils/data/user'); +const UserData = require('../../utils/data/user'); /** *