/packages/node_modules/@webex/internal-plugin-conversation/test/integration/spec/encryption.js

https://github.com/ciscospark/spark-js-sdk · JavaScript · 269 lines · 238 code · 27 blank · 4 comment · 5 complexity · 7c3a7c9d1698232ca57c59626e966b33 MD5 · raw file

  1. /*!
  2. * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
  3. */
  4. import WebexCore, {WebexHttpError} from '@webex/webex-core';
  5. import {assert, expect} from '@webex/test-helper-chai';
  6. import testUsers from '@webex/test-helper-test-users';
  7. describe('plugin-conversation', () => {
  8. let checkov, mccoy, participants, webex, spock;
  9. before(() => testUsers.create({count: 3})
  10. .then((users) => {
  11. participants = [spock, mccoy, checkov] = users;
  12. webex = new WebexCore({
  13. credentials: {
  14. authorization: spock.token
  15. }
  16. });
  17. return webex.internal.mercury.connect();
  18. }));
  19. after(() => webex && webex.internal.mercury.disconnect());
  20. describe('when not supplying enough encryption data', () => {
  21. let conversation;
  22. before(() => webex.internal.conversation.create({participants, comment: 'first'})
  23. .then((c) => {
  24. conversation = c;
  25. }));
  26. it('fetches the conversation and does not alter its key', () => webex.internal.conversation.post({url: conversation.url}, {displayName: 'second'})
  27. .then(() => webex.internal.conversation.get(conversation))
  28. .then((c) => assert.equal(c.defaultActivityEncryptionKeyUrl, conversation.defaultActivityEncryptionKeyUrl)));
  29. });
  30. describe('when interacting with a non-encrypted conversation', () => {
  31. before(() => {
  32. mccoy.webex = new WebexCore({
  33. credentials: {
  34. authorization: mccoy.token
  35. }
  36. });
  37. checkov.webex = new WebexCore({
  38. credentials: {
  39. authorization: checkov.token
  40. }
  41. });
  42. return Promise.all([
  43. checkov.webex.internal.mercury.connect(),
  44. mccoy.webex.internal.mercury.connect()
  45. ]);
  46. });
  47. after(() => Promise.all([
  48. checkov && checkov.webex && checkov.webex.internal.mercury.disconnect(),
  49. mccoy && mccoy.webex && mccoy.webex.internal.mercury.disconnect()
  50. ]));
  51. let conversation;
  52. beforeEach(() => webex.request({
  53. method: 'POST',
  54. service: 'conversation',
  55. resource: '/conversations',
  56. noTransform: true,
  57. body: {
  58. objectType: 'conversation',
  59. activities: {
  60. items: [
  61. {
  62. verb: 'create',
  63. actor: {
  64. id: spock.id,
  65. objectType: 'person'
  66. }
  67. },
  68. {
  69. verb: 'add',
  70. actor: {
  71. id: spock.id,
  72. objectType: 'person'
  73. },
  74. object: {
  75. id: spock.id,
  76. objectType: 'person'
  77. }
  78. },
  79. {
  80. verb: 'add',
  81. actor: {
  82. id: spock.id,
  83. objectType: 'person'
  84. },
  85. object: {
  86. id: checkov.id,
  87. objectType: 'person'
  88. }
  89. }
  90. ]
  91. }
  92. }
  93. })
  94. .then((res) => res.body)
  95. .then((c) => {
  96. conversation = c;
  97. assert.notProperty(conversation, 'defaultActivityEncryptionKeyUrl');
  98. }));
  99. describe('when the conversation is a grouped conversation', () => {
  100. describe('#add()', () => {
  101. it('adds the specified user', () => webex.internal.conversation.add(conversation, mccoy)
  102. .then(() => mccoy.webex.internal.conversation.get(conversation))
  103. .then((c) => assert.property(c, 'defaultActivityEncryptionKeyUrl', 'The conversation was encrypted as a side effect of the add activity')));
  104. });
  105. describe('#leave()', () => {
  106. it('removes the current user', () => webex.internal.conversation.leave(conversation)
  107. .then(() => assert.isRejected(webex.internal.conversation.get(conversation)))
  108. .then((reason) => assert.instanceOf(reason, WebexHttpError.NotFound))
  109. .then(() => checkov.webex.internal.conversation.get(conversation))
  110. .then((c) => assert.notProperty(c, 'defaultActivityEncryptionKeyUrl', 'The conversation was not encrypted as a side effect of the leave activity')));
  111. it('removes the specified user', () => webex.internal.conversation.leave(conversation, checkov)
  112. .then(() => assert.isRejected(checkov.webex.internal.conversation.get(conversation)))
  113. .then((reason) => assert.instanceOf(reason, WebexHttpError.NotFound))
  114. .then(() => webex.internal.conversation.get(conversation))
  115. .then((c) => assert.notProperty(c, 'defaultActivityEncryptionKeyUrl', 'The conversation was not encrypted as a side effect of the leave activity')));
  116. });
  117. describe('#post()', () => {
  118. it('posts a message', () => webex.internal.conversation.post(conversation, {displayName: 'Ahoy'})
  119. .then(() => checkov.webex.internal.conversation.get(conversation, {activitiesLimit: 1}))
  120. .then((c) => {
  121. assert.property(c, 'defaultActivityEncryptionKeyUrl');
  122. assert.equal(c.activities.items[0].object.displayName, 'Ahoy');
  123. }));
  124. });
  125. describe('#cardAction()', () => {
  126. it('creates a cardAction Activity', () => webex.internal.conversation.post(conversation, {displayName: 'First Message', cards: ['test']})
  127. .then(() => checkov.webex.internal.conversation.get(conversation, {activitiesLimit: 1}))
  128. .then((c) => {
  129. assert.property(c, 'defaultActivityEncryptionKeyUrl');
  130. assert.equal(c.activities.items[0].object.displayName, 'First Message');
  131. webex.internal.conversation.cardAction(conversation, {
  132. objectType: 'submit',
  133. inputs: {key: 'value'}
  134. }, c.activities.items[0])
  135. .then(() => checkov.webex.internal.conversation.get(conversation, {activitiesLimit: 1}))
  136. .then((ci) => {
  137. assert.property(c, 'defaultActivityEncryptionKeyUrl');
  138. /* eslint-disable no-unused-expressions */
  139. expect(ci.activities.items[0].object.inputs).to.not.be.null;
  140. });
  141. }));
  142. });
  143. describe('#update()', () => {
  144. it('sets the conversation\'s title', () => webex.internal.conversation.update(conversation, {
  145. displayName: 'New Name!',
  146. objectType: 'conversation'
  147. })
  148. .then(() => checkov.webex.internal.conversation.get(conversation))
  149. .then((c) => {
  150. assert.property(c, 'defaultActivityEncryptionKeyUrl');
  151. assert.property(c, 'encryptionKeyUrl');
  152. assert.equal(c.displayName, 'New Name!');
  153. }));
  154. });
  155. describe('#updateKey()', () => {
  156. it('sets the conversation\'s defaultActivityEncryptionKeyUrl', () => webex.internal.conversation.updateKey(conversation)
  157. .then(() => webex.internal.conversation.get(conversation))
  158. .then((c) => {
  159. assert.property(c, 'defaultActivityEncryptionKeyUrl');
  160. })
  161. .then(() => checkov.webex.internal.conversation.get(conversation))
  162. .then((c) => {
  163. assert.property(c, 'defaultActivityEncryptionKeyUrl');
  164. }));
  165. it('unsets the conversations\'s defaultActivityEncryptionKeyUrl', () => webex.internal.conversation.updateKey(conversation, {uri: null})
  166. .then(() => checkov.webex.internal.conversation.get(conversation))
  167. .then((c) => {
  168. assert.isUndefined(c.defaultActivityEncryptionKeyUrl);
  169. }));
  170. describe('when the KMS key has been unset', () => {
  171. it('rotates the key and sends the post', () => webex.internal.conversation.updateKey(conversation, {uri: null})
  172. .then(() => webex.internal.conversation.post(conversation, {displayName: 'Ahoy'}))
  173. .then(() => checkov.webex.internal.conversation.get(conversation, {activitiesLimit: 1}))
  174. .then((c) => {
  175. assert.property(c, 'defaultActivityEncryptionKeyUrl');
  176. assert.equal(c.activities.items[0].object.displayName, 'Ahoy');
  177. }));
  178. });
  179. });
  180. });
  181. describe('when the conversation is a 1:1 conversation', () => {
  182. let conversation;
  183. beforeEach(() => webex.request({
  184. method: 'POST',
  185. service: 'conversation',
  186. resource: '/conversations',
  187. noTransform: true,
  188. body: {
  189. objectType: 'conversation',
  190. activities: {
  191. items: [
  192. {
  193. verb: 'create',
  194. actor: {
  195. id: spock.id,
  196. objectType: 'person'
  197. }
  198. },
  199. {
  200. verb: 'add',
  201. actor: {
  202. id: spock.id,
  203. objectType: 'person'
  204. },
  205. object: {
  206. id: spock.id,
  207. objectType: 'person'
  208. }
  209. },
  210. {
  211. verb: 'add',
  212. actor: {
  213. id: spock.id,
  214. objectType: 'person'
  215. },
  216. object: {
  217. id: mccoy.id,
  218. objectType: 'person'
  219. }
  220. }
  221. ]
  222. },
  223. tags: ['ONE_ON_ONE']
  224. }
  225. })
  226. .then((res) => res.body)
  227. .then((c) => {
  228. conversation = c;
  229. assert.notProperty(conversation, 'defaultActivityEncryptionKeyUrl');
  230. assert.include(c.tags, 'ONE_ON_ONE');
  231. }));
  232. describe('#post()', () => {
  233. it('posts a message', () => webex.internal.conversation.post(conversation, {displayName: 'First Message'})
  234. .then(() => mccoy.webex.internal.conversation.get(conversation, {activitiesLimit: 1}))
  235. .then((c) => {
  236. assert.property(c, 'defaultActivityEncryptionKeyUrl');
  237. assert.equal(c.activities.items[0].object.displayName, 'First Message');
  238. }));
  239. });
  240. });
  241. });
  242. });