Skip to content

Commit f07b724

Browse files
committed
feat: check proposal limits
1 parent 82e38a1 commit f07b724

File tree

5 files changed

+96
-15
lines changed

5 files changed

+96
-15
lines changed

src/helpers/options.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,24 @@ export async function getLimit(key: string): Promise<number> {
1111
export async function getList(key: string): Promise<string[]> {
1212
return (await getOption(key))?.value?.split(',') || [];
1313
}
14+
15+
export async function getSpaceType(
16+
space: {
17+
verified: boolean;
18+
turbo: boolean;
19+
flagged: boolean;
20+
id: string;
21+
},
22+
withEcosystem = false
23+
) {
24+
let type = 'default';
25+
26+
if (withEcosystem && (await getList('space.ecosystem.list')).includes(space.id)) {
27+
type = 'ecosystem';
28+
}
29+
if (space.flagged) type = 'flagged';
30+
if (space.verified) type = 'verified';
31+
if (space.turbo) type = 'turbo';
32+
33+
return type;
34+
}

src/writer/proposal.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import log from '../helpers/log';
77
import { containsFlaggedLinks, flaggedAddresses } from '../helpers/moderation';
88
import { isMalicious } from '../helpers/monitoring';
99
import db from '../helpers/mysql';
10-
import { getLimit, getList } from '../helpers/options';
10+
import { getLimit, getSpaceType } from '../helpers/options';
1111
import { captureError, getQuorum, jsonParse, validateChoices } from '../helpers/utils';
1212

1313
const scoreAPIUrl = process.env.SCORE_API_URL || 'https://score.snapshot.org';
@@ -17,16 +17,7 @@ export async function getSpaceProposalsLimits(
1717
space: { verified: boolean; turbo: boolean; flagged: boolean; id: string },
1818
interval: 'day' | 'month'
1919
): Promise<number> {
20-
let type = 'default';
21-
22-
if ((await getList('space.ecosystem.list')).includes(space.id)) {
23-
type = 'ecosystem';
24-
}
25-
if (space.flagged) type = 'flagged';
26-
if (space.verified) type = 'verified';
27-
if (space.turbo) type = 'turbo';
28-
29-
return getLimit(`space.${type}.proposal_limit_per_${interval}`);
20+
return getLimit(`space.${await getSpaceType(space, true)}.proposal_limit_per_${interval}`);
3021
}
3122

3223
export const getProposalsCount = async (space, author) => {
@@ -217,6 +208,16 @@ export async function verify(body): Promise<any> {
217208
capture(e);
218209
return Promise.reject('failed to check proposals limit');
219210
}
211+
212+
const bodyLengthLimit = await getLimit(`space.${await getSpaceType(space)}.body_limit`);
213+
if (msg.payload.body.length > bodyLengthLimit) {
214+
return Promise.reject(`proposal body length can not exceed ${bodyLengthLimit} characters`);
215+
}
216+
217+
const choicesLimit = await getLimit(`space.${await getSpaceType(space)}.choices_limit`);
218+
if (msg.payload.choices.length > choicesLimit) {
219+
return Promise.reject(`number of choices can not exceed ${choicesLimit}`);
220+
}
220221
}
221222

222223
export async function action(body, ipfs, receipt, id): Promise<void> {

src/writer/settings.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import isEqual from 'lodash/isEqual';
44
import { addOrUpdateSpace, getSpace } from '../helpers/actions';
55
import log from '../helpers/log';
66
import db from '../helpers/mysql';
7-
import { getLimit } from '../helpers/options';
7+
import { getLimit, getSpaceType } from '../helpers/options';
88
import { clearStampCache, DEFAULT_NETWORK, jsonParse } from '../helpers/utils';
99

1010
const SNAPSHOT_ENV = process.env.NETWORK || 'testnet';
@@ -74,9 +74,7 @@ export async function verify(body): Promise<any> {
7474
return Promise.reject(e);
7575
}
7676

77-
const strategiesLimit = await getLimit(
78-
`space.${space.turbo ? 'turbo' : 'default'}.strategies_limit`
79-
);
77+
const strategiesLimit = await getLimit(`space.${await getSpaceType(space)}.strategies_limit`);
8078

8179
if (msg.payload.strategies.length > strategiesLimit) {
8280
return Promise.reject(`max number of strategies is ${strategiesLimit}`);

test/unit/writer/proposal.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,29 @@ const LIMITS = {
99
'space.active_proposal_limit_per_author': 20,
1010
'space.ecosystem.proposal_limit_per_day': 150,
1111
'space.ecosystem.proposal_limit_per_month': 750,
12+
'space.ecosystem.choices_limit': 20,
13+
'space.ecosystem.body_length': 10000,
14+
'space.ecosystem.strategies_limit': 8,
1215
'space.flagged.proposal_limit_per_day': 5,
1316
'space.flagged.proposal_limit_per_month': 7,
17+
'space.flagged.choices_limit': 20,
18+
'space.flagged.body_length': 10000,
19+
'space.flagged.strategies_limit': 8,
1420
'space.default.proposal_limit_per_day': 10,
1521
'space.default.proposal_limit_per_month': 150,
22+
'space.default.choices_limit': 20,
23+
'space.default.body_length': 10000,
24+
'space.default.strategies_limit': 8,
1625
'space.turbo.proposal_limit_per_day': 40,
1726
'space.turbo.proposal_limit_per_month': 200,
27+
'space.turbo.choices_limit': 1000,
28+
'space.turbo.body_length': 40000,
29+
'space.turbo.strategies_limit': 8,
1830
'space.verified.proposal_limit_per_day': 20,
1931
'space.verified.proposal_limit_per_month': 100,
32+
'space.verified.choices_limit': 20,
33+
'space.verified.body_length': 10000,
34+
'space.verified.strategies_limit': 6,
2035
'user.default.follow.limit': 25
2136
};
2237
const ECOSYSTEM_LIST = ['test.eth', 'snapshot.eth'];

test/unit/writer/settings.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,52 @@ function randomStrategies(count = 1) {
1818
}));
1919
}
2020

21+
const LIMITS = {
22+
'space.active_proposal_limit_per_author': 20,
23+
'space.ecosystem.proposal_limit_per_day': 150,
24+
'space.ecosystem.proposal_limit_per_month': 750,
25+
'space.ecosystem.choices_limit': 20,
26+
'space.ecosystem.body_length': 10000,
27+
'space.ecosystem.strategies_limit': 8,
28+
'space.flagged.proposal_limit_per_day': 5,
29+
'space.flagged.proposal_limit_per_month': 7,
30+
'space.flagged.choices_limit': 20,
31+
'space.flagged.body_length': 10000,
32+
'space.flagged.strategies_limit': 8,
33+
'space.default.proposal_limit_per_day': 10,
34+
'space.default.proposal_limit_per_month': 150,
35+
'space.default.choices_limit': 20,
36+
'space.default.body_length': 10000,
37+
'space.default.strategies_limit': 8,
38+
'space.turbo.proposal_limit_per_day': 40,
39+
'space.turbo.proposal_limit_per_month': 200,
40+
'space.turbo.choices_limit': 1000,
41+
'space.turbo.body_length': 40000,
42+
'space.turbo.strategies_limit': 10,
43+
'space.verified.proposal_limit_per_day': 20,
44+
'space.verified.proposal_limit_per_month': 100,
45+
'space.verified.choices_limit': 20,
46+
'space.verified.body_length': 10000,
47+
'space.verified.strategies_limit': 6,
48+
'user.default.follow.limit': 25
49+
};
50+
const ECOSYSTEM_LIST = ['test.eth', 'snapshot.eth'];
51+
52+
jest.mock('../../../src/helpers/options', () => {
53+
const originalModule = jest.requireActual('../../../src/helpers/options');
54+
55+
return {
56+
__esModule: true,
57+
...originalModule,
58+
getList: () => {
59+
return ECOSYSTEM_LIST;
60+
},
61+
getLimit: (key: string) => {
62+
return LIMITS[key];
63+
}
64+
};
65+
});
66+
2167
// eslint-disable-next-line @typescript-eslint/no-unused-vars
2268
const mockGetSpace = jest.fn((_): any => {
2369
return spacesGetSpaceFixtures;

0 commit comments

Comments
 (0)