DEV: Use NewPostManager to handle new posts.

DEV: Use NewPostManager to handle new posts.

diff --git a/assets/javascripts/discourse/initializers/hook-composer.js.es6 b/assets/javascripts/discourse/initializers/hook-composer.js.es6
index 65dde96..14a3e30 100644
--- a/assets/javascripts/discourse/initializers/hook-composer.js.es6
+++ b/assets/javascripts/discourse/initializers/hook-composer.js.es6
@@ -32,48 +32,10 @@ export default {
       return;
     }
 
-    // Decode composer on reply reload. This usually occurs when a post is
-    // edited or a draft is loaded.
-    const appEvents = container.lookup("app-events:main");
-    appEvents.on("composer:reply-reloaded", model => {
-      const draftKey = model.draftKey;
-
-      let encrypted, decTitle, decReply;
-      if (draftKey === Composer.NEW_PRIVATE_MESSAGE_KEY) {
-        encrypted = true;
-      } else if (draftKey.indexOf("topic_") === 0) {
-        const topicId = draftKey.substr("topic_".length);
-        encrypted = !!hasTopicKey(topicId);
-      }
-
-      if (encrypted) {
-        if (model.action === "edit" && model.originalText) {
-          const topicId = model.get("topic.id");
-          decTitle = getTopicTitle(topicId);
-          decReply = getTopicKey(topicId).then(key =>
-            decrypt(key, model.reply)
-          );
-        } else {
-          const pk = getPrivateKey();
-          decTitle =
-            model.title && pk.then(key => rsaDecrypt(key, model.title));
-          decReply =
-            model.reply && pk.then(key => rsaDecrypt(key, model.reply));
-        }
-      }
-
-      if (decTitle) {
-        decTitle.then(title =>
-          model.setProperties({ title, isEncrypted: true })
-        );
-      }
-
-      if (decReply) {
-        decReply.then(reply =>
-          model.setProperties({ reply, isEncrypted: true })
-        );
-      }
-    });
+    // Register custom fields to be saved for new post.
+    Composer.serializeOnCreate("encryptedTitle", "encryptedTitle");
+    Composer.serializeOnCreate("encryptedRaw", "encryptedRaw");
+    Composer.serializeOnCreate("encryptedKeys", "encryptedKeys");
 
     // Encrypt the Composer contents on-the-fly right before it is sent over
     // to the server.
@@ -136,11 +98,10 @@ export default {
         }
 
         // Generating a new topic key.
-        const p0 = generateKey();
+        const topicKey = generateKey();
 
-        // Encrypting user keys.
         const usernames = this.recipients;
-        const p1 = p0.then(key =>
+        const encryptedKeys = topicKey.then(key =>
           ajax("/encrypt/user", {
             type: "GET",
             data: { usernames }
@@ -171,38 +132,32 @@ export default {
             })
         );
 
-        // Encrypting title and reply.
-        const p2 = p0.then(key => encrypt(key, title));
-        const p3 = p0.then(key => encrypt(key, reply));
+        const encryptedTitle = topicKey.then(key => encrypt(key, title));
+        const encryptedRaw = topicKey.then(key => encrypt(key, reply));
 
         // Send user keys, title and reply encryption to the server.
-        return Ember.RSVP.Promise.all([p1, p2, p3])
-          .then(([keys, encTitle, encReply]) => {
-            const userKeys = {};
-            for (let i = 0; i < keys.length; ++i) {
-              userKeys[usernames[i]] = keys[i];
-            }
-
-            this.set("title", I18n.t("encrypt.encrypted_topic_title"));
-            this.set("reply", encReply);
-
-            const result = _super.call(this, ...arguments);
-            return Ember.RSVP.Promise.all([p0, encTitle, userKeys, result]);
-          })
-          .then(([key, encTitle, userKeys, result]) => {
-            const topicId = result.responseJson.post.topic_id;
-
-            putTopicKey(topicId, key);
-            putTopicTitle(topicId, encTitle);
+        return Ember.RSVP.Promise.all([
+          encryptedTitle,
+          encryptedRaw,
+          encryptedKeys
+        ]).then(([encTitle, encReply, encKeys]) => {
+          const userKeys = {};
+          for (let i = 0; i < encKeys.length; ++i) {
+            userKeys[usernames[i]] = encKeys[i];
+          }
 
-            ajax("/encrypt/topic", {
-              type: "PUT",
-              data: { topic_id: topicId, title: encTitle, keys: userKeys }
-            });
+          this.setProperties({
+            title: I18n.t("encrypt.encrypted_topic_title"),
+            raw: I18n.t("encrypt.encrypted_topic_raw"),
+            encryptedTitle: encTitle,
+            encryptedRaw: encReply,
+            encryptedKeys: JSON.stringify(userKeys)
+          });
 
-            return result;
-          })
-          .finally(() => this.setProperties({ title, reply }));
+          return _super
+            .call(this, ...arguments)
+            .finally(() => this.setProperties({ title: title, raw: reply }));
+        });
       },
 
       @on("init")
@@ -276,5 +231,48 @@ export default {
         return recipients;
       }
     });
+
+    // Decode composer on reply reload. This usually occurs when a post is
+    // edited or a draft is loaded.
+    const appEvents = container.lookup("app-events:main");
+    appEvents.on("composer:reply-reloaded", model => {
+      const draftKey = model.draftKey;
+
+      let encrypted, decTitle, decReply;
+      if (draftKey === Composer.NEW_PRIVATE_MESSAGE_KEY) {
+        encrypted = true;
+      } else if (draftKey.indexOf("topic_") === 0) {
+        const topicId = draftKey.substr("topic_".length);
+        encrypted = !!hasTopicKey(topicId);
+      }
+
+      if (encrypted) {
+        if (model.action === "edit" && model.originalText) {
+          const topicId = model.get("topic.id");
+          decTitle = getTopicTitle(topicId);
+          decReply = getTopicKey(topicId).then(key =>
+            decrypt(key, model.reply)
+          );
+        } else {
+          const pk = getPrivateKey();
+          decTitle =
+            model.title && pk.then(key => rsaDecrypt(key, model.title));
+          decReply =
+            model.reply && pk.then(key => rsaDecrypt(key, model.reply));
+        }
+      }
+
+      if (decTitle) {
+        decTitle.then(title =>
+          model.setProperties({ title, isEncrypted: true })
+        );
+      }
+
+      if (decReply) {
+        decReply.then(reply =>
+          model.setProperties({ reply, isEncrypted: true })
+        );
+      }
+    });
   }
 };
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 612bd2f..85584f2 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -6,6 +6,7 @@ en:
       decryption_failed: "This message could not be decrypted."
 
       encrypted_topic_title: "A secret message"
+      encrypted_topic_raw: "This is a secret message that has been end-to-end encrypted."
       encrypted_icon_title: "This message is end-to-end encrypted."
 
       encrypted_uploads: "Uploads cannot be encrypted at this time."
diff --git a/plugin.rb b/plugin.rb
index 5fe20d5..5fbd3b8 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -166,6 +166,37 @@ after_initialize do
   add_preloaded_topic_list_custom_field('encrypted_title')
   CategoryList.preloaded_topic_custom_fields << 'encrypted_title'
 
+  # Handle new post creation.
+  add_permitted_post_create_param(:encryptedTitle)
+  add_permitted_post_create_param(:encryptedRaw)
+  add_permitted_post_create_param(:encryptedKeys)
+
+  NewPostManager.add_handler do |manager|
+    if manager.args[:archetype] != Archetype.private_message ||
+       !manager.args[:encryptedRaw]
+      next
+    end
+
+    manager.args[:raw] = manager.args[:encryptedRaw]
+    manager.args[:skip_unique_check] = true
+    if title = manager.args[:encryptedTitle]
+      manager.args[:topic_opts] ||= {}
+      manager.args[:topic_opts][:custom_fields] ||= {}
+      manager.args[:topic_opts][:custom_fields][:encrypted_title] = manager.args[:encryptedTitle]
+    end
+
+    result = manager.perform_create_post
+    if result.success?
+      keys = JSON.parse(manager.args[:encryptedKeys])
+      topic_id = result.post.topic_id

[... diff too long, it was truncated ...]

GitHub sha: 02c72aac

1 Like