From 363bb37d424106ef4143690b211c909a5e3b87d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro?= Date: Fri, 21 Jan 2022 18:31:52 -0300 Subject: [PATCH 1/2] add filter login inactivity --- packages/api/src/controllers/community.ts | 4 +++ packages/core/src/config/index.ts | 2 ++ packages/core/src/config/validatenv.ts | 1 + packages/core/src/services/endpoints.ts | 1 + packages/core/src/services/ubi/beneficiary.ts | 12 ++++++++ packages/core/src/services/ubi/managers.ts | 8 +++--- .../tests/integration/beneficiary.test.ts | 28 +++++++++++++++++++ .../core/tests/integration/community.test.ts | 2 +- 8 files changed, 53 insertions(+), 5 deletions(-) diff --git a/packages/api/src/controllers/community.ts b/packages/api/src/controllers/community.ts index 954d00cdf..8889fdd3a 100644 --- a/packages/api/src/controllers/community.ts +++ b/packages/api/src/controllers/community.ts @@ -74,6 +74,7 @@ class CommunityController { inactivity, unidentified, blocked, + loginInactivity, } = req.query; if (search === undefined || typeof search !== 'string') { throw new Error('invalid search!'); @@ -85,6 +86,7 @@ class CommunityController { inactivity: inactivity === 'true', unidentified: unidentified === 'true', blocked: blocked === 'true', + loginInactivity: loginInactivity === 'true', }) .then((r) => standardResponse(res, 200, true, r)) .catch((e) => @@ -99,6 +101,7 @@ class CommunityController { inactivity, unidentified, blocked, + loginInactivity, } = req.query; if (active === undefined || typeof active !== 'string') { active = 'true'; @@ -119,6 +122,7 @@ class CommunityController { inactivity: inactivity === 'true', unidentified: unidentified === 'true', blocked: blocked === 'true', + loginInactivity: loginInactivity === 'true', } ) .then((r) => standardResponse(res, 200, true, r)) diff --git a/packages/core/src/config/index.ts b/packages/core/src/config/index.ts index 3f0cd010c..ba40a0eff 100644 --- a/packages/core/src/config/index.ts +++ b/packages/core/src/config/index.ts @@ -245,6 +245,8 @@ export default { claimLocationTimeframe: validatedEnv.CLAIM_LOCATION_TIMEFRAME, claimInactivityThreshold: validatedEnv.CLAIM_INACTIVITY_THRESHOLD, + loginInactivityThreshold: validatedEnv.LOGIN_INACTIVITY_THRESHOLD, + defaultLimit: validatedEnv.DEFAULT_LIMIT, defaultOffset: validatedEnv.DEFAULT_OFFSET, diff --git a/packages/core/src/config/validatenv.ts b/packages/core/src/config/validatenv.ts index 59b5ecd48..c988dc3cb 100644 --- a/packages/core/src/config/validatenv.ts +++ b/packages/core/src/config/validatenv.ts @@ -85,6 +85,7 @@ function validateEnv() { COMMUNITY_ADMIN_ADDRESS: str({ devDefault: onlyOnTestEnv('xyz') }), CLAIM_LOCATION_TIMEFRAME: num({ default: 150 }), CLAIM_INACTIVITY_THRESHOLD: num({ default: 4 }), + LOGIN_INACTIVITY_THRESHOLD: num({ default: 10 }), DEFAULT_LIMIT: num({ default: 10 }), DEFAULT_OFFSET: num({ default: 0 }), ENABLED_CACHE_WITH_REDIS: bool({ default: true }), diff --git a/packages/core/src/services/endpoints.ts b/packages/core/src/services/endpoints.ts index 16992697a..2ef87bb6f 100644 --- a/packages/core/src/services/endpoints.ts +++ b/packages/core/src/services/endpoints.ts @@ -268,6 +268,7 @@ export type BeneficiaryFilterType = { active?: boolean; suspect?: boolean; inactivity?: boolean; + loginInactivity?: boolean; unidentified?: boolean; blocked?: boolean; }; diff --git a/packages/core/src/services/ubi/beneficiary.ts b/packages/core/src/services/ubi/beneficiary.ts index 62adf8b8d..0c2dc24d0 100644 --- a/packages/core/src/services/ubi/beneficiary.ts +++ b/packages/core/src/services/ubi/beneficiary.ts @@ -349,6 +349,18 @@ export default class BeneficiaryService { }; } + if (filter.loginInactivity) { + const date = new Date(); + date.setDate(date.getDate() - config.loginInactivityThreshold); + + where = { + ...where, + '$"user"."lastLogin"$': { + [Op.lt]: date, + }, + }; + } + return where; } diff --git a/packages/core/src/services/ubi/managers.ts b/packages/core/src/services/ubi/managers.ts index 63d2eea60..65ed584dc 100644 --- a/packages/core/src/services/ubi/managers.ts +++ b/packages/core/src/services/ubi/managers.ts @@ -84,14 +84,14 @@ export default class ManagerService { from manager m, manager mq left join "app_user" u on u.address = mq."address" where mq.active = true and m."communityId" = mq."communityId" and m."address" = :managerAddress and mq."address" = :address order by mq."createdAt" desc - ` + `; return await this.sequelize.query(query, { type: QueryTypes.SELECT, replacements: { managerAddress, address, - } + }, }); } @@ -126,7 +126,7 @@ export default class ManagerService { order by mq."createdAt" desc offset :offset limit :limit - ` + `; return await this.sequelize.query(query, { type: QueryTypes.SELECT, @@ -134,7 +134,7 @@ export default class ManagerService { managerAddress, offset, limit, - } + }, }); } diff --git a/packages/core/tests/integration/beneficiary.test.ts b/packages/core/tests/integration/beneficiary.test.ts index 5915effd1..291a4def0 100644 --- a/packages/core/tests/integration/beneficiary.test.ts +++ b/packages/core/tests/integration/beneficiary.test.ts @@ -5,6 +5,7 @@ import { Sequelize } from 'sequelize'; import { assert, spy, replace, restore, SinonSpy } from 'sinon'; import tk from 'timekeeper'; +import config from '../../src/config'; import { models, sequelize as database } from '../../src/database'; import { ManagerAttributes } from '../../src/database/models/ubi/manager'; import { AppUser } from '../../src/interfaces/app/appUser'; @@ -376,6 +377,33 @@ describe('beneficiary service', () => { expect(result.length).to.be.equal(1); expect(result[0].address).to.be.equal(listUsers[4].address); }); + + it('should list suspect and login inactive beneficiaries', async () => { + const date = new Date(); + date.setDate(date.getDate() - config.loginInactivityThreshold); + + await sequelize.models.AppUserModel.update( + { + suspect: true, + lastLogin: date, + }, + { where: { address: listUsers[0].address } } + ); + const result = await BeneficiaryService.list( + listManagers[0].address, + 0, + 5, + { + suspect: true, + loginInactivity: true, + } + ); + + expect(result.length).to.be.equal(1); + expect(result[0].address).to.be.equal(listUsers[0].address); + // eslint-disable-next-line no-unused-expressions + expect(result[0].suspect).to.be.true; + }); }); describe('search', () => { diff --git a/packages/core/tests/integration/community.test.ts b/packages/core/tests/integration/community.test.ts index 2b5a3c8b0..c8586adfa 100644 --- a/packages/core/tests/integration/community.test.ts +++ b/packages/core/tests/integration/community.test.ts @@ -1,3 +1,4 @@ +import { cronJobs } from '@impactmarket/worker'; import { expect } from 'chai'; import faker from 'faker'; import { Sequelize } from 'sequelize'; @@ -11,7 +12,6 @@ import { CommunityContentStorage } from '../../src/services/storage'; import BeneficiaryService from '../../src/services/ubi/beneficiary'; import CommunityService from '../../src/services/ubi/community'; import ManagerService from '../../src/services/ubi/managers'; -import { cronJobs } from '@impactmarket/worker'; import { sequelizeSetup, truncate } from '../config/sequelizeSetup'; import { randomTx } from '../config/utils'; import BeneficiaryFactory from '../factories/beneficiary'; From 502771df6f0b7469915555226430aff7bac9eca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro?= Date: Fri, 21 Jan 2022 18:52:23 -0300 Subject: [PATCH 2/2] add comment in loginInactivityThreshold --- packages/core/src/config/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/core/src/config/index.ts b/packages/core/src/config/index.ts index ba40a0eff..7a6b19072 100644 --- a/packages/core/src/config/index.ts +++ b/packages/core/src/config/index.ts @@ -245,6 +245,9 @@ export default { claimLocationTimeframe: validatedEnv.CLAIM_LOCATION_TIMEFRAME, claimInactivityThreshold: validatedEnv.CLAIM_INACTIVITY_THRESHOLD, + /** + * Days without login to consider a user inactive + */ loginInactivityThreshold: validatedEnv.LOGIN_INACTIVITY_THRESHOLD, defaultLimit: validatedEnv.DEFAULT_LIMIT,