typo3-typescript-sources 13.4.20

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.
Files changed (415) hide show
  1. package/.github/workflows/sync-and-publish.yml +265 -0
  2. package/.last-synced-tag +1 -0
  3. package/LICENSE.txt +339 -0
  4. package/README-TYPO3.md +166 -0
  5. package/README.md +28 -0
  6. package/adminpanel/admin-panel.ts +375 -0
  7. package/adminpanel/modules/cache.ts +27 -0
  8. package/adminpanel/modules/preview.ts +75 -0
  9. package/backend/action-button/abstract-action.ts +22 -0
  10. package/backend/action-button/deferred-action.ts +41 -0
  11. package/backend/action-button/immediate-action.ts +31 -0
  12. package/backend/action-dispatcher.ts +104 -0
  13. package/backend/ajax-data-handler/message-interface.ts +18 -0
  14. package/backend/ajax-data-handler/response-interface.ts +20 -0
  15. package/backend/ajax-data-handler.ts +214 -0
  16. package/backend/backend-exception.ts +22 -0
  17. package/backend/broadcast-message.ts +50 -0
  18. package/backend/broadcast-service.ts +52 -0
  19. package/backend/browse-database.ts +38 -0
  20. package/backend/clear-cache.ts +88 -0
  21. package/backend/clipboard-panel.ts +240 -0
  22. package/backend/close-current-window.ts +2 -0
  23. package/backend/code-editor/autocomplete/completion-result.ts +105 -0
  24. package/backend/code-editor/autocomplete/ts-code-completion.ts +142 -0
  25. package/backend/code-editor/autocomplete/ts-parser.ts +485 -0
  26. package/backend/code-editor/autocomplete/ts-ref.ts +164 -0
  27. package/backend/code-editor/element/code-mirror-element.ts +282 -0
  28. package/backend/code-editor/language/typoscript.ts +181 -0
  29. package/backend/code-editor/stream-parser/typoscript.ts +1600 -0
  30. package/backend/color-picker.ts +158 -0
  31. package/backend/color-scheme-switch.ts +179 -0
  32. package/backend/column-selector-button.ts +302 -0
  33. package/backend/context-help.ts +68 -0
  34. package/backend/context-menu-actions.ts +322 -0
  35. package/backend/context-menu.ts +751 -0
  36. package/backend/copy-to-clipboard.ts +79 -0
  37. package/backend/date-time-picker.ts +270 -0
  38. package/backend/document-save-actions.ts +159 -0
  39. package/backend/drag-tooltip.ts +285 -0
  40. package/backend/drag-uploader.ts +914 -0
  41. package/backend/element/alert-element.ts +116 -0
  42. package/backend/element/dispatch-modal-button.ts +50 -0
  43. package/backend/element/draggable-resizable-element.ts +249 -0
  44. package/backend/element/editable-page-title.ts +306 -0
  45. package/backend/element/icon-element.ts +84 -0
  46. package/backend/element/immediate-action-element.ts +89 -0
  47. package/backend/element/pagination.ts +59 -0
  48. package/backend/element/progress-bar-element.ts +172 -0
  49. package/backend/element/progress-tracker-element.ts +119 -0
  50. package/backend/element/pseudo-button.ts +58 -0
  51. package/backend/element/spinner-element.ts +51 -0
  52. package/backend/element/thumbnail-element.ts +80 -0
  53. package/backend/element-browser.ts +182 -0
  54. package/backend/enum/data-transfer-types.ts +21 -0
  55. package/backend/enum/icon-types.ts +31 -0
  56. package/backend/enum/key-types.ts +27 -0
  57. package/backend/enum/severity.ts +20 -0
  58. package/backend/enum/viewport/scaffold-identifier.ts +24 -0
  59. package/backend/event/client-request.ts +25 -0
  60. package/backend/event/consumable.ts +18 -0
  61. package/backend/event/consumer-scope.ts +54 -0
  62. package/backend/event/event-dispatcher.ts +26 -0
  63. package/backend/event/interaction-request-assignment.ts +24 -0
  64. package/backend/event/interaction-request-map.ts +75 -0
  65. package/backend/event/interaction-request.ts +48 -0
  66. package/backend/event/trigger-request.ts +56 -0
  67. package/backend/form/submit-interceptor.ts +66 -0
  68. package/backend/form-engine/container/files-control-container.ts +716 -0
  69. package/backend/form-engine/container/flex-form-container-container.ts +166 -0
  70. package/backend/form-engine/container/flex-form-section-container.ts +210 -0
  71. package/backend/form-engine/container/inline-control-container.ts +1230 -0
  72. package/backend/form-engine/container/site-language-container.ts +616 -0
  73. package/backend/form-engine/element/abstract-sortable-select-items.ts +186 -0
  74. package/backend/form-engine/element/category-element.ts +160 -0
  75. package/backend/form-engine/element/color-element.ts +81 -0
  76. package/backend/form-engine/element/datetime-element.ts +66 -0
  77. package/backend/form-engine/element/extra/char-counter.ts +112 -0
  78. package/backend/form-engine/element/extra/select-box-filter.ts +85 -0
  79. package/backend/form-engine/element/folder-element.ts +66 -0
  80. package/backend/form-engine/element/group-element.ts +47 -0
  81. package/backend/form-engine/element/json-element.ts +52 -0
  82. package/backend/form-engine/element/link-element.ts +121 -0
  83. package/backend/form-engine/element/mfa-info-element.ts +169 -0
  84. package/backend/form-engine/element/modifier/resizable.ts +27 -0
  85. package/backend/form-engine/element/modifier/tabbable.ts +29 -0
  86. package/backend/form-engine/element/online-media-form-element.ts +65 -0
  87. package/backend/form-engine/element/password-element.ts +71 -0
  88. package/backend/form-engine/element/select-multiple-side-by-side-element.ts +83 -0
  89. package/backend/form-engine/element/select-single-element.ts +82 -0
  90. package/backend/form-engine/element/select-tree-element.ts +148 -0
  91. package/backend/form-engine/element/select-tree-toolbar.ts +118 -0
  92. package/backend/form-engine/element/select-tree.ts +210 -0
  93. package/backend/form-engine/element/slug-element.ts +243 -0
  94. package/backend/form-engine/element/suggest/result-container.ts +118 -0
  95. package/backend/form-engine/element/suggest/result-item.ts +90 -0
  96. package/backend/form-engine/element/table-permission-element.ts +101 -0
  97. package/backend/form-engine/element/table-wizard-element.ts +427 -0
  98. package/backend/form-engine/element/text-element.ts +52 -0
  99. package/backend/form-engine/element/text-table-element.ts +31 -0
  100. package/backend/form-engine/field-control/add-record.ts +40 -0
  101. package/backend/form-engine/field-control/edit-popup.ts +64 -0
  102. package/backend/form-engine/field-control/insert-clipboard.ts +50 -0
  103. package/backend/form-engine/field-control/link-popup.ts +53 -0
  104. package/backend/form-engine/field-control/list-module.ts +40 -0
  105. package/backend/form-engine/field-control/password-generator.ts +102 -0
  106. package/backend/form-engine/field-control/reset-selection.ts +48 -0
  107. package/backend/form-engine/field-wizard/localization-state-selector.ts +67 -0
  108. package/backend/form-engine/field-wizard/value-picker.ts +123 -0
  109. package/backend/form-engine/field-wizard/value-slider.ts +86 -0
  110. package/backend/form-engine/inline-relation/ajax-dispatcher.ts +124 -0
  111. package/backend/form-engine/inline-relation/inline-response-interface.ts +41 -0
  112. package/backend/form-engine-link-browser-adapter.ts +129 -0
  113. package/backend/form-engine-review.ts +155 -0
  114. package/backend/form-engine-suggest.ts +133 -0
  115. package/backend/form-engine-validation.ts +686 -0
  116. package/backend/form-engine.ts +1391 -0
  117. package/backend/global-event-handler.ts +252 -0
  118. package/backend/grid-editor.ts +1077 -0
  119. package/backend/hashing/md5.ts +252 -0
  120. package/backend/helper.ts +24 -0
  121. package/backend/hotkeys/hotkey-storage.ts +63 -0
  122. package/backend/hotkeys.ts +216 -0
  123. package/backend/icons.ts +236 -0
  124. package/backend/image-manipulation.ts +885 -0
  125. package/backend/info-window.ts +46 -0
  126. package/backend/input/clearable.ts +128 -0
  127. package/backend/input/index.d.ts +8 -0
  128. package/backend/java-script-module-import-event-handler.ts +19 -0
  129. package/backend/key-bindings.ts +42 -0
  130. package/backend/layout-module/drag-drop.ts +359 -0
  131. package/backend/layout-module/paste.ts +165 -0
  132. package/backend/link-browser.ts +89 -0
  133. package/backend/live-search/element/backend-search.ts +34 -0
  134. package/backend/live-search/element/hint.ts +33 -0
  135. package/backend/live-search/element/provider/default-result-item.ts +52 -0
  136. package/backend/live-search/element/provider/page-provider-result-item.ts +52 -0
  137. package/backend/live-search/element/result/item/action/action-container.ts +135 -0
  138. package/backend/live-search/element/result/item/action/action.ts +56 -0
  139. package/backend/live-search/element/result/item/item-container.ts +224 -0
  140. package/backend/live-search/element/result/item/item.ts +74 -0
  141. package/backend/live-search/element/result/result-container.ts +110 -0
  142. package/backend/live-search/element/result/result-detail-container.ts +50 -0
  143. package/backend/live-search/element/result/result-pagination.ts +122 -0
  144. package/backend/live-search/element/search-option-item.ts +70 -0
  145. package/backend/live-search/live-search-configurator.ts +54 -0
  146. package/backend/live-search/live-search-shortcut.ts +29 -0
  147. package/backend/live-search/result-types/backend-module-result-type.ts +8 -0
  148. package/backend/live-search/result-types/default-result-type.ts +21 -0
  149. package/backend/live-search/result-types/page-result-type.ts +23 -0
  150. package/backend/localization.ts +390 -0
  151. package/backend/login-refresh.ts +525 -0
  152. package/backend/login.ts +179 -0
  153. package/backend/mail-link-handler.ts +45 -0
  154. package/backend/modal-interface.ts +19 -0
  155. package/backend/modal.ts +685 -0
  156. package/backend/module/iframe.ts +125 -0
  157. package/backend/module/router.ts +275 -0
  158. package/backend/module-menu.ts +550 -0
  159. package/backend/module.ts +133 -0
  160. package/backend/multi-record-selection-action.ts +44 -0
  161. package/backend/multi-record-selection-delete-action.ts +108 -0
  162. package/backend/multi-record-selection-edit-action.ts +56 -0
  163. package/backend/multi-record-selection.ts +468 -0
  164. package/backend/multi-step-wizard.ts +568 -0
  165. package/backend/new-content-element-wizard-button.ts +51 -0
  166. package/backend/new-multiple-pages.ts +108 -0
  167. package/backend/new-record-wizard.ts +680 -0
  168. package/backend/notification.ts +366 -0
  169. package/backend/offset.ts +40 -0
  170. package/backend/online-media.ts +110 -0
  171. package/backend/page-actions.ts +91 -0
  172. package/backend/page-link-handler.ts +51 -0
  173. package/backend/pagetsconfig/pagetsconfig-includes.ts +77 -0
  174. package/backend/popover.ts +165 -0
  175. package/backend/record-download-button.ts +104 -0
  176. package/backend/record-link-handler.ts +31 -0
  177. package/backend/record-search.ts +44 -0
  178. package/backend/recordlist.ts +230 -0
  179. package/backend/resource/resource.ts +35 -0
  180. package/backend/security/element/csp-reports.ts +406 -0
  181. package/backend/security/element/sudo-mode.ts +249 -0
  182. package/backend/security/sudo-mode-interceptor.ts +19 -0
  183. package/backend/settings/editor/editable-setting.ts +231 -0
  184. package/backend/settings/editor.ts +451 -0
  185. package/backend/settings/enum/settings-mode.enum.ts +24 -0
  186. package/backend/settings/type/base.ts +200 -0
  187. package/backend/settings/type/bool.ts +56 -0
  188. package/backend/settings/type/color.ts +64 -0
  189. package/backend/settings/type/int.ts +85 -0
  190. package/backend/settings/type/number.ts +61 -0
  191. package/backend/settings/type/page.ts +100 -0
  192. package/backend/settings/type/string.ts +77 -0
  193. package/backend/settings/type/stringlist.ts +87 -0
  194. package/backend/severity.ts +88 -0
  195. package/backend/site-inline-actions.ts +32 -0
  196. package/backend/sortable-table.ts +208 -0
  197. package/backend/storage/abstract-client-storage.ts +76 -0
  198. package/backend/storage/browser-session.ts +28 -0
  199. package/backend/storage/client.ts +28 -0
  200. package/backend/storage/module-state-storage.ts +118 -0
  201. package/backend/storage/persistent.ts +204 -0
  202. package/backend/switch-user.ts +82 -0
  203. package/backend/tabs.ts +72 -0
  204. package/backend/telephone-link-handler.ts +40 -0
  205. package/backend/tests/backend/storage/browser-storage-test.ts +87 -0
  206. package/backend/tests/backend/storage/client-test.ts +87 -0
  207. package/backend/tests/backend/utility/dom-helper-test.ts +51 -0
  208. package/backend/tests/backend-exception-test.ts +28 -0
  209. package/backend/tests/element/immediate-action-element-test.ts +81 -0
  210. package/backend/tests/form-engine-validation-test.ts +304 -0
  211. package/backend/tests/grid-editor-test.ts +29 -0
  212. package/backend/tests/hashing/md5Test.ts +28 -0
  213. package/backend/tests/icons-test.ts +23 -0
  214. package/backend/tests/notification-test.ts +161 -0
  215. package/backend/tests/popover-test.ts +83 -0
  216. package/backend/toolbar/clear-cache-menu.ts +88 -0
  217. package/backend/toolbar/live-search.ts +284 -0
  218. package/backend/toolbar/shortcut-menu.ts +254 -0
  219. package/backend/toolbar/system-information-menu.ts +161 -0
  220. package/backend/toolbar.ts +41 -0
  221. package/backend/tree/file-storage-browser.ts +194 -0
  222. package/backend/tree/file-storage-tree-container.ts +465 -0
  223. package/backend/tree/file-storage-tree.ts +42 -0
  224. package/backend/tree/page-browser.ts +272 -0
  225. package/backend/tree/page-tree-element.ts +602 -0
  226. package/backend/tree/page-tree.ts +152 -0
  227. package/backend/tree/tree-module-state.ts +159 -0
  228. package/backend/tree/tree-node-toggle.ts +31 -0
  229. package/backend/tree/tree-node.ts +97 -0
  230. package/backend/tree/tree-toolbar.ts +117 -0
  231. package/backend/tree/tree.ts +1595 -0
  232. package/backend/url-link-handler.ts +36 -0
  233. package/backend/user-pass-login.ts +255 -0
  234. package/backend/user-settings-manager.ts +189 -0
  235. package/backend/utility/collapse-state-persister.ts +205 -0
  236. package/backend/utility/collapse-state-search.ts +183 -0
  237. package/backend/utility/dom-helper.ts +91 -0
  238. package/backend/utility/drag-drop-utility.ts +47 -0
  239. package/backend/utility/message-utility.ts +45 -0
  240. package/backend/utility/top-level-module-import.ts +32 -0
  241. package/backend/utility.ts +194 -0
  242. package/backend/viewport/abstract-container.ts +22 -0
  243. package/backend/viewport/content-container.ts +98 -0
  244. package/backend/viewport/loader.ts +28 -0
  245. package/backend/viewport/navigation-container.ts +119 -0
  246. package/backend/viewport/resizable-navigation.ts +176 -0
  247. package/backend/viewport/toolbar.ts +27 -0
  248. package/backend/viewport/topbar.ts +39 -0
  249. package/backend/viewport.ts +46 -0
  250. package/backend/window-manager.ts +84 -0
  251. package/backend/wizard/move-content-element.ts +107 -0
  252. package/backend/wizard/move-page.ts +74 -0
  253. package/backend/wizard.ts +331 -0
  254. package/belog/backend-log.ts +88 -0
  255. package/beuser/backend-user-listing.ts +40 -0
  256. package/beuser/permissions.ts +291 -0
  257. package/core/ajax/ajax-request-types.ts +15 -0
  258. package/core/ajax/ajax-request.ts +202 -0
  259. package/core/ajax/ajax-response.ts +57 -0
  260. package/core/ajax/input-transformer.ts +92 -0
  261. package/core/ajax/simple-response-interface.ts +5 -0
  262. package/core/authentication/mfa-provider/totp.ts +54 -0
  263. package/core/cache/dedupe-async-task.ts +95 -0
  264. package/core/directive/markdown.ts +82 -0
  265. package/core/directive/nl2br.ts +16 -0
  266. package/core/document-service.ts +35 -0
  267. package/core/event/debounce-event.ts +40 -0
  268. package/core/event/event-interface.ts +24 -0
  269. package/core/event/regular-event.ts +58 -0
  270. package/core/event/request-animation-frame-event.ts +42 -0
  271. package/core/event/throttle-event.ts +54 -0
  272. package/core/java-script-item-handler.ts +29 -0
  273. package/core/java-script-item-processor.ts +171 -0
  274. package/core/lit-helper.ts +126 -0
  275. package/core/literals.ts +17 -0
  276. package/core/referrer-refresh.ts +2 -0
  277. package/core/security-utility.ts +89 -0
  278. package/core/tests/ajax/ajax-request-test.ts +290 -0
  279. package/core/tests/ajax/input-transformer-test.ts +64 -0
  280. package/core/tests/cache/dedupe-async-task-test.ts +152 -0
  281. package/core/tests/event/throttle-event-test.ts +47 -0
  282. package/core/tests/literals-test.ts +24 -0
  283. package/core/tests/security-utility-test.ts +50 -0
  284. package/core/utility/types.ts +9 -0
  285. package/dashboard/chart-initializer.ts +136 -0
  286. package/dashboard/dashboard.ts +1487 -0
  287. package/extensionmanager/distribution-image.ts +55 -0
  288. package/extensionmanager/main.ts +291 -0
  289. package/extensionmanager/repository.ts +195 -0
  290. package/extensionmanager/update.ts +118 -0
  291. package/extensionmanager/upload-form.ts +42 -0
  292. package/filelist/browse-files.ts +148 -0
  293. package/filelist/browse-folders.ts +94 -0
  294. package/filelist/context-menu-actions.ts +335 -0
  295. package/filelist/create-folder.ts +69 -0
  296. package/filelist/file-delete.ts +69 -0
  297. package/filelist/file-list-actions.ts +132 -0
  298. package/filelist/file-list-dragdrop.ts +139 -0
  299. package/filelist/file-list-rename-handler.ts +128 -0
  300. package/filelist/file-list-transfer-handler.ts +138 -0
  301. package/filelist/file-list.ts +396 -0
  302. package/filelist/file-replace.ts +37 -0
  303. package/filelist/linkbrowser-file-handler.ts +94 -0
  304. package/filelist/linkbrowser-folder-handler.ts +74 -0
  305. package/filelist/rename-file.ts +109 -0
  306. package/form/backend/form-editor/component/property-grid-editor.ts +340 -0
  307. package/form/backend/form-editor/core.ts +2104 -0
  308. package/form/backend/form-editor/helper.ts +226 -0
  309. package/form/backend/form-editor/inspector-component.ts +2323 -0
  310. package/form/backend/form-editor/mediator.ts +941 -0
  311. package/form/backend/form-editor/modals-component.ts +433 -0
  312. package/form/backend/form-editor/stage-component.ts +908 -0
  313. package/form/backend/form-editor/tree-component.ts +548 -0
  314. package/form/backend/form-editor/view-model.ts +1343 -0
  315. package/form/backend/form-editor.ts +846 -0
  316. package/form/backend/form-manager/main.ts +39 -0
  317. package/form/backend/form-manager/view-model.ts +789 -0
  318. package/form/backend/form-manager.ts +180 -0
  319. package/form/backend/helper.ts +60 -0
  320. package/form/frontend/date-picker.ts +38 -0
  321. package/frontend/default_frontend.ts +82 -0
  322. package/impexp/context-menu-actions.ts +50 -0
  323. package/impexp/import-export.ts +62 -0
  324. package/indexed-search/pagination.ts +26 -0
  325. package/indexed-search/statistics.ts +50 -0
  326. package/info/translation-status.ts +48 -0
  327. package/install/ajax/ajax-queue.ts +83 -0
  328. package/install/init-install.ts +2 -0
  329. package/install/init-installer.ts +2 -0
  330. package/install/install.ts +25 -0
  331. package/install/installer.ts +458 -0
  332. package/install/message-interface.ts +18 -0
  333. package/install/module/abstract-inline-module.ts +27 -0
  334. package/install/module/abstract-interactable-module.ts +107 -0
  335. package/install/module/environment/environment-check.ts +92 -0
  336. package/install/module/environment/folder-structure.ts +145 -0
  337. package/install/module/environment/image-processing.ts +141 -0
  338. package/install/module/environment/mail-test.ts +127 -0
  339. package/install/module/environment/php-info.ts +50 -0
  340. package/install/module/environment/system-information.ts +50 -0
  341. package/install/module/maintenance/cache.ts +59 -0
  342. package/install/module/maintenance/clear-tables.ts +134 -0
  343. package/install/module/maintenance/clear-typo3temp-files.ts +137 -0
  344. package/install/module/maintenance/create-admin.ts +126 -0
  345. package/install/module/maintenance/database-analyzer.ts +266 -0
  346. package/install/module/maintenance/dump-autoload.ts +58 -0
  347. package/install/module/maintenance/language-packs.ts +338 -0
  348. package/install/module/maintenance/reset-backend-user-uc.ts +58 -0
  349. package/install/module/password-strength.ts +56 -0
  350. package/install/module/settings/change-install-tool-password.ts +101 -0
  351. package/install/module/settings/extension-configuration.ts +224 -0
  352. package/install/module/settings/features.ts +102 -0
  353. package/install/module/settings/local-configuration.ts +316 -0
  354. package/install/module/settings/presets.ts +147 -0
  355. package/install/module/settings/system-maintainer.ts +111 -0
  356. package/install/module/upgrade/core-update.ts +255 -0
  357. package/install/module/upgrade/extension-compat-tester.ts +195 -0
  358. package/install/module/upgrade/extension-scanner.ts +381 -0
  359. package/install/module/upgrade/tca-ext-tables-check.ts +93 -0
  360. package/install/module/upgrade/tca-migrations-check.ts +101 -0
  361. package/install/module/upgrade/upgrade-docs.ts +310 -0
  362. package/install/module/upgrade/upgrade-wizards.ts +612 -0
  363. package/install/renderable/clearable.ts +113 -0
  364. package/install/renderable/flash-message.ts +64 -0
  365. package/install/renderable/info-box.ts +66 -0
  366. package/install/renderable/language-packs.ts +304 -0
  367. package/install/renderable/offset-group.ts +38 -0
  368. package/install/renderable/severity.ts +49 -0
  369. package/install/renderable/wrap-group.ts +36 -0
  370. package/install/router.ts +468 -0
  371. package/linkvalidator/linkvalidator-modal.ts +45 -0
  372. package/linkvalidator/linkvalidator.ts +101 -0
  373. package/lowlevel/query-generator.ts +132 -0
  374. package/lowlevel/reference-index.ts +44 -0
  375. package/opendocs/toolbar/opendocs-menu.ts +117 -0
  376. package/package.json +34 -0
  377. package/recycler/recycler.ts +539 -0
  378. package/redirects/event-handler.ts +108 -0
  379. package/redirects/form-engine-evaluation.ts +34 -0
  380. package/redirects/redirects-module.ts +58 -0
  381. package/rte-ckeditor/ckeditor5.ts +402 -0
  382. package/rte-ckeditor/css-prefixer.ts +94 -0
  383. package/rte-ckeditor/legacy/ckeditor5-bundle.ts +17 -0
  384. package/rte-ckeditor/legacy/ckeditor5-inspector.ts +2 -0
  385. package/rte-ckeditor/plugin/typo3-link.ts +810 -0
  386. package/rte-ckeditor/plugin/whitespace.ts +114 -0
  387. package/rte-ckeditor/rte-link-browser.ts +112 -0
  388. package/rte-ckeditor/tests/css-prefixer-test.ts +314 -0
  389. package/scheduler/scheduler-add-group.ts +119 -0
  390. package/scheduler/scheduler-editable-group-name.ts +307 -0
  391. package/scheduler/scheduler-sortable-groups.ts +59 -0
  392. package/scheduler/scheduler.ts +466 -0
  393. package/setup/setup-module.ts +122 -0
  394. package/styleguide/checkbox-demo.ts +5 -0
  395. package/styleguide/element/theme-switcher-element.ts +101 -0
  396. package/styleguide/filter.ts +22 -0
  397. package/styleguide/find-icons.ts +78 -0
  398. package/styleguide/processing-indicator.ts +78 -0
  399. package/styleguide/render-notifications.ts +64 -0
  400. package/sys-note/element/delete-button.ts +78 -0
  401. package/tstemplate/constant-editor.ts +64 -0
  402. package/tstemplate/information-module.ts +31 -0
  403. package/tstemplate/template-analyzer.ts +77 -0
  404. package/viewpage/main.ts +253 -0
  405. package/workspaces/backend.ts +979 -0
  406. package/workspaces/preview.ts +232 -0
  407. package/workspaces/renderable/comment-view.ts +79 -0
  408. package/workspaces/renderable/diff-view.ts +58 -0
  409. package/workspaces/renderable/history-view.ts +97 -0
  410. package/workspaces/renderable/record-information.ts +118 -0
  411. package/workspaces/renderable/record-table.ts +355 -0
  412. package/workspaces/renderable/send-to-stage-form.ts +108 -0
  413. package/workspaces/toolbar/workspaces-menu.ts +190 -0
  414. package/workspaces/utility/icon-helper.ts +57 -0
  415. package/workspaces/workspaces.ts +136 -0
@@ -0,0 +1,406 @@
1
+ /*
2
+ * This file is part of the TYPO3 CMS project.
3
+ *
4
+ * It is free software; you can redistribute it and/or modify it under
5
+ * the terms of the GNU General Public License, either version 2
6
+ * of the License, or any later version.
7
+ *
8
+ * For the full copyright and license information, please read the
9
+ * LICENSE.txt file that was distributed with this source code.
10
+ *
11
+ * The TYPO3 project - inspiring people to share!
12
+ */
13
+
14
+ import { customElement, property, state } from 'lit/decorators';
15
+ import { html, LitElement, nothing, type TemplateResult } from 'lit';
16
+ import { classMap } from 'lit/directives/class-map';
17
+ import AjaxRequest from '@typo3/core/ajax/ajax-request';
18
+ import RegularEvent from '@typo3/core/event/regular-event';
19
+ import { lll } from '@typo3/core/lit-helper';
20
+ import type { AjaxResponse } from '@typo3/core/ajax/ajax-response';
21
+
22
+ enum CspReportAttribute {
23
+ fixable= 'fixable',
24
+ irrelevant = 'irrelevant',
25
+ suspicious = 'suspicious',
26
+ }
27
+
28
+ interface CspReportUuids {
29
+ uuids: string[]
30
+ }
31
+
32
+ interface SummarizedCspReport {
33
+ uuid: string,
34
+ scope: string;
35
+ created: Date;
36
+ requestTime: number;
37
+ summary: string;
38
+ count: number,
39
+ attributes: CspReportAttribute[],
40
+ mutationHashes: string[];
41
+ meta: {
42
+ addr: string,
43
+ agent: string,
44
+ };
45
+ details: {
46
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP#violation_report_syntax
47
+ disposition: 'enforce' | 'report',
48
+
49
+ blockedUri: string,
50
+ documentUri: string,
51
+ statusCode: number,
52
+ referrer?: string,
53
+
54
+ originalPolicy: string,
55
+ effectiveDirective: string,
56
+ /**
57
+ * @deprecated historical alias of effectiveDirective
58
+ * see https://w3c.github.io/webappsec-csp/#violation-events
59
+ */
60
+ violatedDirective: string,
61
+
62
+ sourceFile?: string,
63
+ scriptSample?: string,
64
+ columnNumber?: number,
65
+ lineNumber?: number,
66
+ };
67
+ }
68
+
69
+ interface MutationSuggestion {
70
+ collection: MutationCollection;
71
+ identifier: string;
72
+ priority?: number;
73
+ label?: string;
74
+ hash: string;
75
+ hmac: string;
76
+ }
77
+
78
+ interface MutationCollection {
79
+ mutations: Mutation[];
80
+ }
81
+
82
+ interface Mutation {
83
+ directive: string;
84
+ mode: string,
85
+ sources: string[]
86
+ }
87
+
88
+ @customElement('typo3-backend-security-csp-reports')
89
+ export class CspReports extends LitElement {
90
+ @property({ type: Array }) scopes: string[];
91
+ @property({ type: String }) controlUri: string;
92
+ @state() selectedScope: string = null;
93
+
94
+ @state() reports: SummarizedCspReport[] = [];
95
+ @state() selectedReport: SummarizedCspReport | null = null;
96
+ @state() suggestions: MutationSuggestion[] = [];
97
+
98
+ private peripheralEvent: RegularEvent;
99
+
100
+ public override connectedCallback(): void {
101
+ super.connectedCallback();
102
+ this.fetchReports();
103
+ this.peripheralEvent = new RegularEvent('click', (evt: Event, target: HTMLElement) => {
104
+ if (target.dataset.cspReportsHandler === 'refresh') {
105
+ evt.preventDefault();
106
+ this.fetchReports();
107
+ }
108
+ });
109
+ this.peripheralEvent.delegateTo(document, '[data-csp-reports-handler]');
110
+ }
111
+
112
+ public override disconnectedCallback(): void {
113
+ super.disconnectedCallback();
114
+ this.peripheralEvent?.release();
115
+ }
116
+
117
+ protected override createRenderRoot(): HTMLElement | ShadowRoot {
118
+ return this;
119
+ }
120
+
121
+ protected override render(): TemplateResult {
122
+ return html`
123
+ <div class="infolist-container infolist-overlay">
124
+ <div class="infolist">
125
+ <div class="infolist-header">
126
+ ${this.renderNavigation()}
127
+ </div>
128
+ </div>
129
+ </div>
130
+
131
+ <div class="infolist-container">
132
+ <div class="infolist">
133
+ <div class="infolist-content">
134
+ <div class="table-fit mb-0">
135
+ <table class="table table-striped">
136
+ <thead>
137
+ <tr>
138
+ <th>${lll('label.created') || 'Created'}</th>
139
+ <th>${lll('label.scope') || 'Scope'}</th>
140
+ <th>${lll('label.violation') || 'Violation'}</th>
141
+ <th>${lll('label.uri') || 'URI'}</th>
142
+ <th></th>
143
+ </tr>
144
+ </thead>
145
+ <tbody>
146
+ ${this.reports.length === 0 ? html`
147
+ <tr><td colspan="5">${lll('label.label.noEntriesAvailable') || 'No entries available.'}</td></tr>
148
+ ` : nothing}
149
+ ${this.reports.map((report: SummarizedCspReport) => html`
150
+ <tr class=${classMap({ 'table-info': this.selectedReport === report })} data-mutation-group=${report.mutationHashes.join('-')}
151
+ @click=${() => this.selectReport(report)}>
152
+ <td>${report.created}</td>
153
+ <td>${report.scope}</td>
154
+ <td>
155
+ <span class="badge badge-warning">${report.count}</span>
156
+ ${report.details.effectiveDirective}
157
+ </td>
158
+ <td>${this.shortenUri(report.details.blockedUri)}</td>
159
+ <td>${report.attributes.join(', ')}</td>
160
+ </tr>
161
+ `)}
162
+ </tbody>
163
+ </table>
164
+ </div>
165
+ </div>
166
+ <div class="infolist-info${this.selectedReport ? ' infolist-info-showrecord' : ''}">
167
+ ${this.renderGuide()}
168
+ ${this.renderSelectedReport()}
169
+ </div>
170
+ </div>
171
+ </div>
172
+ `;
173
+ }
174
+
175
+ protected renderNavigation(): TemplateResult {
176
+ return html`
177
+ <div class="btn-toolbar">
178
+ <button type="button" class="btn btn-default dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" title="${lll('label.scope') || 'Scope'}">
179
+ ${null === this.selectedScope ? lll('label.all') || 'ALL' : this.selectedScope}
180
+ </button>
181
+ <ul class="dropdown-menu">
182
+ <button class="dropdown-item dropdown-item-spaced" title="${lll('label.all') || 'ALL'}" @click=${() => this.selectScope(null)}>
183
+ <span class="${null === this.selectedScope ? 'text-primary' : '' }">
184
+ <typo3-backend-icon identifier="${null === this.selectedScope ? 'actions-dot' : 'empty-empty'}" size="small"></typo3-backend-icon>
185
+ </span>
186
+ ${lll('label.all') || 'ALL'}
187
+ </button>
188
+ ${this.scopes.map((scope: string) => html`
189
+ <li>
190
+ <button class="dropdown-item dropdown-item-spaced" title="${scope}" @click=${() => this.selectScope(scope)}>
191
+ <span class="${scope === this.selectedScope ? 'text-primary' : '' }">
192
+ <typo3-backend-icon identifier="${scope === this.selectedScope ? 'actions-dot' : 'empty-empty'}" size="small"></typo3-backend-icon>
193
+ </span>
194
+ ${scope}
195
+ </button>
196
+ </li>`)}
197
+ </ul>
198
+ <button type="button" class="btn btn-danger" title="${lll('label.removeAll') || 'Remove all'}" @click=${() => this.invokeDeleteReportsAction()}>
199
+ ${lll('label.removeAll') || 'Remove all'}
200
+ ${this.selectedScope !== null ? html`"${this.selectedScope}"` : nothing}
201
+ </button>
202
+ </div>`;
203
+ }
204
+
205
+ protected renderGuide(): TemplateResult {
206
+ return html`${!this.selectedReport ? html`
207
+ <div class="infolist-info-norecord">
208
+ <div class="card mb-0">
209
+ <div class="card-body">
210
+ <p>${ lll('label.guide.no_record_selected') || 'Select a row to see more information.'}</p>
211
+ </div>
212
+ </div>
213
+ </div>
214
+ ` : nothing }`;
215
+ }
216
+
217
+ protected renderSelectedReport(): TemplateResult {
218
+ const report = this.selectedReport;
219
+ return html`${report ? html`
220
+ <div class="infolist-info-record">
221
+ <div class="card mb-0">
222
+ <div class="card-header">
223
+ <h3>${ lll('label.details') || 'Details'}</h3>
224
+ </div>
225
+ <div class="card-body">
226
+ <dl>
227
+ <dt>${ lll('label.directive') || 'Directive'} / ${ lll('label.disposition') || 'Disposition'}</dt>
228
+ <dd>${report.details.effectiveDirective} / ${report.details.disposition}</dd>
229
+
230
+ <dt>${ lll('label.document_uri') || 'Document URI'}</dt>
231
+ <dd>${report.details.documentUri} ${this.renderCodeLocation(report)}</dd>
232
+
233
+ ${report.details.sourceFile && report.details.sourceFile !== report.details.documentUri ? html`
234
+ <dt>${ lll('label.source_file') || 'Source File'}</dt>
235
+ <dd>${report.details.sourceFile}</dd>
236
+ ` : nothing}
237
+
238
+ <dt>${ lll('label.blocked_uri') || 'Blocked URI'}</dt>
239
+ <dd>${report.details.blockedUri}</dd>
240
+
241
+ ${report.details.scriptSample ? html`
242
+ <dt>${ lll('label.sample') || 'Sample'}</dt>
243
+ <dd><code>${report.details.scriptSample}</code></dd>
244
+ ` : nothing}
245
+
246
+ ${report.meta.agent ? html`
247
+ <dt>${ lll('label.user_agent') || 'User Agent'}</dt>
248
+ <dd><code>${report.meta.agent}</code></dd>
249
+ ` : nothing}
250
+
251
+ <dt>${ lll('label.uuid') || 'UUID'}</dt>
252
+ <dd><code>${report.uuid}</code></dd>
253
+
254
+ <dt>${ lll('label.summary') || 'Summary'}</dt>
255
+ <dd><code>${report.summary}</code></dd>
256
+ </dl>
257
+ </div>
258
+ ${this.suggestions.length > 0 ? html`
259
+ <div class="card-header">
260
+ <h3>${ lll('label.suggestions') || 'Suggestions'}</h3>
261
+ </div>
262
+ ` : nothing}
263
+ ${this.suggestions.map((suggestion: MutationSuggestion) => html`
264
+ <div class="card-body">
265
+ <h4>${suggestion.label || suggestion.identifier}</h4>
266
+ ${suggestion.collection.mutations.map((mutation: Mutation) => html`
267
+ <p>
268
+ <i>${mutation.mode}</i>
269
+ <code>${mutation.directive}: ${mutation.sources.join(' ')}</code>
270
+ </p>
271
+ `)}
272
+ <button class="btn btn-primary" @click=${() => this.invokeMutateReportAction(report, suggestion)}>
273
+ <typo3-backend-icon identifier="actions-check" size="small"></typo3-backend-icon>
274
+ ${ lll('button.apply') || 'Apply'}
275
+ </button>
276
+ </div>
277
+ `)}
278
+
279
+ <div class="card-footer">
280
+ <button class="btn btn-default" @click=${() => this.selectReport(null)}>
281
+ <typo3-backend-icon identifier="actions-close" size="small"></typo3-backend-icon>
282
+ ${ lll('button.close') || 'Close'}
283
+ </button>
284
+ <button class="btn btn-default" @click=${() => this.invokeMuteReportAction(report)}>
285
+ <typo3-backend-icon identifier="actions-ban" size="small"></typo3-backend-icon>
286
+ ${ lll('button.mute') || 'Mute'}
287
+ </button>
288
+ <button class="btn btn-default" @click=${() => this.invokeDeleteReportAction(report)}>
289
+ <typo3-backend-icon identifier="actions-delete" size="small"></typo3-backend-icon>
290
+ ${ lll('button.delete') || 'Delete'}
291
+ </button>
292
+ </div>
293
+ </div>
294
+ </div>
295
+ ` : nothing }`;
296
+ }
297
+
298
+ private renderCodeLocation(report: SummarizedCspReport): TemplateResult|symbol {
299
+ if (!report.details.lineNumber) {
300
+ return nothing;
301
+ }
302
+ const parts = [report.details.lineNumber];
303
+ if (report.details.columnNumber) {
304
+ parts.push(report.details.columnNumber);
305
+ }
306
+ return html`(${parts.join(':')})`;
307
+ }
308
+
309
+ private selectReport(report: SummarizedCspReport): void {
310
+ this.suggestions = [];
311
+ if (report !== null && this.selectedReport !== report) {
312
+ this.selectedReport = report;
313
+ this.invokeHandleReportAction(report)
314
+ .then((suggestions: MutationSuggestion[]) => this.suggestions = suggestions);
315
+ } else {
316
+ this.selectedReport = null;
317
+ }
318
+ }
319
+
320
+ private selectScope(scope: string): void {
321
+ this.selectedScope = scope;
322
+ this.fetchReports();
323
+ }
324
+
325
+ private fetchReports(): void {
326
+ this.invokeFetchReportsAction().then((reports: SummarizedCspReport[]) => this.reports = reports);
327
+ }
328
+
329
+ /*
330
+ * Remote API calls
331
+ */
332
+
333
+ private filterReports(...uuids: string[]): void {
334
+ if (uuids.includes(this.selectedReport?.uuid)) {
335
+ this.selectedReport = null;
336
+ }
337
+ this.reports = this.reports.filter((report: SummarizedCspReport) => !uuids.includes(report.uuid));
338
+ }
339
+
340
+ private invokeFetchReportsAction(): Promise<SummarizedCspReport[]> {
341
+ return (new AjaxRequest(this.controlUri))
342
+ .post({ action: 'fetchReports', scope: this.selectedScope || '' })
343
+ .then((response: AjaxResponse) => response.resolve('application/json'));
344
+ }
345
+
346
+ private invokeHandleReportAction(report: SummarizedCspReport) {
347
+ return (new AjaxRequest(this.controlUri))
348
+ .post({ action: 'handleReport', uuid: report.uuid })
349
+ .then((response: AjaxResponse) => response.resolve('application/json'));
350
+ }
351
+
352
+ private invokeMutateReportAction(report: SummarizedCspReport, suggestion: MutationSuggestion) {
353
+ const summaries = this.reports
354
+ .filter((other: SummarizedCspReport) => other.mutationHashes.includes(suggestion.hash))
355
+ .map((other: SummarizedCspReport) => other.summary);
356
+ return (new AjaxRequest(this.controlUri))
357
+ .post({ action: 'mutateReport', scope: report.scope, hmac: suggestion.hmac, suggestion, summaries })
358
+ .then((response: AjaxResponse) => response.resolve('application/json'))
359
+ .then((response: CspReportUuids) => this.filterReports(...response.uuids));
360
+ }
361
+
362
+ private invokeMuteReportAction(report: SummarizedCspReport): void {
363
+ (new AjaxRequest(this.controlUri))
364
+ .post({ action: 'muteReport', summaries: [report.summary] })
365
+ .then((response: AjaxResponse) => response.resolve('application/json'))
366
+ .then((response: CspReportUuids) => this.filterReports(...response.uuids));
367
+ }
368
+
369
+ private invokeDeleteReportAction(report: SummarizedCspReport): void {
370
+ (new AjaxRequest(this.controlUri))
371
+ .post({ action: 'deleteReport', summaries: [report.summary] })
372
+ .then((response: AjaxResponse) => response.resolve('application/json'))
373
+ .then((response: CspReportUuids) => this.filterReports(...response.uuids));
374
+ }
375
+
376
+ private invokeDeleteReportsAction(): void {
377
+ (new AjaxRequest(this.controlUri))
378
+ .post({ action: 'deleteReports', scope: this.selectedScope || '' })
379
+ .then((response: AjaxResponse) => response.resolve('application/json'))
380
+ .then(() => this.fetchReports())
381
+ .then(() => this.selectReport(null));
382
+ }
383
+
384
+ /*
385
+ * Helper methods
386
+ */
387
+
388
+ private shortenUri(value: string): string
389
+ {
390
+ if (value === 'inline') {
391
+ return value;
392
+ }
393
+ try {
394
+ const uri = new URL(value);
395
+ return uri.hostname;
396
+ } catch {
397
+ return value;
398
+ }
399
+ }
400
+ }
401
+
402
+ declare global {
403
+ interface HTMLElementTagNameMap {
404
+ 'typo3-backend-security-csp-reports': CspReports;
405
+ }
406
+ }
@@ -0,0 +1,249 @@
1
+ /*
2
+ * This file is part of the TYPO3 CMS project.
3
+ *
4
+ * It is free software; you can redistribute it and/or modify it under
5
+ * the terms of the GNU General Public License, either version 2
6
+ * of the License, or any later version.
7
+ *
8
+ * For the full copyright and license information, please read the
9
+ * LICENSE.txt file that was distributed with this source code.
10
+ *
11
+ * The TYPO3 project - inspiring people to share!
12
+ */
13
+
14
+ import { customElement, property, query, state } from 'lit/decorators';
15
+ import { html, LitElement, nothing, type PropertyValues, type TemplateResult } from 'lit';
16
+ import AjaxRequest from '@typo3/core/ajax/ajax-request';
17
+ import { AjaxResponse } from '@typo3/core/ajax/ajax-response';
18
+ import Viewport from '@typo3/backend/viewport';
19
+ import { topLevelModuleImport } from '@typo3/backend/utility/top-level-module-import';
20
+ import Modal, { Sizes } from '@typo3/backend/modal';
21
+ import { SeverityEnum } from '@typo3/backend/enum/severity';
22
+ import type { ReactiveElement } from '@lit/reactive-element';
23
+
24
+ interface SudoModeResponse {
25
+ message: string;
26
+ redirect?: {
27
+ uri: string,
28
+ }
29
+ }
30
+
31
+ interface Labels {
32
+ cancel: string;
33
+ verify: string;
34
+ password: string;
35
+ verifyWithUserPassword: string;
36
+ verifyWithInstallToolPassword: string;
37
+ accessGranted: string;
38
+ invalidPassword: string;
39
+ userPasswordMode: string;
40
+ installToolPasswordMode: string;
41
+ verificationFailed: string;
42
+ verificationExpired: string;
43
+ sudoModeUserPasswordExplanation: string;
44
+ sudoModeInstallToolPasswordExplanation: string;
45
+ }
46
+
47
+ abstract class SudoModeProperties extends LitElement {
48
+ @property({ type: String }) verifyActionUri: string;
49
+ @property({ type: String }) cancelUri: string;
50
+ @property({ type: Boolean }) isAjax: boolean;
51
+ @property({ type: Boolean, attribute: 'has-fatal-error' }) hasFatalError: boolean;
52
+ @property({ type: Boolean, attribute: 'allow-install-tool-password' }) allowInstallToolPassword: boolean;
53
+ @property({ type: Object }) labels: Labels;
54
+ public windowRef: Window | undefined;
55
+ }
56
+
57
+ export const initiateSudoModeModal = async (properties: Omit<SudoModeProperties, keyof LitElement>): Promise<void> => {
58
+ const isInIframe = window.location !== window.parent.location;
59
+ if (isInIframe) {
60
+ // Create a top-level instance
61
+ topLevelModuleImport('@typo3/backend/security/element/sudo-mode.js');
62
+ }
63
+ const el = top.document.createElement('typo3-backend-security-sudo-mode');
64
+ Object.assign(el, properties);
65
+ el.windowRef = window;
66
+ top.document.body.append(el);
67
+ return new Promise<void>((resolve, reject) => {
68
+ el.addEventListener('typo3:sudo-mode:verified', () => resolve());
69
+ el.addEventListener('typo3:sudo-mode:finished', () => reject());
70
+ });
71
+ };
72
+
73
+ /**
74
+ * Web Component showing the sudo mode password dialogs. The password verification
75
+ * happens via AJAX, the redirect to the actually requested resources is triggered
76
+ * by this JavaScript component as well - since it is capable of navigating to the
77
+ * `top` frame directly (compared to using `target` in e.g. Fluid HTML).
78
+ */
79
+ @customElement('typo3-backend-security-sudo-mode')
80
+ export class SudoMode extends SudoModeProperties {
81
+
82
+ protected override render() {
83
+ return nothing;
84
+ }
85
+
86
+ protected override async firstUpdated() {
87
+ const isInIframe = window.location !== window.parent.location;
88
+ // Launched from /sudo-mode/module route
89
+ if (isInIframe) {
90
+ try {
91
+ await initiateSudoModeModal(this.getPropertyValues());
92
+ } catch {
93
+ // Go back to previous route when the modal is closed without verification
94
+ history.go(-1);
95
+ }
96
+ return;
97
+ }
98
+
99
+ Modal.advanced({
100
+ title: this.hasFatalError ? this.labels.verificationFailed : this.labels.verifyWithUserPassword,
101
+ severity: this.hasFatalError ? SeverityEnum.error : SeverityEnum.notice,
102
+ size: Sizes.small,
103
+ additionalCssClasses: ['modal-sudo-mode-verification'],
104
+ buttons: [
105
+ this.hasFatalError ? {
106
+ text: this.labels.cancel,
107
+ btnClass: 'btn-default',
108
+ trigger: () => {
109
+ top.location.href = this.cancelUri;
110
+ },
111
+ } : {
112
+ text: this.labels.verify,
113
+ name: 'verify',
114
+ form: 'verify-sudo-mode',
115
+ btnClass: 'btn-primary',
116
+ }
117
+ ],
118
+ content: html`
119
+ <typo3-backend-security-sudo-mode-form
120
+ .labels=${this.labels}
121
+ .verifyActionUri=${this.verifyActionUri}
122
+ .cancelUri=${this.cancelUri}
123
+ .isAjax=${this.isAjax}
124
+ .hasFatalError=${this.hasFatalError}
125
+ .allowInstallToolPassword=${this.allowInstallToolPassword}
126
+ .windowRef=${this.windowRef}
127
+ @typo3:sudo-mode:verified=${() => this.dispatchEvent(new Event('typo3:sudo-mode:verified'))}
128
+ ></typo3-backend-security-sudo-mode-form>
129
+ `
130
+ }).addEventListener('typo3-modal-hidden', (): void => {
131
+ this.dispatchEvent(new Event('typo3:sudo-mode:finished'));
132
+ this.remove();
133
+ });
134
+ }
135
+
136
+ protected getPropertyValues(): Omit<this, keyof LitElement> {
137
+ const properties = {} as Omit<this, keyof LitElement>;
138
+ const ctor = this.constructor as typeof ReactiveElement;
139
+ for (const key of ctor.elementProperties.keys() as IterableIterator<keyof Omit<this, keyof LitElement>>) {
140
+ properties[key] = this[key];
141
+ }
142
+ return properties;
143
+ }
144
+ }
145
+
146
+ @customElement('typo3-backend-security-sudo-mode-form')
147
+ export class SudoModeForm extends SudoModeProperties {
148
+ @state() useInstallToolPassword = false;
149
+ @state() errorMessage: string = null;
150
+ @query('#password') passwordElement: HTMLInputElement;
151
+
152
+ protected override createRenderRoot(): HTMLElement | ShadowRoot {
153
+ return this;
154
+ }
155
+
156
+ protected override render(): TemplateResult {
157
+ if (this.hasFatalError) {
158
+ return html`
159
+ <div>
160
+ <div class="alert alert-danger">${this.labels.verificationExpired}</div>
161
+ </div>
162
+ `;
163
+ }
164
+ return html`
165
+ <div>
166
+ ${this.errorMessage ? html`
167
+ <div class="alert alert-danger" id="invalid-password">${this.labels[this.errorMessage as keyof Labels] || this.errorMessage}</div>
168
+ ` : nothing}
169
+ <p>${this.useInstallToolPassword ? this.labels.sudoModeInstallToolPasswordExplanation : this.labels.sudoModeUserPasswordExplanation}</p>
170
+ <form method="post" class="form" id="verify-sudo-mode" spellcheck="false" @submit=${(evt: SubmitEvent) => this.verifyPassword(evt)}>
171
+ ${this.useInstallToolPassword ? nothing : html`
172
+ <input hidden aria-hidden="true" type="text" autocomplete="username" value=${TYPO3.configuration.username}>
173
+ `}
174
+ <div class="form-group">
175
+ <label class="form-label" for="password">${this.labels.password}</label>
176
+ <input required="required" class="form-control" id="password" type="password" name="password" autofocus
177
+ autocomplete=${this.useInstallToolPassword ? 'section-install current-password' : 'current-password'}>
178
+ </div>
179
+ </form>
180
+ ${!this.allowInstallToolPassword ? nothing : html`
181
+ <div class="text-end">
182
+ <a href="#" @click=${(evt: MouseEvent) => this.toggleUseInstallToolPassword(evt)}>
183
+ ${this.useInstallToolPassword ? this.labels.userPasswordMode : this.labels.installToolPasswordMode}
184
+ </a>
185
+ </div>
186
+ `}
187
+ </div>
188
+ `;
189
+ }
190
+
191
+ protected override updated(changedProperties: PropertyValues): void {
192
+ if (changedProperties.has('useInstallToolPassword')) {
193
+ this.closest('typo3-backend-modal').modalTitle = this.getModalTitle();
194
+ }
195
+ }
196
+
197
+ protected getModalTitle() {
198
+ if (this.hasFatalError) {
199
+ return this.labels.verificationFailed;
200
+ }
201
+ if (this.useInstallToolPassword) {
202
+ return this.labels.verifyWithInstallToolPassword;
203
+ }
204
+ return this.labels.verifyWithUserPassword;
205
+ }
206
+
207
+ private async verifyPassword(evt: SubmitEvent): Promise<void> {
208
+ evt.preventDefault();
209
+ this.errorMessage = null;
210
+ try {
211
+ const response = await new AjaxRequest(this.verifyActionUri).post({
212
+ password: this.passwordElement.value,
213
+ useInstallToolPassword: this.useInstallToolPassword ? 1 : 0
214
+ });
215
+
216
+ const responseData: SudoModeResponse = await response.resolve('application/json');
217
+ this.dispatchEvent(new Event('typo3:sudo-mode:verified'));
218
+ this.closest('typo3-backend-modal').hideModal();
219
+ if (!this.isAjax && responseData.redirect) {
220
+ const { uri } = responseData.redirect;
221
+ const windowRef = this.windowRef ?? window;
222
+ if (windowRef.name === 'list_frame') {
223
+ Viewport.ContentContainer.setUrl(uri);
224
+ } else {
225
+ windowRef.location.assign(uri);
226
+ }
227
+ }
228
+ } catch (e: unknown) {
229
+ if (e instanceof AjaxResponse) {
230
+ const response = await e.resolve('application/json');
231
+ this.errorMessage = response.message;
232
+ } else {
233
+ throw e;
234
+ }
235
+ }
236
+ }
237
+
238
+ private toggleUseInstallToolPassword(evt: MouseEvent): void {
239
+ evt.preventDefault();
240
+ this.useInstallToolPassword = !this.useInstallToolPassword;
241
+ }
242
+ }
243
+
244
+ declare global {
245
+ interface HTMLElementTagNameMap {
246
+ 'typo3-backend-security-sudo-mode': SudoMode;
247
+ 'typo3-backend-security-sudo-mode-form': SudoModeForm;
248
+ }
249
+ }
@@ -0,0 +1,19 @@
1
+ import type { RequestMiddleware, RequestHandler } from '@typo3/core/ajax/ajax-request-types';
2
+
3
+ export const sudoModeInterceptor: RequestMiddleware = async (request: Request, next: RequestHandler): Promise<Response> => {
4
+ // Requests are not immutable, therefore we clone to be able to re-submit exactly the same request later on
5
+ const requestClone = request.clone();
6
+ const response = await next(request);
7
+ if (response.status === 422) {
8
+ const { initiateSudoModeModal } = await import('@typo3/backend/security/element/sudo-mode');
9
+ const data = await response.json();
10
+ try {
11
+ await initiateSudoModeModal(data.sudoModeInitialization);
12
+ } catch {
13
+ // sudo mode was aborted
14
+ return response;
15
+ }
16
+ return next(requestClone);
17
+ }
18
+ return response;
19
+ };