Skip to content

Commit 00112a0

Browse files
authored
[ENG-3054] Allow all users to view and manage subscriptions (#96)
* Allow all users view subscription * update tests * update required scopes * Show all subscriptions in unsubscribe menu action
1 parent 1359f62 commit 00112a0

File tree

6 files changed

+72
-74
lines changed

6 files changed

+72
-74
lines changed

manifest.yml

-4
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ oauth_config:
2222
redirect_urls:
2323
- https://major-cougar-adequately.ngrok-free.app/api/v1/auth/oauth
2424
scopes:
25-
user:
26-
- links:read
27-
- links:write
2825
bot:
2926
- channels:read
3027
- chat:write
@@ -40,7 +37,6 @@ settings:
4037
request_url: https://major-cougar-adequately.ngrok-free.app/api/v1/unfurl/action
4138
user_events:
4239
- app_uninstalled
43-
- link_shared
4440
- tokens_revoked
4541
bot_events:
4642
- link_shared

server/controllers/__test__/command.test.js

+9-18
Original file line numberDiff line numberDiff line change
@@ -241,27 +241,22 @@ describe("Test Auth controller methods", () => {
241241
});
242242

243243
it("should send appropiate message to slack when subscription is not present in channel", async done => {
244-
const userid = "userid";
245244
const channelid = "channelid";
246245
const cmd = "unsubscribe owner/datasetid";
247246
const responseUrl = "responseUrl";
248-
const token = "token";
249247

250248
helper.getSubscriptionStatus = jest.fn(() => [false, false]);
251249
slack.sendResponse = jest.fn(() => Promise.resolve());
252250

253251
await command.unsubscribeFromDatasetOrProject(
254-
userid,
255252
channelid,
256253
cmd,
257-
responseUrl,
258-
token
254+
responseUrl
259255
);
260256

261257
expect(helper.getSubscriptionStatus).toHaveBeenCalledWith(
262258
"owner/datasetid",
263-
channelid,
264-
userid
259+
channelid
265260
);
266261
expect(slack.sendResponse).toHaveBeenCalledWith(responseUrl, {
267262
replace_original: false,
@@ -275,11 +270,9 @@ describe("Test Auth controller methods", () => {
275270
it(
276271
"should send appropiate message to slack when unsubscribeFromDatasetOrProject fails",
277272
async done => {
278-
const userid = "userid";
279273
const channelid = "channelid";
280274
const cmd = "subscribe owner/datasetid";
281275
const responseUrl = "responseUrl";
282-
const token = "token";
283276
const error = new Error("Test - error");
284277
const data = {
285278
replace_original: false,
@@ -291,17 +284,14 @@ describe("Test Auth controller methods", () => {
291284
helper.getSubscriptionStatus = jest.fn(() => Promise.reject(error));
292285

293286
await command.unsubscribeFromDatasetOrProject(
294-
userid,
295287
channelid,
296288
cmd,
297289
responseUrl,
298-
token
299290
);
300291

301292
expect(helper.getSubscriptionStatus).toHaveBeenCalledWith(
302293
"owner/datasetid",
303294
channelid,
304-
userid
305295
);
306296

307297
expect(slack.sendResponse).toHaveBeenCalledWith(responseUrl, data);
@@ -314,7 +304,6 @@ describe("Test Auth controller methods", () => {
314304
it(
315305
"should unsubscribe from project",
316306
async done => {
317-
const userid = "userid";
318307
const channelId = "channelid";
319308
const cmd = "subscribe owner/datasetid";
320309
const responseUrl = "responseUrl";
@@ -336,7 +325,6 @@ describe("Test Auth controller methods", () => {
336325

337326
await command.unsubscribeFromProject(
338327
channelId,
339-
userid,
340328
cmd,
341329
responseUrl,
342330
token
@@ -353,34 +341,37 @@ describe("Test Auth controller methods", () => {
353341
it(
354342
"should unsubscribe from account",
355343
async done => {
356-
const userid = "userid";
357344
const cmd = "subscribe agentid";
358345
const responseUrl = "responseUrl";
359346
const channelid = "channelid";
360-
const token = "token";
361347
const message = "No problem! You'll no longer receive notifications about *agentid* here.";
362348
const data = { message };
363349
const slackData = {
364350
replace_original: false,
365351
delete_original: false,
366352
text: message
367353
};
354+
const user = { dwAccessToken: "dwAccessToken" };
355+
const subscription = { slackUserId: "slackUserId" };
368356

357+
Subscription.findOne = jest.fn(() => Promise.resolve({ subscription }));
358+
User.findOne = jest.fn(() => Promise.resolve({ user }));
369359
Subscription.destroy = jest.fn(() => Promise.resolve());
360+
370361
helper.getSubscriptionStatus = jest.fn(() => [true, true]);
371362
dataworld.unsubscribeFromAccount = jest.fn(() =>
372363
Promise.resolve({ data })
373364
);
374365
slack.sendResponse = jest.fn(() => Promise.resolve());
375366

376367
await command.unsubscribeFromAccount(
377-
userid,
378368
channelid,
379369
cmd,
380370
responseUrl,
381-
token
382371
);
383372
expect(helper.getSubscriptionStatus).toHaveBeenCalledTimes(1);
373+
expect(User.findOne).toHaveBeenCalledTimes(1);
374+
expect(Subscription.findOne).toHaveBeenCalledTimes(1);
384375
expect(Subscription.destroy).toHaveBeenCalledTimes(1);
385376
expect(dataworld.unsubscribeFromAccount).toHaveBeenCalledTimes(1);
386377
expect(slack.sendResponse).toHaveBeenCalledWith(responseUrl, slackData);

server/controllers/command.js

+51-45
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,11 @@ const subscribeToAccount = async (
208208
};
209209

210210
const unsubscribeFromDatasetOrProject = async (
211-
userId,
212211
channelid,
213212
command,
214-
responseUrl,
215-
token
213+
responseUrl
216214
) => {
215+
let token;
217216
try {
218217
const commandText = process.env.SLASH_COMMAND;
219218

@@ -223,10 +222,23 @@ const unsubscribeFromDatasetOrProject = async (
223222
const [
224223
hasSubscriptionInChannel,
225224
removeDWSubscription
226-
] = await helper.getSubscriptionStatus(resourceId, channelid, userId);
225+
] = await helper.getSubscriptionStatus(resourceId, channelid);
227226

228227
// If subscription belongs to channel and the actor(user), then go ahead and unsubscribe
229228
if (hasSubscriptionInChannel) {
229+
const channelSubscription = await Subscription.findOne({
230+
where: {
231+
resourceId: `${commandParams.owner}/${commandParams.id}`,
232+
channelId: channelid
233+
}
234+
});
235+
236+
const user = await User.findOne({
237+
where: { slackId: channelSubscription.slackUserId }
238+
});
239+
240+
token = user.dwAccessToken;
241+
230242
// will be true if user subscribed to this resource in one channel
231243
if (removeDWSubscription) {
232244
// use dataworld wrapper to unsubscribe from dataset
@@ -241,7 +253,6 @@ const unsubscribeFromDatasetOrProject = async (
241253
await removeSubscriptionRecord(
242254
commandParams.owner,
243255
commandParams.id,
244-
userId,
245256
channelid
246257
);
247258
// send successful unsubscription message to Slack
@@ -259,7 +270,6 @@ const unsubscribeFromDatasetOrProject = async (
259270
console.warn("Failed to unsubscribe from dataset : ", error.message);
260271
// Handle as project
261272
await unsubscribeFromProject(
262-
userId,
263273
channelid,
264274
command,
265275
responseUrl,
@@ -269,7 +279,6 @@ const unsubscribeFromDatasetOrProject = async (
269279
};
270280

271281
const unsubscribeFromProject = async (
272-
userId,
273282
channelId,
274283
command,
275284
responseUrl,
@@ -282,7 +291,7 @@ const unsubscribeFromProject = async (
282291
const [
283292
hasSubscriptionInChannel,
284293
removeDWSubscription
285-
] = await helper.getSubscriptionStatus(resourceId, channelId, userId);
294+
] = await helper.getSubscriptionStatus(resourceId, channelId);
286295

287296
if (removeDWSubscription) {
288297
await dataworld.unsubscribeFromProject(
@@ -295,7 +304,6 @@ const unsubscribeFromProject = async (
295304
await removeSubscriptionRecord(
296305
commandParams.owner,
297306
commandParams.id,
298-
userId,
299307
channelId
300308
);
301309
// send successful unsubscription message to Slack
@@ -314,11 +322,9 @@ const unsubscribeFromProject = async (
314322
};
315323

316324
const unsubscribeFromAccount = async (
317-
userId,
318325
channelid,
319326
command,
320-
responseUrl,
321-
token
327+
responseUrl
322328
) => {
323329
const commandText = process.env.SLASH_COMMAND;
324330

@@ -328,16 +334,26 @@ const unsubscribeFromAccount = async (
328334
const [
329335
hasSubscriptionInChannel,
330336
removeDWSubscription
331-
] = await helper.getSubscriptionStatus(resourceId, channelid, userId);
337+
] = await helper.getSubscriptionStatus(resourceId, channelid);
332338
if (hasSubscriptionInChannel) {
333339
try {
340+
const channelSubscription = await Subscription.findOne({
341+
where: {
342+
resourceId: `${commandParams.owner}/${commandParams.id}`,
343+
channelId: channelid
344+
}
345+
});
346+
347+
const user = await User.findOne({
348+
where: { slackId: channelSubscription.slackUserId }
349+
});
350+
334351
if (removeDWSubscription) {
335-
await dataworld.unsubscribeFromAccount(commandParams.id, token);
352+
await dataworld.unsubscribeFromAccount(commandParams.id, user.dwAccessToken);
336353
}
337354
await removeSubscriptionRecord(
338355
commandParams.owner,
339356
commandParams.id,
340-
userId,
341357
channelid
342358
);
343359
// send successful unsubscription message to Slack
@@ -373,10 +389,6 @@ const listSubscription = async (
373389
where: { channelId: channelid }
374390
});
375391

376-
const user = await User.findOne({
377-
where: { slackId: userId }
378-
});
379-
380392
let message;
381393
let blocks;
382394
let options = [];
@@ -388,6 +400,10 @@ const listSubscription = async (
388400
await Promise.all(
389401
subscriptions.map(async subscription => {
390402
try {
403+
const user = await User.findOne({
404+
where: { slackId: subscription.slackUserId }
405+
});
406+
391407
let isProject = false;
392408
if (subscription.resourceId.includes("/")) {
393409
const data = subscription.resourceId.split("/");
@@ -410,15 +426,13 @@ const listSubscription = async (
410426
isProject
411427
);
412428
if (existsInDW) {
413-
if (subscription.slackUserId === userId) {
414-
options.push({
415-
"text": {
416-
"type": "plain_text",
417-
"text": subscription.resourceId
418-
},
419-
"value": subscription.resourceId
420-
});
421-
}
429+
options.push({
430+
"text": {
431+
"type": "plain_text",
432+
"text": subscription.resourceId
433+
},
434+
"value": subscription.resourceId
435+
});
422436
blockText += `• ${baseUrl}/${subscription.resourceId
423437
} \n *created by :* <@${subscription.slackUserId}> \n`;
424438
}
@@ -520,11 +534,11 @@ const addSubscriptionRecord = async (owner, id, userId, channelId) => {
520534
}
521535
};
522536

523-
const removeSubscriptionRecord = async (owner, id, userId, channelId) => {
537+
const removeSubscriptionRecord = async (owner, id, channelId) => {
524538
// delete subscription
525539
const resourceId = owner ? `${owner}/${id}` : `${id}`;
526540
await Subscription.destroy({
527-
where: { resourceId: resourceId, slackUserId: userId, channelId: channelId }
541+
where: { resourceId: resourceId, channelId: channelId }
528542
});
529543
};
530544

@@ -622,20 +636,16 @@ const subscribeOrUnsubscribe = (req, token) => {
622636
break;
623637
case UNSUBSCRIBE_DATASET_OR_PROJECT:
624638
unsubscribeFromDatasetOrProject(
625-
req.body.user_id,
626639
req.body.channel_id,
627640
command,
628-
responseUrl,
629-
token
641+
responseUrl
630642
);
631643
break;
632644
case UNSUBSCRIBE_ACCOUNT:
633645
unsubscribeFromAccount(
634-
req.body.user_id,
635646
req.body.channel_id,
636647
command,
637-
responseUrl,
638-
token
648+
responseUrl
639649
);
640650
break;
641651
default:
@@ -721,29 +731,25 @@ const handleButtonAction = async (payload, action, user) => {
721731
}
722732
};
723733

724-
const handleMenuAction = async (payload, action, user) => {
734+
const handleMenuAction = async (payload, action) => {
725735
if (action.action_id === "unsubscribe_menu") {
726736
const value = action.selected_option.value;
727737
if (value.includes("/")) {
728738
//unsubscribe from project of dataset
729739
await unsubscribeFromDatasetOrProject(
730-
payload.user.id,
731740
payload.channel.id,
732741
`unsubscribe ${value}`,
733-
payload.response_url,
734-
user.dwAccessToken
742+
payload.response_url
735743
);
736744
} else {
737745
// unsubscribe from account
738746
await unsubscribeFromAccount(
739-
payload.user.id,
740747
payload.channel.id,
741748
`unsubscribe ${value}`,
742-
payload.response_url,
743-
user.dwAccessToken
749+
payload.response_url
744750
);
745751
}
746-
// Update list of subscriptions
752+
// Updated list of subscriptions
747753
await listSubscription(
748754
payload.response_url,
749755
payload.channel.id,
@@ -801,7 +807,7 @@ const performAction = async (req, res) => {
801807
if (action.type === "button") {
802808
await handleButtonAction(payload, action, user);
803809
} else if (action.type === "static_select") {
804-
await handleMenuAction(payload, action, user);
810+
await handleMenuAction(payload, action);
805811
} else {
806812
console.warn("Unknown action type : ", action.action_id)
807813
}

0 commit comments

Comments
 (0)