Skip to content

Commit 3d7c8df

Browse files
committed
feat: add update-subscription writer
1 parent 5866dbb commit 3d7c8df

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

src/writer/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import * as subscribe from './subscribe';
1212
import * as unfollow from './unfollow';
1313
import * as unsubscribe from './unsubscribe';
1414
import * as updateProposal from './update-proposal';
15+
import * as updateSubscription from './update-subscription';
1516
import * as vote from './vote';
1617

1718
export default {
@@ -26,6 +27,7 @@ export default {
2627
unfollow,
2728
subscribe,
2829
unsubscribe,
30+
'update-subscription': updateSubscription,
2931
'delete-subscription': deleteSubscription,
3032
alias,
3133
profile,

src/writer/update-subscription.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { envelopDB } from '../helpers/mysql';
2+
import { jsonParse } from '../helpers/utils';
3+
4+
type Message = { msg: string; from: string };
5+
6+
const VALID_SUBSCRIPTIONS = ['summary', 'newProposal', 'closedProposal'];
7+
8+
function extractPayload(message: Message): { subscriptions: string[] } {
9+
return jsonParse(message.msg).payload;
10+
}
11+
12+
export async function verify(message: Message): Promise<any> {
13+
const result = await envelopDB.queryAsync(`SELECT * FROM subscribers WHERE address = ? LIMIT 1`, [
14+
message.from
15+
]);
16+
17+
if (!result[0]) {
18+
return Promise.reject('user not subscribed');
19+
}
20+
21+
if (!result[0].verified) {
22+
return Promise.reject('email not verified');
23+
}
24+
25+
const { subscriptions } = extractPayload(message);
26+
if (subscriptions.some(s => !VALID_SUBSCRIPTIONS.includes(s))) {
27+
return Promise.reject('invalid subscription value');
28+
}
29+
30+
return result[0];
31+
}
32+
33+
export async function action(message: Message): Promise<void> {
34+
const { subscriptions } = extractPayload(message);
35+
36+
await envelopDB.queryAsync(`UPDATE subscribers SET subscriptions = ? WHERE address = ? LIMIT 1`, [
37+
JSON.stringify(subscriptions),
38+
message.from
39+
]);
40+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import db, { envelopDB, sequencerDB } from '../../../src/helpers/mysql';
2+
import { action, verify } from '../../../src/writer/update-subscription';
3+
4+
describe('writer/update-subscription', () => {
5+
const TEST_PREFIX = 'test-update-subscription';
6+
7+
afterAll(async () => {
8+
await envelopDB.queryAsync('DELETE FROM subscribers');
9+
await envelopDB.endAsync();
10+
await db.endAsync();
11+
await sequencerDB.endAsync();
12+
});
13+
14+
describe('verify()', () => {
15+
const msg = JSON.stringify({ payload: { subscriptions: ['closedProposal'] } });
16+
const msgWithInvalidSubscriptions = JSON.stringify({
17+
payload: { subscriptions: ['test'] }
18+
});
19+
20+
beforeAll(async () => {
21+
await Promise.all([
22+
envelopDB.queryAsync(
23+
'INSERT INTO subscribers SET address = ?, email = ?, subscriptions = ?, created = ?, verified = ?',
24+
[`${TEST_PREFIX}-0x0`, '[email protected]', '[]', 0, 0]
25+
),
26+
envelopDB.queryAsync(
27+
'INSERT INTO subscribers SET address = ?, email = ?, subscriptions = ?, created = ?, verified = ?',
28+
[`${TEST_PREFIX}-0x1`, '[email protected]', '[]', 0, 1]
29+
)
30+
]);
31+
});
32+
33+
it('rejects when the address is not subscribed', () => {
34+
return expect(verify({ from: '0x0', msg })).rejects.toEqual(`user not subscribed`);
35+
});
36+
37+
it('rejects when the address is not verified', () => {
38+
return expect(verify({ from: `${TEST_PREFIX}-0x0`, msg })).rejects.toEqual(
39+
`email not verified`
40+
);
41+
});
42+
43+
it('rejects when subscription values are not valid', () => {
44+
return expect(
45+
verify({ from: `${TEST_PREFIX}-0x1`, msg: msgWithInvalidSubscriptions })
46+
).rejects.toEqual(`invalid subscription value`);
47+
});
48+
49+
it('resolves when all args are valid', () => {
50+
return expect(verify({ from: `${TEST_PREFIX}-0x1`, msg })).resolves.toHaveProperty('address');
51+
});
52+
});
53+
54+
describe('action()', () => {
55+
const address = `${TEST_PREFIX}-0x3`;
56+
const subscriptions = ['newProposal', 'closedProposal'];
57+
58+
beforeAll(async () => {
59+
await envelopDB.queryAsync(
60+
'INSERT INTO subscribers SET address = ?, email = ?, subscriptions = ?, created = ?, verified = ?',
61+
[address, '[email protected]', '["summary"]', 0, 1]
62+
);
63+
});
64+
65+
it('updates the subscription', async () => {
66+
await action({
67+
from: address,
68+
msg: JSON.stringify({ payload: { subscriptions } })
69+
});
70+
71+
const result = await envelopDB.queryAsync(
72+
`SELECT subscriptions FROM subscribers WHERE address = ? LIMIT 1`,
73+
[address]
74+
);
75+
76+
expect(JSON.parse(result[0].subscriptions)).toEqual(subscriptions);
77+
});
78+
});
79+
});

0 commit comments

Comments
 (0)