@instructure/canvas-rce 5.8.0 → 5.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## 5.9.0 - 2023-08-30
9
+
10
+ ### Fixed
11
+ - An issue where LTI postMessages were not working inside active RCE
12
+
13
+ ### Changed
14
+ - Encrypt auto-saved RCE content
15
+ - Remove dependency on `@instructure/filter-console-messages`
16
+
8
17
  ## 5.8.0 - 2023-08-15
9
18
 
10
19
  ### Fixed
@@ -2373,6 +2373,7 @@ import { rceWrapperPropTypes } from './RCEWrapperProps';
2373
2373
  import { insertPlaceholder, placeholderInfoFor, removePlaceholder } from '../util/loadingPlaceholder';
2374
2374
  import { transformRceContentForEditing } from './transformContent';
2375
2375
  import { IconMoreSolid } from '@instructure/ui-icons/es/svg';
2376
+ import EncryptedStorage from '../util/encrypted-storage';
2376
2377
  import buildStyle from './style';
2377
2378
  const RestoreAutoSaveModal = /*#__PURE__*/React.lazy(() => import('./RestoreAutoSaveModal'));
2378
2379
  const RceHtmlEditor = /*#__PURE__*/React.lazy(() => import('./RceHtmlEditor'));
@@ -2713,9 +2714,48 @@ class RCEWrapper extends React.Component {
2713
2714
 
2714
2715
  this.checkAccessibility();
2715
2716
  this.fixToolbarKeyboardNavigation();
2717
+ this.forwardPostMessages();
2716
2718
  (_this$props$onInitted = (_this$props = this.props).onInitted) === null || _this$props$onInitted === void 0 ? void 0 : _this$props$onInitted.call(_this$props, editor);
2717
2719
  };
2718
2720
 
2721
+ this.forwardPostMessages = () => {
2722
+ const windowReferences = {};
2723
+ const rceWindow = this.editor.getWin(); // explicitly assign name for reference by parent window
2724
+
2725
+ rceWindow.name = `${RCEWrapper.editorFrameName}_${this.id}`;
2726
+ rceWindow.addEventListener('message', this.forwardPostMessagesHandler(rceWindow, windowReferences));
2727
+ };
2728
+
2729
+ this.forwardPostMessagesHandler = (rceWindow, windowReferences) => e => {
2730
+ let message;
2731
+
2732
+ try {
2733
+ message = typeof e.data === 'string' ? JSON.parse(e.data) : e.data;
2734
+ } catch (err) {
2735
+ // unparseable message may not be meant for our handlers
2736
+ return false;
2737
+ }
2738
+
2739
+ if (e.origin === rceWindow.origin) {
2740
+ // message is from Canvas window, forward to tool
2741
+ const targetOrigin = message.toolOrigin;
2742
+
2743
+ if (!targetOrigin) {
2744
+ return false;
2745
+ }
2746
+
2747
+ const targetWindow = windowReferences[targetOrigin];
2748
+ delete message.toolOrigin;
2749
+ targetWindow === null || targetWindow === void 0 ? void 0 : targetWindow.postMessage(message, targetOrigin);
2750
+ } else {
2751
+ // message is from tool, forward to Canvas window
2752
+ windowReferences[e.origin] = e.source;
2753
+ message.toolOrigin = e.origin;
2754
+ message.frameName = rceWindow.name;
2755
+ rceWindow.parent.postMessage(message, rceWindow.origin);
2756
+ }
2757
+ };
2758
+
2719
2759
  this.fixToolbarKeyboardNavigation = () => {
2720
2760
  var _this$_elementRef$cur2;
2721
2761
 
@@ -2787,7 +2827,9 @@ class RCEWrapper extends React.Component {
2787
2827
  this.announcing = 0;
2788
2828
 
2789
2829
  this.initAutoSave = editor => {
2790
- this.storage = window.localStorage;
2830
+ var _this$props$userCache;
2831
+
2832
+ this.storage = new EncryptedStorage((_this$props$userCache = this.props.userCacheKey) !== null && _this$props$userCache !== void 0 ? _this$props$userCache : '');
2791
2833
 
2792
2834
  if (this.storage) {
2793
2835
  editor.on('change Undo Redo', this.doAutoSave);
@@ -2875,10 +2917,7 @@ class RCEWrapper extends React.Component {
2875
2917
  });
2876
2918
 
2877
2919
  try {
2878
- _this.storage.setItem(_this.autoSaveKey, JSON.stringify({
2879
- autosaveTimestamp: Date.now(),
2880
- content
2881
- }));
2920
+ _this.storage.setItem(_this.autoSaveKey, content);
2882
2921
  } catch (ex) {
2883
2922
  if (!retry) {
2884
2923
  // probably failed because there's not enough space
@@ -3733,7 +3772,7 @@ class RCEWrapper extends React.Component {
3733
3772
  let autosaved = null;
3734
3773
 
3735
3774
  try {
3736
- autosaved = this.storage && JSON.parse(this.storage.getItem(key));
3775
+ autosaved = this.storage && this.storage.getItem(key);
3737
3776
  } catch (_ex) {
3738
3777
  this.storage.removeItem(this.autoSaveKey);
3739
3778
  }
@@ -4199,6 +4238,7 @@ RCEWrapper.defaultProps = {
4199
4238
  canvasOrigin: ''
4200
4239
  };
4201
4240
  RCEWrapper.skinCssInjected = false;
4241
+ RCEWrapper.editorFrameName = 'active_rce_frame';
4202
4242
 
4203
4243
  function mergeMenuItems(standard, custom) {
4204
4244
  var _custom$trim;
@@ -125,5 +125,6 @@ export const rceWrapperPropTypes = {
125
125
  features: PropTypes.objectOf(PropTypes.bool),
126
126
  flashAlertTimeout: PropTypes.number,
127
127
  timezone: PropTypes.string,
128
+ userCacheKey: PropTypes.string,
128
129
  externalToolsConfig: externalToolsConfigPropType
129
130
  };
@@ -0,0 +1,124 @@
1
+ /*
2
+ * Copyright (C) 2023 - present Instructure, Inc.
3
+ *
4
+ * This file is part of Canvas.
5
+ *
6
+ * Canvas is free software: you can redistribute it and/or modify it under
7
+ * the terms of the GNU Affero General Public License as published by the Free
8
+ * Software Foundation, version 3 of the License.
9
+ *
10
+ * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
11
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
+ * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
+ * details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License along
16
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+ export default {
19
+ lib: {
20
+ Base: {},
21
+ WordArray: {},
22
+ BufferedBlockAlgorithm: {},
23
+ Hasher: {},
24
+ Cipher: {},
25
+ StreamCipher: {},
26
+ BlockCipherMode: {},
27
+ BlockCipher: {},
28
+ CipherParams: {},
29
+ SerializableCipher: {},
30
+ PasswordBasedCipher: {}
31
+ },
32
+ x64: {
33
+ Word: {},
34
+ WordArray: {}
35
+ },
36
+ enc: {
37
+ Hex: {},
38
+ Latin1: {},
39
+ Utf8: {
40
+ parse: () => {}
41
+ },
42
+ Utf16: {},
43
+ Utf16BE: {},
44
+ Utf16LE: {},
45
+ Base64: {},
46
+ Base64url: {}
47
+ },
48
+ algo: {
49
+ HMAC: {},
50
+ MD5: {},
51
+ SHA1: {},
52
+ SHA224: {},
53
+ SHA256: {},
54
+ SHA384: {},
55
+ SHA512: {},
56
+ SHA3: {},
57
+ RIPEMD160: {},
58
+ PBKDF2: {},
59
+ EvpKDF: {},
60
+ AES: {},
61
+ DES: {},
62
+ TripleDES: {},
63
+ Rabbit: {},
64
+ RabbitLegacy: {},
65
+ RC4: {},
66
+ RC4Drop: {},
67
+ Blowfish: {}
68
+ },
69
+ mode: {
70
+ CBC: {},
71
+ CFB: {},
72
+ CTR: {},
73
+ CTRGladman: {},
74
+ ECB: {},
75
+ OFB: {}
76
+ },
77
+ pad: {
78
+ Pkcs7: {},
79
+ AnsiX923: {},
80
+ Iso10126: {},
81
+ Iso97971: {},
82
+ NoPadding: {},
83
+ ZeroPadding: {}
84
+ },
85
+ format: {
86
+ OpenSSL: {},
87
+ Hex: {}
88
+ },
89
+ kdf: {
90
+ OpenSSL: {}
91
+ },
92
+ MD5: {},
93
+ HmacMD5: {},
94
+ SHA1: {},
95
+ HmacSHA1: {},
96
+ SHA224: {},
97
+ HmacSHA224: {},
98
+ SHA256: {},
99
+ HmacSHA256: {},
100
+ SHA384: {},
101
+ HmacSHA384: {},
102
+ SHA512: {},
103
+ HmacSHA512: {},
104
+ SHA3: {},
105
+ HmacSHA3: {},
106
+ RIPEMD160: {},
107
+ HmacRIPEMD160: {},
108
+ PBKDF2: {},
109
+ EvpKDF: {},
110
+ AES: {},
111
+ DES: {},
112
+ TripleDES: {},
113
+ Rabbit: {},
114
+ RabbitLegacy: {},
115
+ RC4: {
116
+ encrypt: () => {},
117
+ decrypt: () => {}
118
+ },
119
+ RC4Drop: {
120
+ encrypt: () => {},
121
+ decrypt: () => {}
122
+ },
123
+ Blowfish: {}
124
+ };
@@ -45,6 +45,9 @@ const locale = {
45
45
  "add_image_60b2de07": {
46
46
  "message": "Tilføj billede"
47
47
  },
48
+ "add_one_9e34a6f8": {
49
+ "message": "Tilføj en!"
50
+ },
48
51
  "additional_considerations_f3801683": {
49
52
  "message": "Yderligere overvejelser"
50
53
  },
@@ -1323,9 +1326,27 @@ const locale = {
1323
1326
  "no_accessibility_issues_were_detected_f8d3c875": {
1324
1327
  "message": "Der blev ikke fundet nogen tilgængelighedsproblemer."
1325
1328
  },
1329
+ "no_announcements_created_yet_c44a94f4": {
1330
+ "message": "Der er ikke oprettet beskeder endnu."
1331
+ },
1332
+ "no_announcements_found_20185afc": {
1333
+ "message": "Ingen beskeder fundet."
1334
+ },
1335
+ "no_assignments_created_yet_1b236d87": {
1336
+ "message": "Der er ikke oprettet opgaver endnu."
1337
+ },
1338
+ "no_assignments_found_79e46d7f": {
1339
+ "message": "Ingen opgaver fundet."
1340
+ },
1326
1341
  "no_changes_to_save_d29f6e91": {
1327
1342
  "message": "Ingen ændringer at gemme."
1328
1343
  },
1344
+ "no_discussions_created_yet_ff99abe3": {
1345
+ "message": "Der er ikke oprettet diskussioner endnu."
1346
+ },
1347
+ "no_discussions_found_9284063b": {
1348
+ "message": "Ingen diskussioner fundet."
1349
+ },
1329
1350
  "no_e16d9132": {
1330
1351
  "message": "Nej"
1331
1352
  },
@@ -1335,9 +1356,27 @@ const locale = {
1335
1356
  "no_headers_9bc7dc7f": {
1336
1357
  "message": "Ingen overskrifter"
1337
1358
  },
1359
+ "no_modules_created_yet_c71b6d4d": {
1360
+ "message": "Der er ikke oprettet forløb endnu."
1361
+ },
1362
+ "no_modules_found_2df43a40": {
1363
+ "message": "Ingen forløb fundet."
1364
+ },
1365
+ "no_pages_created_yet_c379fa6e": {
1366
+ "message": "Der er ikke oprettet sider endnu."
1367
+ },
1368
+ "no_pages_found_6799350": {
1369
+ "message": "Ingen sider fundet."
1370
+ },
1338
1371
  "no_preview_is_available_for_this_file_f940114a": {
1339
1372
  "message": "Der findes ikke forhåndsvisning for denne fil."
1340
1373
  },
1374
+ "no_quizzes_created_yet_1a2370b9": {
1375
+ "message": "Der er ikke oprettet nogen quizzer endnu."
1376
+ },
1377
+ "no_quizzes_found_c80c537a": {
1378
+ "message": "Der er ikke fundet nogen quizzer."
1379
+ },
1341
1380
  "no_results_940393cf": {
1342
1381
  "message": "Ingen resultater."
1343
1382
  },
@@ -45,6 +45,9 @@ const locale = {
45
45
  "add_image_60b2de07": {
46
46
  "message": "Lisää kuva"
47
47
  },
48
+ "add_one_9e34a6f8": {
49
+ "message": "Lisää yksi!"
50
+ },
48
51
  "additional_considerations_f3801683": {
49
52
  "message": "Muuta huomioon otettavaa"
50
53
  },
@@ -1323,9 +1326,27 @@ const locale = {
1323
1326
  "no_accessibility_issues_were_detected_f8d3c875": {
1324
1327
  "message": "Ei havaittu käytettävyysongelmia."
1325
1328
  },
1329
+ "no_announcements_created_yet_c44a94f4": {
1330
+ "message": "Ilmoituksia ei ole vielä luotu."
1331
+ },
1332
+ "no_announcements_found_20185afc": {
1333
+ "message": "Ilmoituksia ei löytynyt."
1334
+ },
1335
+ "no_assignments_created_yet_1b236d87": {
1336
+ "message": "Tehtäviä ei ole vielä luotu."
1337
+ },
1338
+ "no_assignments_found_79e46d7f": {
1339
+ "message": "Tehtäviä ei löytynyt."
1340
+ },
1326
1341
  "no_changes_to_save_d29f6e91": {
1327
1342
  "message": "Ei tallennettavia muutoksia."
1328
1343
  },
1344
+ "no_discussions_created_yet_ff99abe3": {
1345
+ "message": "Keskusteluja ei ole vielä luotu."
1346
+ },
1347
+ "no_discussions_found_9284063b": {
1348
+ "message": "Keskusteluja ei löytynyt."
1349
+ },
1329
1350
  "no_e16d9132": {
1330
1351
  "message": "Ei"
1331
1352
  },
@@ -1335,9 +1356,27 @@ const locale = {
1335
1356
  "no_headers_9bc7dc7f": {
1336
1357
  "message": "Ei otsikoita"
1337
1358
  },
1359
+ "no_modules_created_yet_c71b6d4d": {
1360
+ "message": "Moduuleja ei ole vielä luotu."
1361
+ },
1362
+ "no_modules_found_2df43a40": {
1363
+ "message": "Moduuleja ei löytynyt."
1364
+ },
1365
+ "no_pages_created_yet_c379fa6e": {
1366
+ "message": "Sivuja ei ole vielä luotu"
1367
+ },
1368
+ "no_pages_found_6799350": {
1369
+ "message": "Sivuja ei löytynyt."
1370
+ },
1338
1371
  "no_preview_is_available_for_this_file_f940114a": {
1339
1372
  "message": "Tälle tiedostolle ei ole saatavissa esikatselua."
1340
1373
  },
1374
+ "no_quizzes_created_yet_1a2370b9": {
1375
+ "message": "Testejä ei ole vielä luotu."
1376
+ },
1377
+ "no_quizzes_found_c80c537a": {
1378
+ "message": "Testejä ei löytynyt."
1379
+ },
1341
1380
  "no_results_940393cf": {
1342
1381
  "message": "Ei tuloksia."
1343
1382
  },
@@ -45,6 +45,9 @@ const locale = {
45
45
  "add_image_60b2de07": {
46
46
  "message": "Legg til bilde"
47
47
  },
48
+ "add_one_9e34a6f8": {
49
+ "message": "Legg til en!"
50
+ },
48
51
  "additional_considerations_f3801683": {
49
52
  "message": "Ekstra hensyn"
50
53
  },
@@ -1323,9 +1326,27 @@ const locale = {
1323
1326
  "no_accessibility_issues_were_detected_f8d3c875": {
1324
1327
  "message": "Ingen tiljengelighetsproblemer ble oppdaget."
1325
1328
  },
1329
+ "no_announcements_created_yet_c44a94f4": {
1330
+ "message": "Ingen beskjeder opprettet ennå."
1331
+ },
1332
+ "no_announcements_found_20185afc": {
1333
+ "message": "Ingen beskjeder funnet."
1334
+ },
1335
+ "no_assignments_created_yet_1b236d87": {
1336
+ "message": "Ingen oppgave opprettet ennå."
1337
+ },
1338
+ "no_assignments_found_79e46d7f": {
1339
+ "message": "Ingen oppgaver funnet."
1340
+ },
1326
1341
  "no_changes_to_save_d29f6e91": {
1327
1342
  "message": "Ingen endringer å lagre."
1328
1343
  },
1344
+ "no_discussions_created_yet_ff99abe3": {
1345
+ "message": "Ingen diskusjoner opprettet ennå."
1346
+ },
1347
+ "no_discussions_found_9284063b": {
1348
+ "message": "Ingen diskusjoner funnet."
1349
+ },
1329
1350
  "no_e16d9132": {
1330
1351
  "message": "Nei"
1331
1352
  },
@@ -1335,9 +1356,27 @@ const locale = {
1335
1356
  "no_headers_9bc7dc7f": {
1336
1357
  "message": "Ingen titler"
1337
1358
  },
1359
+ "no_modules_created_yet_c71b6d4d": {
1360
+ "message": "Ingen moduler opprettet ennå."
1361
+ },
1362
+ "no_modules_found_2df43a40": {
1363
+ "message": "Ingen moduler funnet."
1364
+ },
1365
+ "no_pages_created_yet_c379fa6e": {
1366
+ "message": "Ingen sider opprettet ennå."
1367
+ },
1368
+ "no_pages_found_6799350": {
1369
+ "message": "Ingen sider funnet."
1370
+ },
1338
1371
  "no_preview_is_available_for_this_file_f940114a": {
1339
1372
  "message": "Ingen forhåndsvisning er tilgjengelig for denne filen."
1340
1373
  },
1374
+ "no_quizzes_created_yet_1a2370b9": {
1375
+ "message": "Ingen quizer opprettet ennå."
1376
+ },
1377
+ "no_quizzes_found_c80c537a": {
1378
+ "message": "Ingen quizer funnet."
1379
+ },
1341
1380
  "no_results_940393cf": {
1342
1381
  "message": "Ingen resultater."
1343
1382
  },
@@ -45,6 +45,9 @@ const locale = {
45
45
  "add_image_60b2de07": {
46
46
  "message": "Lägg till bild"
47
47
  },
48
+ "add_one_9e34a6f8": {
49
+ "message": "Lägg till en!"
50
+ },
48
51
  "additional_considerations_f3801683": {
49
52
  "message": "Ytterliggare hänsynstaganden"
50
53
  },
@@ -1323,9 +1326,27 @@ const locale = {
1323
1326
  "no_accessibility_issues_were_detected_f8d3c875": {
1324
1327
  "message": "Inga tillgänglighetsproblem upptäcktes."
1325
1328
  },
1329
+ "no_announcements_created_yet_c44a94f4": {
1330
+ "message": "Inga meddelanden har skapats än."
1331
+ },
1332
+ "no_announcements_found_20185afc": {
1333
+ "message": "Inga meddelande hittades."
1334
+ },
1335
+ "no_assignments_created_yet_1b236d87": {
1336
+ "message": "Inga uppgifter har skapats än."
1337
+ },
1338
+ "no_assignments_found_79e46d7f": {
1339
+ "message": "Inga uppgifter hittades."
1340
+ },
1326
1341
  "no_changes_to_save_d29f6e91": {
1327
1342
  "message": "Inga ändringar att spara."
1328
1343
  },
1344
+ "no_discussions_created_yet_ff99abe3": {
1345
+ "message": "Inga diskussioner har skapats än."
1346
+ },
1347
+ "no_discussions_found_9284063b": {
1348
+ "message": "Inga diskussioner hittades."
1349
+ },
1329
1350
  "no_e16d9132": {
1330
1351
  "message": "Nej"
1331
1352
  },
@@ -1335,9 +1356,27 @@ const locale = {
1335
1356
  "no_headers_9bc7dc7f": {
1336
1357
  "message": "Inga rubriker"
1337
1358
  },
1359
+ "no_modules_created_yet_c71b6d4d": {
1360
+ "message": "Inga moduler har skapats än."
1361
+ },
1362
+ "no_modules_found_2df43a40": {
1363
+ "message": "Inga moduler hittades."
1364
+ },
1365
+ "no_pages_created_yet_c379fa6e": {
1366
+ "message": "Inga sidor har skapats än."
1367
+ },
1368
+ "no_pages_found_6799350": {
1369
+ "message": "Inga sidor hittades."
1370
+ },
1338
1371
  "no_preview_is_available_for_this_file_f940114a": {
1339
1372
  "message": "Förhandsvisning är inte tillgänglig för den här filen."
1340
1373
  },
1374
+ "no_quizzes_created_yet_1a2370b9": {
1375
+ "message": "Inga quiz har skapats än."
1376
+ },
1377
+ "no_quizzes_found_c80c537a": {
1378
+ "message": "Inga quiz hittades."
1379
+ },
1341
1380
  "no_results_940393cf": {
1342
1381
  "message": "Inga resultat."
1343
1382
  },
@@ -0,0 +1,84 @@
1
+ /*
2
+ * Copyright (C) 2023 - present Instructure, Inc.
3
+ *
4
+ * This file is part of Canvas.
5
+ *
6
+ * Canvas is free software: you can redistribute it and/or modify it under
7
+ * the terms of the GNU Affero General Public License as published by the Free
8
+ * Software Foundation, version 3 of the License.
9
+ *
10
+ * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
11
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
+ * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
+ * details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License along
16
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+ import CryptoES from 'crypto-es';
19
+ export default class EncryptedStorage {
20
+ constructor(passphrase) {
21
+ this.passphrase = void 0;
22
+
23
+ this.errorHandlerWrapper = callback => {
24
+ try {
25
+ return callback();
26
+ } catch (error) {
27
+ console.error('error', error);
28
+ return null;
29
+ }
30
+ };
31
+
32
+ this.passphrase = CryptoES.enc.Utf8.parse(passphrase);
33
+ }
34
+
35
+ setItem(key, content) {
36
+ return this.errorHandlerWrapper(() => {
37
+ // If passphrase is present, encrypt string and JSON stringify
38
+ let encrypted;
39
+
40
+ if (this.passphrase) {
41
+ encrypted = CryptoES.RC4.encrypt(content, this.passphrase, {
42
+ mode: CryptoES.mode.CFB,
43
+ padding: CryptoES.pad.AnsiX923
44
+ }).toString();
45
+ }
46
+
47
+ const data = JSON.stringify({
48
+ autosaveTimestamp: new Date().getTime(),
49
+ content: encrypted
50
+ });
51
+ return window.localStorage.setItem(key, data);
52
+ });
53
+ }
54
+
55
+ getItem(key) {
56
+ return this.errorHandlerWrapper(() => {
57
+ const data = window.localStorage.getItem(key);
58
+
59
+ if (!data) {
60
+ return data;
61
+ } // If passphrase is present, parse JSON and decrypt string
62
+
63
+
64
+ if (this.passphrase) {
65
+ const parsedData = JSON.parse(data);
66
+ parsedData.content = CryptoES.RC4.decrypt(parsedData.content, this.passphrase, {
67
+ mode: CryptoES.mode.CFB,
68
+ padding: CryptoES.pad.AnsiX923
69
+ });
70
+ parsedData.content = parsedData.content.toString(CryptoES.enc.Utf8);
71
+ return parsedData;
72
+ }
73
+ });
74
+ }
75
+
76
+ key(index) {
77
+ return this.errorHandlerWrapper(() => window.localStorage.key(index));
78
+ }
79
+
80
+ removeItem(key) {
81
+ return this.errorHandlerWrapper(() => window.localStorage.removeItem(key));
82
+ }
83
+
84
+ }
@@ -19,7 +19,6 @@
19
19
  // Several components use aphrodite, which tries to manipulate the dom
20
20
  // on a timer which expires after the test completes and the document no longer exists
21
21
  import {StyleSheetTestUtils} from 'aphrodite'
22
- import {filterUselessConsoleMessages} from '@instructure/js-utils'
23
22
 
24
23
  /**
25
24
  * We want to ensure errors and warnings get appropriate eyes. If
@@ -44,6 +43,8 @@ const ignoredErrors = [
44
43
  /Invalid prop `images.searchString` of type `string` supplied to `Images`/,
45
44
  /Invalid URL: undefined/,
46
45
  /failed updating video captions/,
46
+ /You seem to have overlapping act\(\) calls/,
47
+ /A theme registry has already been initialized/,
47
48
  ]
48
49
  const globalWarn = global.console.warn
49
50
  const ignoredWarnings = [
@@ -51,6 +52,9 @@ const ignoredWarnings = [
51
52
  /Found bad LTI MRU data/,
52
53
  /Cannot save LTI MRU list/,
53
54
  /clicked sidebar (link|image) without a focused editor/,
55
+ /Translation for/,
56
+ /Exactly one focusable child is required/,
57
+ /is deprecated and will be removed/,
54
58
  ]
55
59
  global.console = {
56
60
  log: console.log,
@@ -77,7 +81,6 @@ global.console = {
77
81
  }
78
82
  /* eslint-enable no-console */
79
83
 
80
- filterUselessConsoleMessages(console)
81
84
  StyleSheetTestUtils.suppressStyleInjection()
82
85
 
83
86
  // because InstUI themeable components need an explicit "dir" attribute on the <html> element
package/jest.config.js CHANGED
@@ -47,6 +47,7 @@ module.exports = {
47
47
  '\\.(css|less)$': '<rootDir>/src/rce/__mocks__/styleMock.js',
48
48
  // mock the tinymce-react Editor component
49
49
  '@tinymce/tinymce-react': '<rootDir>/src/rce/__mocks__/tinymceReact.jsx',
50
+ 'crypto-es': '<rootDir>/src/rce/__mocks__/_mockCryptoEs.ts',
50
51
  },
51
52
 
52
53
  transform: {
@@ -2373,6 +2373,7 @@ import { rceWrapperPropTypes } from './RCEWrapperProps';
2373
2373
  import { insertPlaceholder, placeholderInfoFor, removePlaceholder } from '../util/loadingPlaceholder';
2374
2374
  import { transformRceContentForEditing } from './transformContent';
2375
2375
  import { IconMoreSolid } from '@instructure/ui-icons/es/svg';
2376
+ import EncryptedStorage from '../util/encrypted-storage';
2376
2377
  import buildStyle from './style';
2377
2378
  const RestoreAutoSaveModal = /*#__PURE__*/React.lazy(() => import('./RestoreAutoSaveModal'));
2378
2379
  const RceHtmlEditor = /*#__PURE__*/React.lazy(() => import('./RceHtmlEditor'));
@@ -2713,9 +2714,48 @@ class RCEWrapper extends React.Component {
2713
2714
 
2714
2715
  this.checkAccessibility();
2715
2716
  this.fixToolbarKeyboardNavigation();
2717
+ this.forwardPostMessages();
2716
2718
  (_this$props$onInitted = (_this$props = this.props).onInitted) === null || _this$props$onInitted === void 0 ? void 0 : _this$props$onInitted.call(_this$props, editor);
2717
2719
  };
2718
2720
 
2721
+ this.forwardPostMessages = () => {
2722
+ const windowReferences = {};
2723
+ const rceWindow = this.editor.getWin(); // explicitly assign name for reference by parent window
2724
+
2725
+ rceWindow.name = `${RCEWrapper.editorFrameName}_${this.id}`;
2726
+ rceWindow.addEventListener('message', this.forwardPostMessagesHandler(rceWindow, windowReferences));
2727
+ };
2728
+
2729
+ this.forwardPostMessagesHandler = (rceWindow, windowReferences) => e => {
2730
+ let message;
2731
+
2732
+ try {
2733
+ message = typeof e.data === 'string' ? JSON.parse(e.data) : e.data;
2734
+ } catch (err) {
2735
+ // unparseable message may not be meant for our handlers
2736
+ return false;
2737
+ }
2738
+
2739
+ if (e.origin === rceWindow.origin) {
2740
+ // message is from Canvas window, forward to tool
2741
+ const targetOrigin = message.toolOrigin;
2742
+
2743
+ if (!targetOrigin) {
2744
+ return false;
2745
+ }
2746
+
2747
+ const targetWindow = windowReferences[targetOrigin];
2748
+ delete message.toolOrigin;
2749
+ targetWindow === null || targetWindow === void 0 ? void 0 : targetWindow.postMessage(message, targetOrigin);
2750
+ } else {
2751
+ // message is from tool, forward to Canvas window
2752
+ windowReferences[e.origin] = e.source;
2753
+ message.toolOrigin = e.origin;
2754
+ message.frameName = rceWindow.name;
2755
+ rceWindow.parent.postMessage(message, rceWindow.origin);
2756
+ }
2757
+ };
2758
+
2719
2759
  this.fixToolbarKeyboardNavigation = () => {
2720
2760
  var _this$_elementRef$cur2;
2721
2761
 
@@ -2787,7 +2827,9 @@ class RCEWrapper extends React.Component {
2787
2827
  this.announcing = 0;
2788
2828
 
2789
2829
  this.initAutoSave = editor => {
2790
- this.storage = window.localStorage;
2830
+ var _this$props$userCache;
2831
+
2832
+ this.storage = new EncryptedStorage((_this$props$userCache = this.props.userCacheKey) !== null && _this$props$userCache !== void 0 ? _this$props$userCache : '');
2791
2833
 
2792
2834
  if (this.storage) {
2793
2835
  editor.on('change Undo Redo', this.doAutoSave);
@@ -2875,10 +2917,7 @@ class RCEWrapper extends React.Component {
2875
2917
  });
2876
2918
 
2877
2919
  try {
2878
- _this.storage.setItem(_this.autoSaveKey, JSON.stringify({
2879
- autosaveTimestamp: Date.now(),
2880
- content
2881
- }));
2920
+ _this.storage.setItem(_this.autoSaveKey, content);
2882
2921
  } catch (ex) {
2883
2922
  if (!retry) {
2884
2923
  // probably failed because there's not enough space
@@ -3733,7 +3772,7 @@ class RCEWrapper extends React.Component {
3733
3772
  let autosaved = null;
3734
3773
 
3735
3774
  try {
3736
- autosaved = this.storage && JSON.parse(this.storage.getItem(key));
3775
+ autosaved = this.storage && this.storage.getItem(key);
3737
3776
  } catch (_ex) {
3738
3777
  this.storage.removeItem(this.autoSaveKey);
3739
3778
  }
@@ -4199,6 +4238,7 @@ RCEWrapper.defaultProps = {
4199
4238
  canvasOrigin: ''
4200
4239
  };
4201
4240
  RCEWrapper.skinCssInjected = false;
4241
+ RCEWrapper.editorFrameName = 'active_rce_frame';
4202
4242
 
4203
4243
  function mergeMenuItems(standard, custom) {
4204
4244
  var _custom$trim;
@@ -125,5 +125,6 @@ export const rceWrapperPropTypes = {
125
125
  features: PropTypes.objectOf(PropTypes.bool),
126
126
  flashAlertTimeout: PropTypes.number,
127
127
  timezone: PropTypes.string,
128
+ userCacheKey: PropTypes.string,
128
129
  externalToolsConfig: externalToolsConfigPropType
129
130
  };
@@ -0,0 +1,124 @@
1
+ /*
2
+ * Copyright (C) 2023 - present Instructure, Inc.
3
+ *
4
+ * This file is part of Canvas.
5
+ *
6
+ * Canvas is free software: you can redistribute it and/or modify it under
7
+ * the terms of the GNU Affero General Public License as published by the Free
8
+ * Software Foundation, version 3 of the License.
9
+ *
10
+ * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
11
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
+ * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
+ * details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License along
16
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+ export default {
19
+ lib: {
20
+ Base: {},
21
+ WordArray: {},
22
+ BufferedBlockAlgorithm: {},
23
+ Hasher: {},
24
+ Cipher: {},
25
+ StreamCipher: {},
26
+ BlockCipherMode: {},
27
+ BlockCipher: {},
28
+ CipherParams: {},
29
+ SerializableCipher: {},
30
+ PasswordBasedCipher: {}
31
+ },
32
+ x64: {
33
+ Word: {},
34
+ WordArray: {}
35
+ },
36
+ enc: {
37
+ Hex: {},
38
+ Latin1: {},
39
+ Utf8: {
40
+ parse: () => {}
41
+ },
42
+ Utf16: {},
43
+ Utf16BE: {},
44
+ Utf16LE: {},
45
+ Base64: {},
46
+ Base64url: {}
47
+ },
48
+ algo: {
49
+ HMAC: {},
50
+ MD5: {},
51
+ SHA1: {},
52
+ SHA224: {},
53
+ SHA256: {},
54
+ SHA384: {},
55
+ SHA512: {},
56
+ SHA3: {},
57
+ RIPEMD160: {},
58
+ PBKDF2: {},
59
+ EvpKDF: {},
60
+ AES: {},
61
+ DES: {},
62
+ TripleDES: {},
63
+ Rabbit: {},
64
+ RabbitLegacy: {},
65
+ RC4: {},
66
+ RC4Drop: {},
67
+ Blowfish: {}
68
+ },
69
+ mode: {
70
+ CBC: {},
71
+ CFB: {},
72
+ CTR: {},
73
+ CTRGladman: {},
74
+ ECB: {},
75
+ OFB: {}
76
+ },
77
+ pad: {
78
+ Pkcs7: {},
79
+ AnsiX923: {},
80
+ Iso10126: {},
81
+ Iso97971: {},
82
+ NoPadding: {},
83
+ ZeroPadding: {}
84
+ },
85
+ format: {
86
+ OpenSSL: {},
87
+ Hex: {}
88
+ },
89
+ kdf: {
90
+ OpenSSL: {}
91
+ },
92
+ MD5: {},
93
+ HmacMD5: {},
94
+ SHA1: {},
95
+ HmacSHA1: {},
96
+ SHA224: {},
97
+ HmacSHA224: {},
98
+ SHA256: {},
99
+ HmacSHA256: {},
100
+ SHA384: {},
101
+ HmacSHA384: {},
102
+ SHA512: {},
103
+ HmacSHA512: {},
104
+ SHA3: {},
105
+ HmacSHA3: {},
106
+ RIPEMD160: {},
107
+ HmacRIPEMD160: {},
108
+ PBKDF2: {},
109
+ EvpKDF: {},
110
+ AES: {},
111
+ DES: {},
112
+ TripleDES: {},
113
+ Rabbit: {},
114
+ RabbitLegacy: {},
115
+ RC4: {
116
+ encrypt: () => {},
117
+ decrypt: () => {}
118
+ },
119
+ RC4Drop: {
120
+ encrypt: () => {},
121
+ decrypt: () => {}
122
+ },
123
+ Blowfish: {}
124
+ };
@@ -45,6 +45,9 @@ const locale = {
45
45
  "add_image_60b2de07": {
46
46
  "message": "Tilføj billede"
47
47
  },
48
+ "add_one_9e34a6f8": {
49
+ "message": "Tilføj en!"
50
+ },
48
51
  "additional_considerations_f3801683": {
49
52
  "message": "Yderligere overvejelser"
50
53
  },
@@ -1323,9 +1326,27 @@ const locale = {
1323
1326
  "no_accessibility_issues_were_detected_f8d3c875": {
1324
1327
  "message": "Der blev ikke fundet nogen tilgængelighedsproblemer."
1325
1328
  },
1329
+ "no_announcements_created_yet_c44a94f4": {
1330
+ "message": "Der er ikke oprettet beskeder endnu."
1331
+ },
1332
+ "no_announcements_found_20185afc": {
1333
+ "message": "Ingen beskeder fundet."
1334
+ },
1335
+ "no_assignments_created_yet_1b236d87": {
1336
+ "message": "Der er ikke oprettet opgaver endnu."
1337
+ },
1338
+ "no_assignments_found_79e46d7f": {
1339
+ "message": "Ingen opgaver fundet."
1340
+ },
1326
1341
  "no_changes_to_save_d29f6e91": {
1327
1342
  "message": "Ingen ændringer at gemme."
1328
1343
  },
1344
+ "no_discussions_created_yet_ff99abe3": {
1345
+ "message": "Der er ikke oprettet diskussioner endnu."
1346
+ },
1347
+ "no_discussions_found_9284063b": {
1348
+ "message": "Ingen diskussioner fundet."
1349
+ },
1329
1350
  "no_e16d9132": {
1330
1351
  "message": "Nej"
1331
1352
  },
@@ -1335,9 +1356,27 @@ const locale = {
1335
1356
  "no_headers_9bc7dc7f": {
1336
1357
  "message": "Ingen overskrifter"
1337
1358
  },
1359
+ "no_modules_created_yet_c71b6d4d": {
1360
+ "message": "Der er ikke oprettet forløb endnu."
1361
+ },
1362
+ "no_modules_found_2df43a40": {
1363
+ "message": "Ingen forløb fundet."
1364
+ },
1365
+ "no_pages_created_yet_c379fa6e": {
1366
+ "message": "Der er ikke oprettet sider endnu."
1367
+ },
1368
+ "no_pages_found_6799350": {
1369
+ "message": "Ingen sider fundet."
1370
+ },
1338
1371
  "no_preview_is_available_for_this_file_f940114a": {
1339
1372
  "message": "Der findes ikke forhåndsvisning for denne fil."
1340
1373
  },
1374
+ "no_quizzes_created_yet_1a2370b9": {
1375
+ "message": "Der er ikke oprettet nogen quizzer endnu."
1376
+ },
1377
+ "no_quizzes_found_c80c537a": {
1378
+ "message": "Der er ikke fundet nogen quizzer."
1379
+ },
1341
1380
  "no_results_940393cf": {
1342
1381
  "message": "Ingen resultater."
1343
1382
  },
@@ -45,6 +45,9 @@ const locale = {
45
45
  "add_image_60b2de07": {
46
46
  "message": "Lisää kuva"
47
47
  },
48
+ "add_one_9e34a6f8": {
49
+ "message": "Lisää yksi!"
50
+ },
48
51
  "additional_considerations_f3801683": {
49
52
  "message": "Muuta huomioon otettavaa"
50
53
  },
@@ -1323,9 +1326,27 @@ const locale = {
1323
1326
  "no_accessibility_issues_were_detected_f8d3c875": {
1324
1327
  "message": "Ei havaittu käytettävyysongelmia."
1325
1328
  },
1329
+ "no_announcements_created_yet_c44a94f4": {
1330
+ "message": "Ilmoituksia ei ole vielä luotu."
1331
+ },
1332
+ "no_announcements_found_20185afc": {
1333
+ "message": "Ilmoituksia ei löytynyt."
1334
+ },
1335
+ "no_assignments_created_yet_1b236d87": {
1336
+ "message": "Tehtäviä ei ole vielä luotu."
1337
+ },
1338
+ "no_assignments_found_79e46d7f": {
1339
+ "message": "Tehtäviä ei löytynyt."
1340
+ },
1326
1341
  "no_changes_to_save_d29f6e91": {
1327
1342
  "message": "Ei tallennettavia muutoksia."
1328
1343
  },
1344
+ "no_discussions_created_yet_ff99abe3": {
1345
+ "message": "Keskusteluja ei ole vielä luotu."
1346
+ },
1347
+ "no_discussions_found_9284063b": {
1348
+ "message": "Keskusteluja ei löytynyt."
1349
+ },
1329
1350
  "no_e16d9132": {
1330
1351
  "message": "Ei"
1331
1352
  },
@@ -1335,9 +1356,27 @@ const locale = {
1335
1356
  "no_headers_9bc7dc7f": {
1336
1357
  "message": "Ei otsikoita"
1337
1358
  },
1359
+ "no_modules_created_yet_c71b6d4d": {
1360
+ "message": "Moduuleja ei ole vielä luotu."
1361
+ },
1362
+ "no_modules_found_2df43a40": {
1363
+ "message": "Moduuleja ei löytynyt."
1364
+ },
1365
+ "no_pages_created_yet_c379fa6e": {
1366
+ "message": "Sivuja ei ole vielä luotu"
1367
+ },
1368
+ "no_pages_found_6799350": {
1369
+ "message": "Sivuja ei löytynyt."
1370
+ },
1338
1371
  "no_preview_is_available_for_this_file_f940114a": {
1339
1372
  "message": "Tälle tiedostolle ei ole saatavissa esikatselua."
1340
1373
  },
1374
+ "no_quizzes_created_yet_1a2370b9": {
1375
+ "message": "Testejä ei ole vielä luotu."
1376
+ },
1377
+ "no_quizzes_found_c80c537a": {
1378
+ "message": "Testejä ei löytynyt."
1379
+ },
1341
1380
  "no_results_940393cf": {
1342
1381
  "message": "Ei tuloksia."
1343
1382
  },
@@ -45,6 +45,9 @@ const locale = {
45
45
  "add_image_60b2de07": {
46
46
  "message": "Legg til bilde"
47
47
  },
48
+ "add_one_9e34a6f8": {
49
+ "message": "Legg til en!"
50
+ },
48
51
  "additional_considerations_f3801683": {
49
52
  "message": "Ekstra hensyn"
50
53
  },
@@ -1323,9 +1326,27 @@ const locale = {
1323
1326
  "no_accessibility_issues_were_detected_f8d3c875": {
1324
1327
  "message": "Ingen tiljengelighetsproblemer ble oppdaget."
1325
1328
  },
1329
+ "no_announcements_created_yet_c44a94f4": {
1330
+ "message": "Ingen beskjeder opprettet ennå."
1331
+ },
1332
+ "no_announcements_found_20185afc": {
1333
+ "message": "Ingen beskjeder funnet."
1334
+ },
1335
+ "no_assignments_created_yet_1b236d87": {
1336
+ "message": "Ingen oppgave opprettet ennå."
1337
+ },
1338
+ "no_assignments_found_79e46d7f": {
1339
+ "message": "Ingen oppgaver funnet."
1340
+ },
1326
1341
  "no_changes_to_save_d29f6e91": {
1327
1342
  "message": "Ingen endringer å lagre."
1328
1343
  },
1344
+ "no_discussions_created_yet_ff99abe3": {
1345
+ "message": "Ingen diskusjoner opprettet ennå."
1346
+ },
1347
+ "no_discussions_found_9284063b": {
1348
+ "message": "Ingen diskusjoner funnet."
1349
+ },
1329
1350
  "no_e16d9132": {
1330
1351
  "message": "Nei"
1331
1352
  },
@@ -1335,9 +1356,27 @@ const locale = {
1335
1356
  "no_headers_9bc7dc7f": {
1336
1357
  "message": "Ingen titler"
1337
1358
  },
1359
+ "no_modules_created_yet_c71b6d4d": {
1360
+ "message": "Ingen moduler opprettet ennå."
1361
+ },
1362
+ "no_modules_found_2df43a40": {
1363
+ "message": "Ingen moduler funnet."
1364
+ },
1365
+ "no_pages_created_yet_c379fa6e": {
1366
+ "message": "Ingen sider opprettet ennå."
1367
+ },
1368
+ "no_pages_found_6799350": {
1369
+ "message": "Ingen sider funnet."
1370
+ },
1338
1371
  "no_preview_is_available_for_this_file_f940114a": {
1339
1372
  "message": "Ingen forhåndsvisning er tilgjengelig for denne filen."
1340
1373
  },
1374
+ "no_quizzes_created_yet_1a2370b9": {
1375
+ "message": "Ingen quizer opprettet ennå."
1376
+ },
1377
+ "no_quizzes_found_c80c537a": {
1378
+ "message": "Ingen quizer funnet."
1379
+ },
1341
1380
  "no_results_940393cf": {
1342
1381
  "message": "Ingen resultater."
1343
1382
  },
@@ -45,6 +45,9 @@ const locale = {
45
45
  "add_image_60b2de07": {
46
46
  "message": "Lägg till bild"
47
47
  },
48
+ "add_one_9e34a6f8": {
49
+ "message": "Lägg till en!"
50
+ },
48
51
  "additional_considerations_f3801683": {
49
52
  "message": "Ytterliggare hänsynstaganden"
50
53
  },
@@ -1323,9 +1326,27 @@ const locale = {
1323
1326
  "no_accessibility_issues_were_detected_f8d3c875": {
1324
1327
  "message": "Inga tillgänglighetsproblem upptäcktes."
1325
1328
  },
1329
+ "no_announcements_created_yet_c44a94f4": {
1330
+ "message": "Inga meddelanden har skapats än."
1331
+ },
1332
+ "no_announcements_found_20185afc": {
1333
+ "message": "Inga meddelande hittades."
1334
+ },
1335
+ "no_assignments_created_yet_1b236d87": {
1336
+ "message": "Inga uppgifter har skapats än."
1337
+ },
1338
+ "no_assignments_found_79e46d7f": {
1339
+ "message": "Inga uppgifter hittades."
1340
+ },
1326
1341
  "no_changes_to_save_d29f6e91": {
1327
1342
  "message": "Inga ändringar att spara."
1328
1343
  },
1344
+ "no_discussions_created_yet_ff99abe3": {
1345
+ "message": "Inga diskussioner har skapats än."
1346
+ },
1347
+ "no_discussions_found_9284063b": {
1348
+ "message": "Inga diskussioner hittades."
1349
+ },
1329
1350
  "no_e16d9132": {
1330
1351
  "message": "Nej"
1331
1352
  },
@@ -1335,9 +1356,27 @@ const locale = {
1335
1356
  "no_headers_9bc7dc7f": {
1336
1357
  "message": "Inga rubriker"
1337
1358
  },
1359
+ "no_modules_created_yet_c71b6d4d": {
1360
+ "message": "Inga moduler har skapats än."
1361
+ },
1362
+ "no_modules_found_2df43a40": {
1363
+ "message": "Inga moduler hittades."
1364
+ },
1365
+ "no_pages_created_yet_c379fa6e": {
1366
+ "message": "Inga sidor har skapats än."
1367
+ },
1368
+ "no_pages_found_6799350": {
1369
+ "message": "Inga sidor hittades."
1370
+ },
1338
1371
  "no_preview_is_available_for_this_file_f940114a": {
1339
1372
  "message": "Förhandsvisning är inte tillgänglig för den här filen."
1340
1373
  },
1374
+ "no_quizzes_created_yet_1a2370b9": {
1375
+ "message": "Inga quiz har skapats än."
1376
+ },
1377
+ "no_quizzes_found_c80c537a": {
1378
+ "message": "Inga quiz hittades."
1379
+ },
1341
1380
  "no_results_940393cf": {
1342
1381
  "message": "Inga resultat."
1343
1382
  },
@@ -0,0 +1,84 @@
1
+ /*
2
+ * Copyright (C) 2023 - present Instructure, Inc.
3
+ *
4
+ * This file is part of Canvas.
5
+ *
6
+ * Canvas is free software: you can redistribute it and/or modify it under
7
+ * the terms of the GNU Affero General Public License as published by the Free
8
+ * Software Foundation, version 3 of the License.
9
+ *
10
+ * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
11
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
+ * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
+ * details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License along
16
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+ import CryptoES from 'crypto-es';
19
+ export default class EncryptedStorage {
20
+ constructor(passphrase) {
21
+ this.passphrase = void 0;
22
+
23
+ this.errorHandlerWrapper = callback => {
24
+ try {
25
+ return callback();
26
+ } catch (error) {
27
+ console.error('error', error);
28
+ return null;
29
+ }
30
+ };
31
+
32
+ this.passphrase = CryptoES.enc.Utf8.parse(passphrase);
33
+ }
34
+
35
+ setItem(key, content) {
36
+ return this.errorHandlerWrapper(() => {
37
+ // If passphrase is present, encrypt string and JSON stringify
38
+ let encrypted;
39
+
40
+ if (this.passphrase) {
41
+ encrypted = CryptoES.RC4.encrypt(content, this.passphrase, {
42
+ mode: CryptoES.mode.CFB,
43
+ padding: CryptoES.pad.AnsiX923
44
+ }).toString();
45
+ }
46
+
47
+ const data = JSON.stringify({
48
+ autosaveTimestamp: new Date().getTime(),
49
+ content: encrypted
50
+ });
51
+ return window.localStorage.setItem(key, data);
52
+ });
53
+ }
54
+
55
+ getItem(key) {
56
+ return this.errorHandlerWrapper(() => {
57
+ const data = window.localStorage.getItem(key);
58
+
59
+ if (!data) {
60
+ return data;
61
+ } // If passphrase is present, parse JSON and decrypt string
62
+
63
+
64
+ if (this.passphrase) {
65
+ const parsedData = JSON.parse(data);
66
+ parsedData.content = CryptoES.RC4.decrypt(parsedData.content, this.passphrase, {
67
+ mode: CryptoES.mode.CFB,
68
+ padding: CryptoES.pad.AnsiX923
69
+ });
70
+ parsedData.content = parsedData.content.toString(CryptoES.enc.Utf8);
71
+ return parsedData;
72
+ }
73
+ });
74
+ }
75
+
76
+ key(index) {
77
+ return this.errorHandlerWrapper(() => window.localStorage.key(index));
78
+ }
79
+
80
+ removeItem(key) {
81
+ return this.errorHandlerWrapper(() => window.localStorage.removeItem(key));
82
+ }
83
+
84
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instructure/canvas-rce",
3
- "version": "5.8.0",
3
+ "version": "5.9.0",
4
4
  "description": "A component wrapping Canvas's usage of Tinymce",
5
5
  "main": "es/index.js",
6
6
  "scripts": {
@@ -77,7 +77,6 @@
77
77
  "@instructure/canvas-theme": "7",
78
78
  "@instructure/debounce": "^7",
79
79
  "@instructure/emotion": "^8.38.1",
80
- "@instructure/js-utils": "*",
81
80
  "@instructure/k5uploader": "*",
82
81
  "@instructure/media-capture": "~8.4.1-rc.16",
83
82
  "@instructure/ui-a11y-content": "^7",
@@ -133,6 +132,7 @@
133
132
  "aphrodite": "^2",
134
133
  "axios": "^0.21.1",
135
134
  "bloody-offset": "0.0.0",
135
+ "crypto-es": "^2.0.4",
136
136
  "classnames": "^2.2.5",
137
137
  "concurrently": "^4",
138
138
  "format-message": "^6",