@fiduswriter/editor 0.1.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/LICENSE +661 -0
- package/README.md +22 -0
- package/dist/bibliography/tools.js +53 -0
- package/dist/bibliography/tools.js.map +1 -0
- package/dist/citations/index.js +339 -0
- package/dist/citations/index.js.map +1 -0
- package/dist/citations/render.js +47 -0
- package/dist/citations/render.js.map +1 -0
- package/dist/clipboard/copy/index.js +2 -0
- package/dist/clipboard/copy/index.js.map +1 -0
- package/dist/clipboard/copy/schema.js +54 -0
- package/dist/clipboard/copy/schema.js.map +1 -0
- package/dist/clipboard/copy/serializers.js +132 -0
- package/dist/clipboard/copy/serializers.js.map +1 -0
- package/dist/clipboard/paste/fidus_writer.js +45 -0
- package/dist/clipboard/paste/fidus_writer.js.map +1 -0
- package/dist/clipboard/paste/general.js +76 -0
- package/dist/clipboard/paste/general.js.map +1 -0
- package/dist/clipboard/paste/google_docs.js +24 -0
- package/dist/clipboard/paste/google_docs.js.map +1 -0
- package/dist/clipboard/paste/html.js +68 -0
- package/dist/clipboard/paste/html.js.map +1 -0
- package/dist/clipboard/paste/index.js +3 -0
- package/dist/clipboard/paste/index.js.map +1 -0
- package/dist/clipboard/paste/libreoffice_writer.js +27 -0
- package/dist/clipboard/paste/libreoffice_writer.js.map +1 -0
- package/dist/clipboard/paste/microsoft_word.js +79 -0
- package/dist/clipboard/paste/microsoft_word.js.map +1 -0
- package/dist/clipboard/paste/text.js +41 -0
- package/dist/clipboard/paste/text.js.map +1 -0
- package/dist/collab/chat.js +154 -0
- package/dist/collab/chat.js.map +1 -0
- package/dist/collab/colors.js +62 -0
- package/dist/collab/colors.js.map +1 -0
- package/dist/collab/doc.js +1090 -0
- package/dist/collab/doc.js.map +1 -0
- package/dist/collab/index.js +75 -0
- package/dist/collab/index.js.map +1 -0
- package/dist/collab/merge/changeset.js +90 -0
- package/dist/collab/merge/changeset.js.map +1 -0
- package/dist/collab/merge/editor.js +708 -0
- package/dist/collab/merge/editor.js.map +1 -0
- package/dist/collab/merge/footnotes.js +149 -0
- package/dist/collab/merge/footnotes.js.map +1 -0
- package/dist/collab/merge/index.js +270 -0
- package/dist/collab/merge/index.js.map +1 -0
- package/dist/collab/merge/recreate_transform.js +259 -0
- package/dist/collab/merge/recreate_transform.js.map +1 -0
- package/dist/collab/merge/schema.js +117 -0
- package/dist/collab/merge/schema.js.map +1 -0
- package/dist/collab/merge/state_plugins/action.js +138 -0
- package/dist/collab/merge/state_plugins/action.js.map +1 -0
- package/dist/collab/merge/state_plugins/clipboard.js +32 -0
- package/dist/collab/merge/state_plugins/clipboard.js.map +1 -0
- package/dist/collab/merge/state_plugins/diff.js +541 -0
- package/dist/collab/merge/state_plugins/diff.js.map +1 -0
- package/dist/collab/merge/state_plugins/index.js +3 -0
- package/dist/collab/merge/state_plugins/index.js.map +1 -0
- package/dist/collab/merge/tools.js +175 -0
- package/dist/collab/merge/tools.js.map +1 -0
- package/dist/collab/templates.js +10 -0
- package/dist/collab/templates.js.map +1 -0
- package/dist/comments/comment.js +17 -0
- package/dist/comments/comment.js.map +1 -0
- package/dist/comments/editors/answer.js +43 -0
- package/dist/comments/editors/answer.js.map +1 -0
- package/dist/comments/editors/comment.js +278 -0
- package/dist/comments/editors/comment.js.map +1 -0
- package/dist/comments/editors/index.js +4 -0
- package/dist/comments/editors/index.js.map +1 -0
- package/dist/comments/editors/notify.js +13 -0
- package/dist/comments/editors/notify.js.map +1 -0
- package/dist/comments/editors/schema.js +60 -0
- package/dist/comments/editors/schema.js.map +1 -0
- package/dist/comments/index.js +11 -0
- package/dist/comments/index.js.map +1 -0
- package/dist/comments/interactions.js +379 -0
- package/dist/comments/interactions.js.map +1 -0
- package/dist/comments/store.js +438 -0
- package/dist/comments/store.js.map +1 -0
- package/dist/contacts/add_dialog.js +88 -0
- package/dist/contacts/add_dialog.js.map +1 -0
- package/dist/contacts/templates.js +23 -0
- package/dist/contacts/templates.js.map +1 -0
- package/dist/copyright_dialog/index.js +148 -0
- package/dist/copyright_dialog/index.js.map +1 -0
- package/dist/copyright_dialog/templates.js +48 -0
- package/dist/copyright_dialog/templates.js.map +1 -0
- package/dist/databases/bibliography.js +162 -0
- package/dist/databases/bibliography.js.map +1 -0
- package/dist/databases/images.js +260 -0
- package/dist/databases/images.js.map +1 -0
- package/dist/databases/index.js +55 -0
- package/dist/databases/index.js.map +1 -0
- package/dist/dialogs/citation.js +321 -0
- package/dist/dialogs/citation.js.map +1 -0
- package/dist/dialogs/code_block.js +192 -0
- package/dist/dialogs/code_block.js.map +1 -0
- package/dist/dialogs/contributor.js +132 -0
- package/dist/dialogs/contributor.js.map +1 -0
- package/dist/dialogs/figure.js +378 -0
- package/dist/dialogs/figure.js.map +1 -0
- package/dist/dialogs/index.js +11 -0
- package/dist/dialogs/index.js.map +1 -0
- package/dist/dialogs/language.js +47 -0
- package/dist/dialogs/language.js.map +1 -0
- package/dist/dialogs/link.js +243 -0
- package/dist/dialogs/link.js.map +1 -0
- package/dist/dialogs/math.js +121 -0
- package/dist/dialogs/math.js.map +1 -0
- package/dist/dialogs/ordered_list.js +67 -0
- package/dist/dialogs/ordered_list.js.map +1 -0
- package/dist/dialogs/revision.js +36 -0
- package/dist/dialogs/revision.js.map +1 -0
- package/dist/dialogs/subsup.js +109 -0
- package/dist/dialogs/subsup.js.map +1 -0
- package/dist/dialogs/table.js +217 -0
- package/dist/dialogs/table.js.map +1 -0
- package/dist/dialogs/templates.js +366 -0
- package/dist/dialogs/templates.js.map +1 -0
- package/dist/document_template/exporter.js +83 -0
- package/dist/document_template/exporter.js.map +1 -0
- package/dist/document_template/index.js +327 -0
- package/dist/document_template/index.js.map +1 -0
- package/dist/documents/access_rights/index.js +532 -0
- package/dist/documents/access_rights/index.js.map +1 -0
- package/dist/documents/access_rights/templates.js +150 -0
- package/dist/documents/access_rights/templates.js.map +1 -0
- package/dist/e2ee/encryptor.js +201 -0
- package/dist/e2ee/encryptor.js.map +1 -0
- package/dist/e2ee/key-manager.js +171 -0
- package/dist/e2ee/key-manager.js.map +1 -0
- package/dist/e2ee/passphrase-crypto.js +365 -0
- package/dist/e2ee/passphrase-crypto.js.map +1 -0
- package/dist/e2ee/passphrase-dialog.js +548 -0
- package/dist/e2ee/passphrase-dialog.js.map +1 -0
- package/dist/e2ee/passphrase-manager.js +350 -0
- package/dist/e2ee/passphrase-manager.js.map +1 -0
- package/dist/e2ee/password-dialog.js +552 -0
- package/dist/e2ee/password-dialog.js.map +1 -0
- package/dist/e2ee/snapshot-manager.js +238 -0
- package/dist/e2ee/snapshot-manager.js.map +1 -0
- package/dist/exporter/native/copy.js +29 -0
- package/dist/exporter/native/copy.js.map +1 -0
- package/dist/exporter/native/file.js +19 -0
- package/dist/exporter/native/file.js.map +1 -0
- package/dist/exporter/native/index.js +4 -0
- package/dist/exporter/native/index.js.map +1 -0
- package/dist/exporter/native/revision.js +54 -0
- package/dist/exporter/native/revision.js.map +1 -0
- package/dist/exporter/native/zip.js +2 -0
- package/dist/exporter/native/zip.js.map +1 -0
- package/dist/footnotes/editor.js +180 -0
- package/dist/footnotes/editor.js.map +1 -0
- package/dist/footnotes/index.js +15 -0
- package/dist/footnotes/index.js.map +1 -0
- package/dist/footnotes/layout.js +125 -0
- package/dist/footnotes/layout.js.map +1 -0
- package/dist/footnotes/state_plugins/access_rights.js +25 -0
- package/dist/footnotes/state_plugins/access_rights.js.map +1 -0
- package/dist/footnotes/state_plugins/index.js +2 -0
- package/dist/footnotes/state_plugins/index.js.map +1 -0
- package/dist/images/edit_dialog/edit_dialog/index.js +186 -0
- package/dist/images/edit_dialog/edit_dialog/index.js.map +1 -0
- package/dist/images/edit_dialog/edit_dialog/model.js +152 -0
- package/dist/images/edit_dialog/edit_dialog/model.js.map +1 -0
- package/dist/images/edit_dialog/edit_dialog/templates.js +33 -0
- package/dist/images/edit_dialog/edit_dialog/templates.js.map +1 -0
- package/dist/images/edit_dialog/model.js +6 -0
- package/dist/images/edit_dialog/model.js.map +1 -0
- package/dist/images/selection_dialog/index.js +149 -0
- package/dist/images/selection_dialog/index.js.map +1 -0
- package/dist/index.js +1002 -0
- package/dist/index.js.map +1 -0
- package/dist/keymap.js +73 -0
- package/dist/keymap.js.map +1 -0
- package/dist/marginboxes/index.js +674 -0
- package/dist/marginboxes/index.js.map +1 -0
- package/dist/marginboxes/templates.js +447 -0
- package/dist/marginboxes/templates.js.map +1 -0
- package/dist/menus/code_block/index.js +2 -0
- package/dist/menus/code_block/index.js.map +1 -0
- package/dist/menus/code_block/model.js +49 -0
- package/dist/menus/code_block/model.js.map +1 -0
- package/dist/menus/figure/index.js +3 -0
- package/dist/menus/figure/index.js.map +1 -0
- package/dist/menus/figure/model.js +80 -0
- package/dist/menus/figure/model.js.map +1 -0
- package/dist/menus/figure/utils.js +6 -0
- package/dist/menus/figure/utils.js.map +1 -0
- package/dist/menus/headerbar/index.js +3 -0
- package/dist/menus/headerbar/index.js.map +1 -0
- package/dist/menus/headerbar/model.js +743 -0
- package/dist/menus/headerbar/model.js.map +1 -0
- package/dist/menus/headerbar/view.js +579 -0
- package/dist/menus/headerbar/view.js.map +1 -0
- package/dist/menus/image/index.js +2 -0
- package/dist/menus/image/index.js.map +1 -0
- package/dist/menus/image/model.js +32 -0
- package/dist/menus/image/model.js.map +1 -0
- package/dist/menus/index.js +10 -0
- package/dist/menus/index.js.map +1 -0
- package/dist/menus/navigator/index.js +2 -0
- package/dist/menus/navigator/index.js.map +1 -0
- package/dist/menus/navigator/model.js +29 -0
- package/dist/menus/navigator/model.js.map +1 -0
- package/dist/menus/ordered_list/index.js +2 -0
- package/dist/menus/ordered_list/index.js.map +1 -0
- package/dist/menus/ordered_list/model.js +17 -0
- package/dist/menus/ordered_list/model.js.map +1 -0
- package/dist/menus/selection/index.js +3 -0
- package/dist/menus/selection/index.js.map +1 -0
- package/dist/menus/selection/model.js +108 -0
- package/dist/menus/selection/model.js.map +1 -0
- package/dist/menus/selection/view.js +125 -0
- package/dist/menus/selection/view.js.map +1 -0
- package/dist/menus/table/index.js +2 -0
- package/dist/menus/table/index.js.map +1 -0
- package/dist/menus/table/model.js +319 -0
- package/dist/menus/table/model.js.map +1 -0
- package/dist/menus/toolbar/index.js +3 -0
- package/dist/menus/toolbar/index.js.map +1 -0
- package/dist/menus/toolbar/model.js +747 -0
- package/dist/menus/toolbar/model.js.map +1 -0
- package/dist/menus/toolbar/view.js +314 -0
- package/dist/menus/toolbar/view.js.map +1 -0
- package/dist/navigator/index.js +435 -0
- package/dist/navigator/index.js.map +1 -0
- package/dist/no_collab_save/index.js +169 -0
- package/dist/no_collab_save/index.js.map +1 -0
- package/dist/plugins/citation_dialog/index.js +2 -0
- package/dist/plugins/citation_dialog/index.js.map +1 -0
- package/dist/plugins/editor/index.js +2 -0
- package/dist/plugins/editor/index.js.map +1 -0
- package/dist/state_plugins/access_rights.js +30 -0
- package/dist/state_plugins/access_rights.js.map +1 -0
- package/dist/state_plugins/citation_render.js +78 -0
- package/dist/state_plugins/citation_render.js.map +1 -0
- package/dist/state_plugins/clipboard.js +217 -0
- package/dist/state_plugins/clipboard.js.map +1 -0
- package/dist/state_plugins/code_block.js +165 -0
- package/dist/state_plugins/code_block.js.map +1 -0
- package/dist/state_plugins/collab_carets.js +115 -0
- package/dist/state_plugins/collab_carets.js.map +1 -0
- package/dist/state_plugins/comments.js +197 -0
- package/dist/state_plugins/comments.js.map +1 -0
- package/dist/state_plugins/contributor_input/add_button.js +101 -0
- package/dist/state_plugins/contributor_input/add_button.js.map +1 -0
- package/dist/state_plugins/contributor_input/dropup.js +273 -0
- package/dist/state_plugins/contributor_input/dropup.js.map +1 -0
- package/dist/state_plugins/contributor_input/helpers.js +23 -0
- package/dist/state_plugins/contributor_input/helpers.js.map +1 -0
- package/dist/state_plugins/contributor_input/index.js +3 -0
- package/dist/state_plugins/contributor_input/index.js.map +1 -0
- package/dist/state_plugins/contributor_input/node_view.js +76 -0
- package/dist/state_plugins/contributor_input/node_view.js.map +1 -0
- package/dist/state_plugins/contributor_input/plugin.js +236 -0
- package/dist/state_plugins/contributor_input/plugin.js.map +1 -0
- package/dist/state_plugins/document_template.js +213 -0
- package/dist/state_plugins/document_template.js.map +1 -0
- package/dist/state_plugins/figure.js +90 -0
- package/dist/state_plugins/figure.js.map +1 -0
- package/dist/state_plugins/footnote_markers.js +187 -0
- package/dist/state_plugins/footnote_markers.js.map +1 -0
- package/dist/state_plugins/headerbar.js +10 -0
- package/dist/state_plugins/headerbar.js.map +1 -0
- package/dist/state_plugins/index.js +27 -0
- package/dist/state_plugins/index.js.map +1 -0
- package/dist/state_plugins/inline_math.js +719 -0
- package/dist/state_plugins/inline_math.js.map +1 -0
- package/dist/state_plugins/inline_reference/dropup.js +182 -0
- package/dist/state_plugins/inline_reference/dropup.js.map +1 -0
- package/dist/state_plugins/inline_reference/index.js +2 -0
- package/dist/state_plugins/inline_reference/index.js.map +1 -0
- package/dist/state_plugins/inline_reference/plugin.js +1134 -0
- package/dist/state_plugins/inline_reference/plugin.js.map +1 -0
- package/dist/state_plugins/jump_hidden_nodes.js +47 -0
- package/dist/state_plugins/jump_hidden_nodes.js.map +1 -0
- package/dist/state_plugins/links.js +622 -0
- package/dist/state_plugins/links.js.map +1 -0
- package/dist/state_plugins/marginboxes.js +13 -0
- package/dist/state_plugins/marginboxes.js.map +1 -0
- package/dist/state_plugins/ordered_list_menu.js +72 -0
- package/dist/state_plugins/ordered_list_menu.js.map +1 -0
- package/dist/state_plugins/placeholders.js +98 -0
- package/dist/state_plugins/placeholders.js.map +1 -0
- package/dist/state_plugins/search.js +212 -0
- package/dist/state_plugins/search.js.map +1 -0
- package/dist/state_plugins/selection_menu.js +10 -0
- package/dist/state_plugins/selection_menu.js.map +1 -0
- package/dist/state_plugins/settings.js +191 -0
- package/dist/state_plugins/settings.js.map +1 -0
- package/dist/state_plugins/table.js +104 -0
- package/dist/state_plugins/table.js.map +1 -0
- package/dist/state_plugins/tag_input/helpers.js +55 -0
- package/dist/state_plugins/tag_input/helpers.js.map +1 -0
- package/dist/state_plugins/tag_input/index.js +3 -0
- package/dist/state_plugins/tag_input/index.js.map +1 -0
- package/dist/state_plugins/tag_input/node_view.js +77 -0
- package/dist/state_plugins/tag_input/node_view.js.map +1 -0
- package/dist/state_plugins/tag_input/plugin.js +199 -0
- package/dist/state_plugins/tag_input/plugin.js.map +1 -0
- package/dist/state_plugins/tag_input/tag_editor.js +159 -0
- package/dist/state_plugins/tag_input/tag_editor.js.map +1 -0
- package/dist/state_plugins/tag_input/tag_editor_plugins.js +61 -0
- package/dist/state_plugins/tag_input/tag_editor_plugins.js.map +1 -0
- package/dist/state_plugins/toc_render.js +142 -0
- package/dist/state_plugins/toc_render.js.map +1 -0
- package/dist/state_plugins/toolbar.js +10 -0
- package/dist/state_plugins/toolbar.js.map +1 -0
- package/dist/state_plugins/track/find_selected_changes.js +82 -0
- package/dist/state_plugins/track/find_selected_changes.js.map +1 -0
- package/dist/state_plugins/track/helpers.js +67 -0
- package/dist/state_plugins/track/helpers.js.map +1 -0
- package/dist/state_plugins/track/index.js +3 -0
- package/dist/state_plugins/track/index.js.map +1 -0
- package/dist/state_plugins/track/plugin.js +114 -0
- package/dist/state_plugins/track/plugin.js.map +1 -0
- package/dist/tools/index.js +4 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/key_bindings/index.js +20 -0
- package/dist/tools/key_bindings/index.js.map +1 -0
- package/dist/tools/key_bindings/templates.js +68 -0
- package/dist/tools/key_bindings/templates.js.map +1 -0
- package/dist/tools/search_replace/index.js +275 -0
- package/dist/tools/search_replace/index.js.map +1 -0
- package/dist/tools/search_replace/templates.js +18 -0
- package/dist/tools/search_replace/templates.js.map +1 -0
- package/dist/tools/word_count/index.js +40 -0
- package/dist/tools/word_count/index.js.map +1 -0
- package/dist/tools/word_count/templates.js +27 -0
- package/dist/tools/word_count/templates.js.map +1 -0
- package/dist/track/accept.js +66 -0
- package/dist/track/accept.js.map +1 -0
- package/dist/track/accept_all.js +51 -0
- package/dist/track/accept_all.js.map +1 -0
- package/dist/track/accept_all_no_insertions.js +63 -0
- package/dist/track/accept_all_no_insertions.js.map +1 -0
- package/dist/track/amend_transaction.js +390 -0
- package/dist/track/amend_transaction.js.map +1 -0
- package/dist/track/delete.js +62 -0
- package/dist/track/delete.js.map +1 -0
- package/dist/track/index.js +6 -0
- package/dist/track/index.js.map +1 -0
- package/dist/track/mod.js +86 -0
- package/dist/track/mod.js.map +1 -0
- package/dist/track/reject.js +67 -0
- package/dist/track/reject.js.map +1 -0
- package/dist/track/reject_all.js +56 -0
- package/dist/track/reject_all.js.map +1 -0
- package/package.json +80 -0
- package/src/bibliography/tools.js +58 -0
- package/src/citations/index.js +443 -0
- package/src/citations/render.js +68 -0
- package/src/clipboard/copy/index.js +1 -0
- package/src/clipboard/copy/schema.js +62 -0
- package/src/clipboard/copy/serializers.js +179 -0
- package/src/clipboard/paste/fidus_writer.js +55 -0
- package/src/clipboard/paste/general.js +80 -0
- package/src/clipboard/paste/google_docs.js +26 -0
- package/src/clipboard/paste/html.js +76 -0
- package/src/clipboard/paste/index.js +2 -0
- package/src/clipboard/paste/libreoffice_writer.js +32 -0
- package/src/clipboard/paste/microsoft_word.js +87 -0
- package/src/clipboard/paste/text.js +58 -0
- package/src/collab/chat.js +195 -0
- package/src/collab/colors.js +67 -0
- package/src/collab/doc.js +1436 -0
- package/src/collab/index.js +81 -0
- package/src/collab/merge/changeset.js +103 -0
- package/src/collab/merge/editor.js +1065 -0
- package/src/collab/merge/footnotes.js +175 -0
- package/src/collab/merge/index.js +401 -0
- package/src/collab/merge/recreate_transform.js +326 -0
- package/src/collab/merge/schema.js +135 -0
- package/src/collab/merge/state_plugins/action.js +171 -0
- package/src/collab/merge/state_plugins/clipboard.js +32 -0
- package/src/collab/merge/state_plugins/diff.js +780 -0
- package/src/collab/merge/state_plugins/index.js +2 -0
- package/src/collab/merge/tools.js +217 -0
- package/src/collab/templates.js +10 -0
- package/src/comments/comment.js +29 -0
- package/src/comments/editors/answer.js +55 -0
- package/src/comments/editors/comment.js +318 -0
- package/src/comments/editors/index.js +4 -0
- package/src/comments/editors/notify.js +13 -0
- package/src/comments/editors/schema.js +65 -0
- package/src/comments/index.js +11 -0
- package/src/comments/interactions.js +465 -0
- package/src/comments/store.js +513 -0
- package/src/contacts/add_dialog.js +110 -0
- package/src/contacts/templates.js +28 -0
- package/src/copyright_dialog/index.js +179 -0
- package/src/copyright_dialog/templates.js +56 -0
- package/src/databases/bibliography.js +179 -0
- package/src/databases/images.js +320 -0
- package/src/databases/index.js +69 -0
- package/src/dialogs/citation.js +428 -0
- package/src/dialogs/code_block.js +242 -0
- package/src/dialogs/contributor.js +173 -0
- package/src/dialogs/figure.js +479 -0
- package/src/dialogs/index.js +10 -0
- package/src/dialogs/language.js +58 -0
- package/src/dialogs/link.js +358 -0
- package/src/dialogs/math.js +148 -0
- package/src/dialogs/ordered_list.js +84 -0
- package/src/dialogs/revision.js +43 -0
- package/src/dialogs/subsup.js +116 -0
- package/src/dialogs/table.js +258 -0
- package/src/dialogs/templates.js +426 -0
- package/src/document_template/exporter.js +97 -0
- package/src/document_template/index.js +483 -0
- package/src/documents/access_rights/index.js +693 -0
- package/src/documents/access_rights/templates.js +178 -0
- package/src/e2ee/encryptor.js +228 -0
- package/src/e2ee/key-manager.js +202 -0
- package/src/e2ee/passphrase-crypto.js +606 -0
- package/src/e2ee/passphrase-dialog.js +655 -0
- package/src/e2ee/passphrase-manager.js +502 -0
- package/src/e2ee/password-dialog.js +652 -0
- package/src/e2ee/snapshot-manager.js +305 -0
- package/src/exporter/native/copy.js +54 -0
- package/src/exporter/native/file.js +37 -0
- package/src/exporter/native/index.js +3 -0
- package/src/exporter/native/revision.js +86 -0
- package/src/exporter/native/zip.js +1 -0
- package/src/footnotes/editor.js +227 -0
- package/src/footnotes/index.js +16 -0
- package/src/footnotes/layout.js +190 -0
- package/src/footnotes/state_plugins/access_rights.js +39 -0
- package/src/footnotes/state_plugins/index.js +1 -0
- package/src/images/edit_dialog/edit_dialog/index.js +222 -0
- package/src/images/edit_dialog/edit_dialog/model.js +183 -0
- package/src/images/edit_dialog/edit_dialog/templates.js +41 -0
- package/src/images/edit_dialog/model.js +5 -0
- package/src/images/selection_dialog/index.js +176 -0
- package/src/index.js +1252 -0
- package/src/keymap.js +102 -0
- package/src/marginboxes/index.js +946 -0
- package/src/marginboxes/templates.js +573 -0
- package/src/menus/code_block/index.js +1 -0
- package/src/menus/code_block/model.js +52 -0
- package/src/menus/figure/index.js +2 -0
- package/src/menus/figure/model.js +91 -0
- package/src/menus/figure/utils.js +5 -0
- package/src/menus/headerbar/index.js +2 -0
- package/src/menus/headerbar/model.js +1077 -0
- package/src/menus/headerbar/view.js +675 -0
- package/src/menus/image/index.js +1 -0
- package/src/menus/image/model.js +32 -0
- package/src/menus/index.js +9 -0
- package/src/menus/navigator/index.js +1 -0
- package/src/menus/navigator/model.js +28 -0
- package/src/menus/ordered_list/index.js +1 -0
- package/src/menus/ordered_list/model.js +19 -0
- package/src/menus/selection/index.js +2 -0
- package/src/menus/selection/model.js +134 -0
- package/src/menus/selection/view.js +154 -0
- package/src/menus/table/index.js +1 -0
- package/src/menus/table/model.js +414 -0
- package/src/menus/toolbar/index.js +2 -0
- package/src/menus/toolbar/model.js +920 -0
- package/src/menus/toolbar/view.js +354 -0
- package/src/navigator/index.js +515 -0
- package/src/no_collab_save/index.js +209 -0
- package/src/plugins/citation_dialog/index.js +1 -0
- package/src/plugins/editor/index.js +1 -0
- package/src/state_plugins/access_rights.js +47 -0
- package/src/state_plugins/citation_render.js +88 -0
- package/src/state_plugins/clipboard.js +289 -0
- package/src/state_plugins/code_block.js +201 -0
- package/src/state_plugins/collab_carets.js +152 -0
- package/src/state_plugins/comments.js +259 -0
- package/src/state_plugins/contributor_input/add_button.js +134 -0
- package/src/state_plugins/contributor_input/dropup.js +318 -0
- package/src/state_plugins/contributor_input/helpers.js +24 -0
- package/src/state_plugins/contributor_input/index.js +2 -0
- package/src/state_plugins/contributor_input/node_view.js +86 -0
- package/src/state_plugins/contributor_input/plugin.js +318 -0
- package/src/state_plugins/document_template.js +315 -0
- package/src/state_plugins/figure.js +108 -0
- package/src/state_plugins/footnote_markers.js +238 -0
- package/src/state_plugins/headerbar.js +12 -0
- package/src/state_plugins/index.js +73 -0
- package/src/state_plugins/inline_math.js +918 -0
- package/src/state_plugins/inline_reference/dropup.js +208 -0
- package/src/state_plugins/inline_reference/index.js +5 -0
- package/src/state_plugins/inline_reference/plugin.js +1429 -0
- package/src/state_plugins/jump_hidden_nodes.js +58 -0
- package/src/state_plugins/links.js +830 -0
- package/src/state_plugins/marginboxes.js +14 -0
- package/src/state_plugins/ordered_list_menu.js +84 -0
- package/src/state_plugins/placeholders.js +123 -0
- package/src/state_plugins/search.js +251 -0
- package/src/state_plugins/selection_menu.js +12 -0
- package/src/state_plugins/settings.js +223 -0
- package/src/state_plugins/table.js +127 -0
- package/src/state_plugins/tag_input/helpers.js +69 -0
- package/src/state_plugins/tag_input/index.js +2 -0
- package/src/state_plugins/tag_input/node_view.js +85 -0
- package/src/state_plugins/tag_input/plugin.js +278 -0
- package/src/state_plugins/tag_input/tag_editor.js +202 -0
- package/src/state_plugins/tag_input/tag_editor_plugins.js +74 -0
- package/src/state_plugins/toc_render.js +160 -0
- package/src/state_plugins/toolbar.js +12 -0
- package/src/state_plugins/track/find_selected_changes.js +107 -0
- package/src/state_plugins/track/helpers.js +108 -0
- package/src/state_plugins/track/index.js +6 -0
- package/src/state_plugins/track/plugin.js +140 -0
- package/src/tools/index.js +3 -0
- package/src/tools/key_bindings/index.js +21 -0
- package/src/tools/key_bindings/templates.js +68 -0
- package/src/tools/search_replace/index.js +421 -0
- package/src/tools/search_replace/templates.js +19 -0
- package/src/tools/word_count/index.js +59 -0
- package/src/tools/word_count/templates.js +34 -0
- package/src/track/accept.js +102 -0
- package/src/track/accept_all.js +103 -0
- package/src/track/accept_all_no_insertions.js +102 -0
- package/src/track/amend_transaction.js +562 -0
- package/src/track/delete.js +92 -0
- package/src/track/index.js +8 -0
- package/src/track/mod.js +116 -0
- package/src/track/reject.js +116 -0
- package/src/track/reject_all.js +121 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PassphraseManager - Manages the personal passphrase system for E2EE.
|
|
3
|
+
*
|
|
4
|
+
* This module ties together PassphraseCrypto with the server API to provide:
|
|
5
|
+
* - Setup flow: generate keys, derive KWK, encrypt, send to server
|
|
6
|
+
* - Unlock flow: fetch from server, derive KWK, decrypt, store in sessionStorage
|
|
7
|
+
* - Recovery flow: use recovery key to decrypt backup, re-encrypt with new passphrase
|
|
8
|
+
* - Key checking: determine if user has encryption keys set up
|
|
9
|
+
* - DEK retrieval: get the document encryption key for a document
|
|
10
|
+
* - DEK sharing: encrypt DEK with recipient's public key
|
|
11
|
+
*/
|
|
12
|
+
import { getJson, post, postJson } from "fwtoolkit";
|
|
13
|
+
import { E2EEKeyManager } from "./key-manager";
|
|
14
|
+
import { PassphraseCrypto } from "./passphrase-crypto";
|
|
15
|
+
export class PassphraseManager {
|
|
16
|
+
/**
|
|
17
|
+
* Check if the user has set up encryption keys on the server.
|
|
18
|
+
*/
|
|
19
|
+
static async hasEncryptionKeys() {
|
|
20
|
+
try {
|
|
21
|
+
const data = await getJson("/api/user/encryption_key/");
|
|
22
|
+
return data.has_key === true;
|
|
23
|
+
}
|
|
24
|
+
catch (_e) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Check if the master key and private key are in sessionStorage.
|
|
30
|
+
*/
|
|
31
|
+
static hasKeysInSession() {
|
|
32
|
+
return PassphraseCrypto.hasKeysInSession();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get keys from sessionStorage.
|
|
36
|
+
* Returns {masterKey, privateKey} or {masterKey: null, privateKey: null}
|
|
37
|
+
*/
|
|
38
|
+
static getKeysFromSession() {
|
|
39
|
+
return PassphraseCrypto.getKeysFromSession();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Clear keys from sessionStorage (e.g., on sign-out).
|
|
43
|
+
*/
|
|
44
|
+
static clearKeysFromSession() {
|
|
45
|
+
PassphraseCrypto.clearKeysFromSession();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Set up encryption keys for the first time.
|
|
49
|
+
*
|
|
50
|
+
* @param {string} passphrase - The user's chosen passphrase
|
|
51
|
+
* @returns {Promise<Object>} {recoveryKey: string} - The recovery key to display
|
|
52
|
+
*/
|
|
53
|
+
static async setupEncryption(passphrase) {
|
|
54
|
+
// 1. Generate keys
|
|
55
|
+
const masterKey = await PassphraseCrypto.generateMasterKey();
|
|
56
|
+
const keyPair = await PassphraseCrypto.generateKeyPair();
|
|
57
|
+
const recoveryKey = PassphraseCrypto.generateRecoveryKey();
|
|
58
|
+
const salt = PassphraseCrypto.generateSalt();
|
|
59
|
+
// 2. Derive KWK from passphrase
|
|
60
|
+
const kwk = await PassphraseCrypto.deriveKWK(passphrase, salt);
|
|
61
|
+
// 3. Encrypt master key and private key with KWK
|
|
62
|
+
const encryptedMasterKey = await PassphraseCrypto.encryptKey(masterKey, kwk);
|
|
63
|
+
const encryptedPrivateKey = await PassphraseCrypto.encryptPrivateKey(keyPair.privateKey, kwk);
|
|
64
|
+
// 4. Encrypt backup of master key with recovery key
|
|
65
|
+
const recoveryKeyRaw = PassphraseCrypto._hexToBytes(recoveryKey);
|
|
66
|
+
const recoveryKeyCryptoKey = await crypto.subtle.importKey("raw", recoveryKeyRaw, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
67
|
+
const encryptedMasterKeyBackup = await PassphraseCrypto.encryptKey(masterKey, recoveryKeyCryptoKey);
|
|
68
|
+
// 5. Export public key as JWK
|
|
69
|
+
const publicKeyJwk = await PassphraseCrypto.exportPublicKey(keyPair.publicKey);
|
|
70
|
+
// 6. Send to server
|
|
71
|
+
const saveData = {
|
|
72
|
+
data: JSON.stringify({
|
|
73
|
+
public_key: publicKeyJwk,
|
|
74
|
+
encrypted_master_key: encryptedMasterKey,
|
|
75
|
+
encrypted_private_key: encryptedPrivateKey,
|
|
76
|
+
user_salt: PassphraseCrypto._bytesToBase64(salt),
|
|
77
|
+
user_iterations: 600000,
|
|
78
|
+
encrypted_master_key_backup: encryptedMasterKeyBackup
|
|
79
|
+
})
|
|
80
|
+
};
|
|
81
|
+
const { status } = await postJson("/api/user/encryption_key/save/", saveData);
|
|
82
|
+
if (status >= 400) {
|
|
83
|
+
throw new Error("Failed to save encryption keys");
|
|
84
|
+
}
|
|
85
|
+
// 7. Store in sessionStorage
|
|
86
|
+
await PassphraseCrypto.storeKeysInSession(masterKey, keyPair.privateKey);
|
|
87
|
+
return { recoveryKey };
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Unlock encryption keys using the passphrase.
|
|
91
|
+
*
|
|
92
|
+
* @param {string} passphrase - The user's passphrase
|
|
93
|
+
* @returns {Promise<boolean>} true if successful
|
|
94
|
+
*/
|
|
95
|
+
static async unlockWithPassphrase(passphrase) {
|
|
96
|
+
// 1. Fetch encrypted keys from server
|
|
97
|
+
const data = await getJson("/api/user/encryption_key/");
|
|
98
|
+
if (!data.has_key) {
|
|
99
|
+
throw new Error("No encryption keys found");
|
|
100
|
+
}
|
|
101
|
+
// 2. Derive KWK
|
|
102
|
+
const salt = PassphraseCrypto._base64ToBytes(data.user_salt);
|
|
103
|
+
const kwk = await PassphraseCrypto.deriveKWK(passphrase, salt, data.user_iterations);
|
|
104
|
+
// 3. Decrypt master key and private key
|
|
105
|
+
const masterKey = await PassphraseCrypto.decryptKey(data.encrypted_master_key, kwk);
|
|
106
|
+
const privateKey = await PassphraseCrypto.decryptPrivateKey(data.encrypted_private_key, kwk);
|
|
107
|
+
// 4. Store in sessionStorage
|
|
108
|
+
await PassphraseCrypto.storeKeysInSession(masterKey, privateKey);
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Change the passphrase without rotating keys.
|
|
113
|
+
*
|
|
114
|
+
* @param {string} oldPassphrase - Current passphrase
|
|
115
|
+
* @param {string} newPassphrase - New passphrase
|
|
116
|
+
* @returns {Promise<boolean>} true if successful
|
|
117
|
+
*/
|
|
118
|
+
static async changePassphrase(oldPassphrase, newPassphrase) {
|
|
119
|
+
// 1. Fetch encrypted keys from server
|
|
120
|
+
const data = await getJson("/api/user/encryption_key/");
|
|
121
|
+
if (!data.has_key) {
|
|
122
|
+
throw new Error("No encryption keys found");
|
|
123
|
+
}
|
|
124
|
+
// 2. Derive old KWK and decrypt keys
|
|
125
|
+
const oldSalt = PassphraseCrypto._base64ToBytes(data.user_salt);
|
|
126
|
+
const oldKwk = await PassphraseCrypto.deriveKWK(oldPassphrase, oldSalt, data.user_iterations);
|
|
127
|
+
const masterKey = await PassphraseCrypto.decryptKey(data.encrypted_master_key, oldKwk);
|
|
128
|
+
const privateKey = await PassphraseCrypto.decryptPrivateKey(data.encrypted_private_key, oldKwk);
|
|
129
|
+
// 3. Generate new salt and derive new KWK
|
|
130
|
+
const newSalt = PassphraseCrypto.generateSalt();
|
|
131
|
+
const newKwk = await PassphraseCrypto.deriveKWK(newPassphrase, newSalt);
|
|
132
|
+
// 4. Re-encrypt master key and private key with new KWK
|
|
133
|
+
const encryptedMasterKey = await PassphraseCrypto.encryptKey(masterKey, newKwk);
|
|
134
|
+
const encryptedPrivateKey = await PassphraseCrypto.encryptPrivateKey(privateKey, newKwk);
|
|
135
|
+
// 5. Re-encrypt master key backup with existing recovery key
|
|
136
|
+
// (We keep the same recovery key so the user doesn't need to update
|
|
137
|
+
// their stored backup. The backup is encrypted with the recovery key,
|
|
138
|
+
// not the passphrase, so it remains valid.)
|
|
139
|
+
const encryptedMasterKeyBackup = data.encrypted_master_key_backup;
|
|
140
|
+
// 6. Send updated keys to server
|
|
141
|
+
const saveData = {
|
|
142
|
+
data: JSON.stringify({
|
|
143
|
+
public_key: data.public_key,
|
|
144
|
+
encrypted_master_key: encryptedMasterKey,
|
|
145
|
+
encrypted_private_key: encryptedPrivateKey,
|
|
146
|
+
user_salt: PassphraseCrypto._bytesToBase64(newSalt),
|
|
147
|
+
user_iterations: 600000,
|
|
148
|
+
encrypted_master_key_backup: encryptedMasterKeyBackup
|
|
149
|
+
})
|
|
150
|
+
};
|
|
151
|
+
const { status } = await postJson("/api/user/encryption_key/save/", saveData);
|
|
152
|
+
if (status >= 400) {
|
|
153
|
+
throw new Error("Failed to save updated encryption keys");
|
|
154
|
+
}
|
|
155
|
+
// 7. Update sessionStorage
|
|
156
|
+
await PassphraseCrypto.storeKeysInSession(masterKey, privateKey);
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Recover encryption keys using the recovery key.
|
|
161
|
+
*
|
|
162
|
+
* @param {string} recoveryKey - The recovery key (hex string)
|
|
163
|
+
* @param {string} newPassphrase - The new passphrase to set
|
|
164
|
+
* @returns {Promise<Object>} {newRecoveryKey: string}
|
|
165
|
+
*/
|
|
166
|
+
static async recoverWithRecoveryKey(recoveryKey, newPassphrase) {
|
|
167
|
+
// 1. Fetch encrypted keys from server
|
|
168
|
+
const data = await getJson("/api/user/encryption_key/");
|
|
169
|
+
if (!data.has_key) {
|
|
170
|
+
throw new Error("No encryption keys found");
|
|
171
|
+
}
|
|
172
|
+
// 2. Decrypt master key backup with recovery key
|
|
173
|
+
const recoveryKeyRaw = PassphraseCrypto._hexToBytes(recoveryKey);
|
|
174
|
+
const recoveryKeyCryptoKey = await crypto.subtle.importKey("raw", recoveryKeyRaw, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
175
|
+
const masterKey = await PassphraseCrypto.decryptKey(data.encrypted_master_key_backup, recoveryKeyCryptoKey);
|
|
176
|
+
// 3. Generate new key pair
|
|
177
|
+
const newKeyPair = await PassphraseCrypto.generateKeyPair();
|
|
178
|
+
const newRecoveryKey = PassphraseCrypto.generateRecoveryKey();
|
|
179
|
+
const newSalt = PassphraseCrypto.generateSalt();
|
|
180
|
+
// 4. Derive new KWK from new passphrase
|
|
181
|
+
const newKwk = await PassphraseCrypto.deriveKWK(newPassphrase, newSalt);
|
|
182
|
+
// 5. Re-encrypt master key and new private key
|
|
183
|
+
const encryptedMasterKey = await PassphraseCrypto.encryptKey(masterKey, newKwk);
|
|
184
|
+
const encryptedPrivateKey = await PassphraseCrypto.encryptPrivateKey(newKeyPair.privateKey, newKwk);
|
|
185
|
+
// 6. Create new backup
|
|
186
|
+
const newRecoveryKeyRaw = PassphraseCrypto._hexToBytes(newRecoveryKey);
|
|
187
|
+
const newRecoveryKeyCryptoKey = await crypto.subtle.importKey("raw", newRecoveryKeyRaw, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
188
|
+
const encryptedMasterKeyBackup = await PassphraseCrypto.encryptKey(masterKey, newRecoveryKeyCryptoKey);
|
|
189
|
+
// 7. Export new public key
|
|
190
|
+
const publicKeyJwk = await PassphraseCrypto.exportPublicKey(newKeyPair.publicKey);
|
|
191
|
+
// 8. Send updated keys to server
|
|
192
|
+
const saveData = {
|
|
193
|
+
data: JSON.stringify({
|
|
194
|
+
public_key: publicKeyJwk,
|
|
195
|
+
encrypted_master_key: encryptedMasterKey,
|
|
196
|
+
encrypted_private_key: encryptedPrivateKey,
|
|
197
|
+
user_salt: PassphraseCrypto._bytesToBase64(newSalt),
|
|
198
|
+
user_iterations: 600000,
|
|
199
|
+
encrypted_master_key_backup: encryptedMasterKeyBackup
|
|
200
|
+
})
|
|
201
|
+
};
|
|
202
|
+
const { status } = await postJson("/api/user/encryption_key/save/", saveData);
|
|
203
|
+
if (status >= 400) {
|
|
204
|
+
throw new Error("Failed to save updated encryption keys");
|
|
205
|
+
}
|
|
206
|
+
// 9. Store in sessionStorage
|
|
207
|
+
await PassphraseCrypto.storeKeysInSession(masterKey, newKeyPair.privateKey);
|
|
208
|
+
return { newRecoveryKey };
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get the document password for a document.
|
|
212
|
+
*
|
|
213
|
+
* If encrypted with the user's master key, decrypts it directly.
|
|
214
|
+
* If encrypted with the user's public key, decrypts with private key and
|
|
215
|
+
* upgrades to master-key encryption.
|
|
216
|
+
*
|
|
217
|
+
* @param {number} documentId - The document ID
|
|
218
|
+
* @returns {Promise<string|null>} The document password, or null if not available
|
|
219
|
+
*/
|
|
220
|
+
static async getDocumentPassword(documentId) {
|
|
221
|
+
const { masterKey, privateKey } = await PassphraseCrypto.getKeysFromSession();
|
|
222
|
+
if (!masterKey || !privateKey) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
const { json } = await postJson("/api/document/encryption_key/get/", {
|
|
226
|
+
document_id: documentId
|
|
227
|
+
});
|
|
228
|
+
if (!json.has_key) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
let password;
|
|
232
|
+
if (json.encrypted_with_master_key) {
|
|
233
|
+
password = await PassphraseCrypto.decryptString(json.encrypted_key, masterKey);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
const parts = json.encrypted_key.split(":");
|
|
237
|
+
if (parts.length !== 2) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
password = await PassphraseCrypto.decryptStringWithPrivateKey(parts[1], parts[0], privateKey);
|
|
241
|
+
// Upgrade to master-key encryption for next time
|
|
242
|
+
const upgradedEncryptedPassword = await PassphraseCrypto.encryptString(password, masterKey);
|
|
243
|
+
await postJson("/api/document/encryption_key/update/", {
|
|
244
|
+
id: json.id,
|
|
245
|
+
encrypted_key: upgradedEncryptedPassword,
|
|
246
|
+
encrypted_with_master_key: true
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
return password;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Create or store a document password for a document.
|
|
253
|
+
*
|
|
254
|
+
* Used when:
|
|
255
|
+
* - Creating a new encrypted document (owner's password encrypted with MK)
|
|
256
|
+
* - Sharing with another passphrase user (password encrypted with their public key)
|
|
257
|
+
*
|
|
258
|
+
* @param {number} documentId - The document ID
|
|
259
|
+
* @param {string} password - The document password
|
|
260
|
+
* @param {number} holderId - The user ID to store the password for (default: current user)
|
|
261
|
+
* @param {string} holderType - "user" or "userinvite"
|
|
262
|
+
* @param {boolean} encryptedWithMasterKey - Whether to encrypt with MK or public key
|
|
263
|
+
* @returns {Promise<Object>} Server response
|
|
264
|
+
*/
|
|
265
|
+
static async saveDocumentPassword(documentId, password, holderId = null, _holderType = "user", encryptedWithMasterKey = true) {
|
|
266
|
+
let encryptedKey;
|
|
267
|
+
if (encryptedWithMasterKey) {
|
|
268
|
+
const { masterKey } = await PassphraseCrypto.getKeysFromSession();
|
|
269
|
+
if (!masterKey) {
|
|
270
|
+
throw new Error("Master key not available in session");
|
|
271
|
+
}
|
|
272
|
+
encryptedKey = await PassphraseCrypto.encryptString(password, masterKey);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
const pkJson = await getJson(`/api/user/encryption_public_key/${holderId}/`);
|
|
276
|
+
if (!pkJson.has_key) {
|
|
277
|
+
throw new Error("Recipient has not set up encryption");
|
|
278
|
+
}
|
|
279
|
+
const recipientPublicKey = await PassphraseCrypto.importPublicKey(pkJson.public_key);
|
|
280
|
+
const encryptedData = await PassphraseCrypto.encryptStringWithPublicKey(password, recipientPublicKey);
|
|
281
|
+
encryptedKey = `${encryptedData.ephemeralPublicKeyJwk}:${encryptedData.encryptedData}`;
|
|
282
|
+
}
|
|
283
|
+
const saveData = {
|
|
284
|
+
document_id: documentId,
|
|
285
|
+
encrypted_key: encryptedKey,
|
|
286
|
+
encrypted_with_master_key: encryptedWithMasterKey
|
|
287
|
+
};
|
|
288
|
+
if (holderId) {
|
|
289
|
+
saveData.holder_id = holderId;
|
|
290
|
+
}
|
|
291
|
+
const { json, status } = await postJson("/api/document/encryption_key/save/", saveData);
|
|
292
|
+
if (status >= 400) {
|
|
293
|
+
throw new Error("Failed to save document password");
|
|
294
|
+
}
|
|
295
|
+
return json;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Generate a new random document password that is itself a valid raw DEK.
|
|
299
|
+
* Returns a 44-character base64-encoded 32-byte AES key.
|
|
300
|
+
*/
|
|
301
|
+
static generateDocumentPassword() {
|
|
302
|
+
return PassphraseCrypto.generateDocumentPassword();
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Resolve a document password to an AES-GCM key.
|
|
306
|
+
* If the password is a raw DEK (43/44 char base64), use it directly.
|
|
307
|
+
* Otherwise, derive the key via PBKDF2.
|
|
308
|
+
*/
|
|
309
|
+
static resolvePasswordToKey(password, salt, iterations) {
|
|
310
|
+
return E2EEKeyManager.resolvePasswordToKey(password, salt, iterations);
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Check if a user has set up encryption keys (for sharing).
|
|
314
|
+
*/
|
|
315
|
+
static async userHasEncryptionKeys(userId) {
|
|
316
|
+
try {
|
|
317
|
+
const data = await getJson(`/api/user/encryption_public_key/${userId}/`);
|
|
318
|
+
return data.has_key === true;
|
|
319
|
+
}
|
|
320
|
+
catch (_e) {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Check if user has dismissed the passphrase setup offer.
|
|
326
|
+
*/
|
|
327
|
+
static async hasUserDismissedPassphraseOffer() {
|
|
328
|
+
try {
|
|
329
|
+
const data = await getJson("/api/user/preferences/get/");
|
|
330
|
+
return data.preferences?.has_dismissed_passphrase_offer === true;
|
|
331
|
+
}
|
|
332
|
+
catch (_e) {
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Mark that user has dismissed the passphrase setup offer.
|
|
338
|
+
*/
|
|
339
|
+
static async markPassphraseDismissed() {
|
|
340
|
+
try {
|
|
341
|
+
await post("/api/user/preferences/update/", {
|
|
342
|
+
has_dismissed_passphrase_offer: true
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
catch (_e) {
|
|
346
|
+
// Silently fail - preference saving is best-effort
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
//# sourceMappingURL=passphrase-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passphrase-manager.js","sourceRoot":"","sources":["../../src/e2ee/passphrase-manager.js"],"names":[],"mappings":"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"}
|