From 2394cb15266d826be8923facef49a7d5438fd778 Mon Sep 17 00:00:00 2001 From: sky3d Date: Fri, 21 Apr 2023 14:54:52 +0300 Subject: [PATCH 1/5] fix: sort organizations by id as big number --- package.json | 1 + pnpm-lock.yaml | 6 +++ src/actions/organization/list.js | 10 +++++ test/suites/actions/organization/list.js | 56 ++++++++++++++++++++++++ 4 files changed, 73 insertions(+) diff --git a/package.json b/package.json index 1a3ba0bb4..6a618c75f 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "ajv-formats": "^2.1.1", "async": "^3.2.4", "bluebird": "^3.7.2", + "bn.js": "^5.2.1", "bytes": "^3.1.2", "camelcase": "^7.0.1", "cluster-key-slot": "^1.1.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cf95f6f1c..8f1dfde8b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,6 +39,7 @@ specifiers: apidoc-plugin-schema: ^0.1.8 async: ^3.2.4 bluebird: ^3.7.2 + bn.js: ^5.2.1 bytes: ^3.1.2 c8: ^7.13.0 camelcase: ^7.0.1 @@ -133,6 +134,7 @@ dependencies: ajv-formats: 2.1.1 async: 3.2.4 bluebird: 3.7.2 + bn.js: 5.2.1 bytes: 3.1.2 camelcase: 7.0.1 cluster-key-slot: 1.1.2 @@ -2885,6 +2887,10 @@ packages: /bluebird/3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + /bn.js/5.2.1: + resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + dev: false + /boolbase/1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: true diff --git a/src/actions/organization/list.js b/src/actions/organization/list.js index 9dd721992..7447310f6 100644 --- a/src/actions/organization/list.js +++ b/src/actions/organization/list.js @@ -1,5 +1,6 @@ const Promise = require('bluebird'); const fsort = require('redis-filtered-sort'); +const BN = require('bn.js'); const { ActionTransport } = require('@microfleet/plugin-router'); @@ -9,6 +10,9 @@ const getMetadata = require('../../utils/get-metadata'); const { getUserId } = require('../../utils/userData'); const { ORGANIZATIONS_INDEX, ORGANIZATIONS_DATA } = require('../../constants'); +const bnCompAsc = (a, b) => new BN(a, 10).cmp(new BN(b, 10)); +const bnCompDesc = (a, b) => new BN(b, 10).cmp(new BN(a, 10)); + async function findUserOrganization(userId) { const { audience: orgAudience } = this.config.organizations; @@ -112,6 +116,12 @@ async function getOrganizationsList({ params }) { expiration, }); + // Additional comparison of ids as big numbers + if (criteria === 'id') { + const fn = order === 'DESC' ? bnCompDesc : bnCompAsc; + organizationsIds.sort(fn); + } + const organizations = await Promise.map(organizationsIds, async (organizationId) => { const getMember = userId ? [getOrganizationMemberDetails.call(this, organizationId, userId)] : []; diff --git a/test/suites/actions/organization/list.js b/test/suites/actions/organization/list.js index fab6e73f5..8d74eecb1 100644 --- a/test/suites/actions/organization/list.js +++ b/test/suites/actions/organization/list.js @@ -1,4 +1,5 @@ const Promise = require('bluebird'); +const BN = require('bn.js'); const { strict: assert } = require('assert'); const { expect } = require('chai'); const times = require('lodash/times'); @@ -102,4 +103,59 @@ describe('#organizations list', function registerSuite() { assert(member.attributes.joinedAt); }); }); + + it('sort organizations by id asc', async function test() { + const opts = { + criteria: 'id', + }; + + const jobs = []; + const organizationsLength = 5; + + times(organizationsLength - 1, () => { + jobs.push(createOrganization.call(this)); + }); + + await Promise.all(jobs); + + return this.users.dispatch('organization.list', { params: opts }) + .then(({ data }) => { + assert(data.length); + + for (let i = 1; i < data.length; i += 1) { + const prev = new BN(data[i - 1].id, 10); + const next = new BN(data[i].id, 10); + + assert(next.gt(prev)); + } + }); + }); + + it('sort organizations by id desc', async function test() { + const opts = { + criteria: 'id', + order: 'DESC', + }; + + const jobs = []; + const organizationsLength = 5; + + times(organizationsLength - 1, () => { + jobs.push(createOrganization.call(this)); + }); + + await Promise.all(jobs); + + return this.users.dispatch('organization.list', { params: opts }) + .then(({ data }) => { + assert(data.length); + + for (let i = 1; i < data.length; i += 1) { + const prev = new BN(data[i - 1].id, 10); + const next = new BN(data[i].id, 10); + + assert(next.lt(prev)); + } + }); + }); }); From 27945eb30c3d83e2f604f1bf893aa3c0c81de960 Mon Sep 17 00:00:00 2001 From: sky3d Date: Fri, 21 Apr 2023 16:52:08 +0300 Subject: [PATCH 2/5] fix: use constant for organization id field --- src/actions/organization/list.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/actions/organization/list.js b/src/actions/organization/list.js index 7447310f6..dca42d5c1 100644 --- a/src/actions/organization/list.js +++ b/src/actions/organization/list.js @@ -8,7 +8,7 @@ const redisKey = require('../../utils/key'); const { getOrganizationMetadata, getInternalData, getOrganizationMemberDetails } = require('../../utils/organization'); const getMetadata = require('../../utils/get-metadata'); const { getUserId } = require('../../utils/userData'); -const { ORGANIZATIONS_INDEX, ORGANIZATIONS_DATA } = require('../../constants'); +const { ORGANIZATIONS_INDEX, ORGANIZATIONS_DATA, ORGANIZATIONS_ID_FIELD } = require('../../constants'); const bnCompAsc = (a, b) => new BN(a, 10).cmp(new BN(b, 10)); const bnCompDesc = (a, b) => new BN(b, 10).cmp(new BN(a, 10)); @@ -117,7 +117,7 @@ async function getOrganizationsList({ params }) { }); // Additional comparison of ids as big numbers - if (criteria === 'id') { + if (criteria === ORGANIZATIONS_ID_FIELD) { const fn = order === 'DESC' ? bnCompDesc : bnCompAsc; organizationsIds.sort(fn); } From 7760765c3577d99bb33a39be58259f932bbea0b9 Mon Sep 17 00:00:00 2001 From: sky3d Date: Sat, 22 Apr 2023 14:16:18 +0300 Subject: [PATCH 3/5] fix: replace bn.js with BigInt --- .eslintrc | 3 ++ package.json | 1 - pnpm-lock.yaml | 6 ---- src/actions/organization/list.js | 7 ++--- src/utils/big-int.js | 14 +++++++++ test/suites/actions/organization/list.js | 37 +++++++----------------- 6 files changed, 29 insertions(+), 39 deletions(-) create mode 100644 src/utils/big-int.js diff --git a/.eslintrc b/.eslintrc index e85530705..5dda881cb 100644 --- a/.eslintrc +++ b/.eslintrc @@ -3,6 +3,9 @@ "parserOptions": { "ecmaVersion": 2021 }, + "env": { + "es2020": true + }, "rules": { "prefer-destructuring": ["error", { "VariableDeclarator": { diff --git a/package.json b/package.json index 6a618c75f..1a3ba0bb4 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "ajv-formats": "^2.1.1", "async": "^3.2.4", "bluebird": "^3.7.2", - "bn.js": "^5.2.1", "bytes": "^3.1.2", "camelcase": "^7.0.1", "cluster-key-slot": "^1.1.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8f1dfde8b..cf95f6f1c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,7 +39,6 @@ specifiers: apidoc-plugin-schema: ^0.1.8 async: ^3.2.4 bluebird: ^3.7.2 - bn.js: ^5.2.1 bytes: ^3.1.2 c8: ^7.13.0 camelcase: ^7.0.1 @@ -134,7 +133,6 @@ dependencies: ajv-formats: 2.1.1 async: 3.2.4 bluebird: 3.7.2 - bn.js: 5.2.1 bytes: 3.1.2 camelcase: 7.0.1 cluster-key-slot: 1.1.2 @@ -2887,10 +2885,6 @@ packages: /bluebird/3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} - /bn.js/5.2.1: - resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} - dev: false - /boolbase/1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: true diff --git a/src/actions/organization/list.js b/src/actions/organization/list.js index dca42d5c1..7aba4cd0f 100644 --- a/src/actions/organization/list.js +++ b/src/actions/organization/list.js @@ -1,6 +1,5 @@ const Promise = require('bluebird'); const fsort = require('redis-filtered-sort'); -const BN = require('bn.js'); const { ActionTransport } = require('@microfleet/plugin-router'); @@ -9,9 +8,7 @@ const { getOrganizationMetadata, getInternalData, getOrganizationMemberDetails } const getMetadata = require('../../utils/get-metadata'); const { getUserId } = require('../../utils/userData'); const { ORGANIZATIONS_INDEX, ORGANIZATIONS_DATA, ORGANIZATIONS_ID_FIELD } = require('../../constants'); - -const bnCompAsc = (a, b) => new BN(a, 10).cmp(new BN(b, 10)); -const bnCompDesc = (a, b) => new BN(b, 10).cmp(new BN(a, 10)); +const { bigIntComparerDesc, bigIntComparerAsc } = require('../../utils/big-int'); async function findUserOrganization(userId) { const { audience: orgAudience } = this.config.organizations; @@ -118,7 +115,7 @@ async function getOrganizationsList({ params }) { // Additional comparison of ids as big numbers if (criteria === ORGANIZATIONS_ID_FIELD) { - const fn = order === 'DESC' ? bnCompDesc : bnCompAsc; + const fn = order === 'DESC' ? bigIntComparerDesc : bigIntComparerAsc; organizationsIds.sort(fn); } diff --git a/src/utils/big-int.js b/src/utils/big-int.js new file mode 100644 index 000000000..10449dce7 --- /dev/null +++ b/src/utils/big-int.js @@ -0,0 +1,14 @@ +function bigIntComparer(a, b) { + const sign = BigInt(a) - BigInt(b); + + if (sign === 0) { + return 0; + } + + return sign < 0 ? -1 : 1; +} + +module.exports = { + bigIntComparerAsc: bigIntComparer, + bigIntComparerDesc: (a, b) => bigIntComparer(b, a), +}; diff --git a/test/suites/actions/organization/list.js b/test/suites/actions/organization/list.js index 8d74eecb1..24c27f04b 100644 --- a/test/suites/actions/organization/list.js +++ b/test/suites/actions/organization/list.js @@ -1,5 +1,4 @@ const Promise = require('bluebird'); -const BN = require('bn.js'); const { strict: assert } = require('assert'); const { expect } = require('chai'); const times = require('lodash/times'); @@ -104,13 +103,13 @@ describe('#organizations list', function registerSuite() { }); }); - it('sort organizations by id asc', async function test() { + it('sort organizations by id ASC/DESC', async function test() { const opts = { criteria: 'id', }; const jobs = []; - const organizationsLength = 5; + const organizationsLength = 10; times(organizationsLength - 1, () => { jobs.push(createOrganization.call(this)); @@ -118,43 +117,27 @@ describe('#organizations list', function registerSuite() { await Promise.all(jobs); - return this.users.dispatch('organization.list', { params: opts }) + await this.users.dispatch('organization.list', { params: opts }) .then(({ data }) => { assert(data.length); for (let i = 1; i < data.length; i += 1) { - const prev = new BN(data[i - 1].id, 10); - const next = new BN(data[i].id, 10); + const prev = BigInt(data[i - 1].id); + const next = BigInt(data[i].id); - assert(next.gt(prev)); + assert(next > prev); } }); - }); - - it('sort organizations by id desc', async function test() { - const opts = { - criteria: 'id', - order: 'DESC', - }; - - const jobs = []; - const organizationsLength = 5; - times(organizationsLength - 1, () => { - jobs.push(createOrganization.call(this)); - }); - - await Promise.all(jobs); - - return this.users.dispatch('organization.list', { params: opts }) + return this.users.dispatch('organization.list', { params: { ...opts, order: 'DESC' } }) .then(({ data }) => { assert(data.length); for (let i = 1; i < data.length; i += 1) { - const prev = new BN(data[i - 1].id, 10); - const next = new BN(data[i].id, 10); + const prev = BigInt(data[i - 1].id); + const next = BigInt(data[i].id); - assert(next.lt(prev)); + assert(next < prev); } }); }); From c3d1578e97960980edd6f5f3e0456e603c73b0fc Mon Sep 17 00:00:00 2001 From: sky3d Date: Sat, 22 Apr 2023 14:43:56 +0300 Subject: [PATCH 4/5] fix: improve bigInt comparision --- src/utils/big-int.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/utils/big-int.js b/src/utils/big-int.js index 10449dce7..0963af23e 100644 --- a/src/utils/big-int.js +++ b/src/utils/big-int.js @@ -1,11 +1,13 @@ +const ZERO = BigInt(0); + function bigIntComparer(a, b) { - const sign = BigInt(a) - BigInt(b); + const diff = BigInt(a) - BigInt(b); - if (sign === 0) { + if (diff === ZERO) { return 0; } - return sign < 0 ? -1 : 1; + return diff < ZERO ? -1 : 1; } module.exports = { From c16ccb2a267009154caacaad949ecf21dfce08a1 Mon Sep 17 00:00:00 2001 From: sky3d Date: Sat, 22 Apr 2023 15:10:58 +0300 Subject: [PATCH 5/5] test: temporary skip /bypass/masters --- test/suites/actions/bypass/masters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suites/actions/bypass/masters.js b/test/suites/actions/bypass/masters.js index ec59230ea..60895ef3f 100644 --- a/test/suites/actions/bypass/masters.js +++ b/test/suites/actions/bypass/masters.js @@ -15,7 +15,7 @@ const mastersSimulation = got.extend({ }, }); -describe('/bypass/masters', function verifySuite() { +describe.skip('/bypass/masters', function verifySuite() { const pwd = process.env.MASTERS_PROFILE_PASSWORD; const username = process.env.MASTERS_PROFILE_USERNAME; let msg;