FIX: Replace cooked content of encrypted post.

FIX: Replace cooked content of encrypted post.

diff --git a/assets/javascripts/discourse/controllers/activate-encrypt.js.es6 b/assets/javascripts/discourse/controllers/activate-encrypt.js.es6
index 5671d6d..edbaa61 100644
--- a/assets/javascripts/discourse/controllers/activate-encrypt.js.es6
+++ b/assets/javascripts/discourse/controllers/activate-encrypt.js.es6
@@ -55,7 +55,11 @@ export default Ember.Controller.extend(ModalFunctionality, {
         // 3. Reset component status.
         .then(() => {
           this.appEvents.trigger("encrypt:status-changed");
-          this.models.forEach(model => model.scheduleRerender());
+          this.models.forEach(model => {
+            model.state.decrypting = false;
+            model.state.decrypted = false;
+            model.scheduleRerender();
+          });
           this.set("models", null);
           this.send("closeModal");
         })
diff --git a/assets/javascripts/discourse/initializers/hook-decrypt-post.js.es6 b/assets/javascripts/discourse/initializers/hook-decrypt-post.js.es6
index 1f35a35..084a538 100644
--- a/assets/javascripts/discourse/initializers/hook-decrypt-post.js.es6
+++ b/assets/javascripts/discourse/initializers/hook-decrypt-post.js.es6
@@ -25,6 +25,7 @@ export default {
     }
 
     withPluginApi("0.8.25", api => {
+      api.includePostAttributes("encrypted_raw");
       api.reopenWidget("post-contents", {
         html(attrs, state) {
           const topicId = attrs.topicId;
@@ -32,15 +33,11 @@ export default {
             return this._super(...arguments);
           }
 
-          // Check if post has been updated (if last decrypted ciphertext
-          // is different than the current ciphertext).
-          const ciphertext = $(attrs.cooked).text();
-          if (state.encrypted && state.encrypted !== ciphertext) {
-            state.decrypting = false;
-            state.decrypted = undefined;
-          }
-
-          if (hasTopicKey(topicId) && !state.decrypted) {
+          const ciphertext = attrs.encrypted_raw;
+          if (
+            (!state.decrypted || state.encrypted !== ciphertext) &&
+            hasTopicKey(topicId)
+          ) {
             state.encrypted = ciphertext;
             state.decrypting = true;
 
@@ -50,12 +47,12 @@ export default {
                   .then(key => decrypt(key, ciphertext))
                   .then(plaintext => cookAsync(plaintext))
                   .then(cooked => {
+                    state.decrypting = false;
                     state.decrypted = cooked.string;
                     this.scheduleRerender();
                   })
                   // Absence of topic key underlies a bigger error.
                   .catch(() => {
-                    state.encrypted = undefined;
                     state.decrypting = false;
                     state.decrypted = true;
                     this.scheduleRerender();
@@ -65,19 +62,16 @@ export default {
               .catch(() => showModal("activate-encrypt", { model: this }));
           }
 
-          // Checking if topic is already being decrypted
-          if (state.decrypting) {
-            if (state.decrypted) {
-              attrs.cooked = state.decrypted;
-              Ember.run.next(() => resolveAllShortUrls(ajax));
-            } else {
-              attrs.cooked =
-                "<div class='alert alert-info'>" +
-                renderSpinner("small") +
-                " " +
-                I18n.t("encrypt.decrypting") +
-                "</div>";
-            }
+          if (state.decrypted && state.decrypted !== true) {
+            attrs.cooked = state.decrypted;
+            Ember.run.next(() => resolveAllShortUrls(ajax));
+          } else if (state.decrypting) {
+            attrs.cooked =
+              "<div class='alert alert-info'>" +
+              renderSpinner("small") +
+              " " +
+              I18n.t("encrypt.decrypting") +
+              "</div>";
           } else {
             attrs.cooked =
               "<div class='alert alert-error'>" +
diff --git a/plugin.rb b/plugin.rb
index 8735769..beabaad 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -121,6 +121,15 @@ after_initialize do
   add_preloaded_topic_list_custom_field('encrypted_title')
   CategoryList.preloaded_topic_custom_fields << 'encrypted_title'
 
+  # Hide cooked content.
+  Plugin::Filter.register(:after_post_cook) do |post, cooked|
+    if post.is_encrypted? && post.raw.match(/\A[A-Za-z0-9+\\\/=]+\Z/)
+      next "<p>#{I18n.t('js.encrypt.encrypted_topic_raw')}</p>"
+    end
+
+    cooked
+  end
+
   # Handle new post creation.
   add_permitted_post_create_param(:encrypted_title)
   add_permitted_post_create_param(:encrypted_raw)
@@ -153,6 +162,16 @@ after_initialize do
     result
   end
 
+  module TopicExtensions
+    def is_encrypted?
+      !!(private_message? &&
+         custom_fields &&
+         custom_fields['encrypted_title'])
+    end
+  end
+
+  ::Topic.class_eval { prepend TopicExtensions }
+
   module PostExtensions
     # Hide version (staff) and public version (regular users) because post
     # revisions will not be decrypted.
@@ -165,7 +184,7 @@ after_initialize do
     end
 
     def is_encrypted?
-      !!(topic && topic.custom_fields && topic.custom_fields['encrypted_title'])
+      !!(topic && topic.is_encrypted?)
     end
   end
 
@@ -214,6 +233,14 @@ after_initialize do
   # +TopicViewSerializer+ and +BasicTopicSerializer+ should cover all topics
   # that are serialized over to the client.
 
+  add_to_serializer(:post, :encrypted_raw, false) do
+    object.raw
+  end
+
+  add_to_serializer(:post, :include_encrypted_raw?) do
+    object.is_encrypted?
+  end
+
   # +encrypted_title+
   #
   # Topic title encrypted with topic key.

GitHub sha: 1bb94f6d