about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/remote_interaction_controller.rb2
-rw-r--r--app/controllers/statuses_controller.rb4
-rw-r--r--app/lib/activitypub/activity/create.rb3
-rw-r--r--app/lib/bangtags.rb7
-rw-r--r--app/models/imported_status.rb13
-rw-r--r--app/models/normalized_status.rb1
-rw-r--r--app/models/sharekey.rb13
-rw-r--r--app/models/status.rb49
-rw-r--r--app/serializers/rest/status_serializer.rb10
-rw-r--r--app/services/post_status_service.rb2
-rw-r--r--db/migrate/20191211235208_create_normalized_statuses.rb2
-rw-r--r--db/migrate/20191212022020_create_sharekeys.rb19
-rw-r--r--db/migrate/20191212022653_create_imported_statuses.rb21
-rw-r--r--db/schema.rb21
-rw-r--r--spec/fabricators/imported_status_fabricator.rb4
-rw-r--r--spec/fabricators/sharekey_fabricator.rb4
-rw-r--r--spec/models/imported_status_spec.rb5
-rw-r--r--spec/models/sharekey_spec.rb5
18 files changed, 155 insertions, 30 deletions
diff --git a/app/controllers/remote_interaction_controller.rb b/app/controllers/remote_interaction_controller.rb
index aa8f73ac8..7ecf95400 100644
--- a/app/controllers/remote_interaction_controller.rb
+++ b/app/controllers/remote_interaction_controller.rb
@@ -49,7 +49,7 @@ class RemoteInteractionController < ApplicationController
     @status = Status.find(params[:id])
     @sharekey = params[:key]
 
-    if @status.sharekey.present? && @sharekey == @status.sharekey
+    if @status.sharekey.present? && @sharekey == @status.sharekey.key
       skip_authorization
     else
       authorize @status, :show?
diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb
index eeece1785..f8e81864c 100644
--- a/app/controllers/statuses_controller.rb
+++ b/app/controllers/statuses_controller.rb
@@ -185,7 +185,7 @@ class StatusesController < ApplicationController
     @type         = @stream_entry.activity_type.downcase
     @sharekey     = params[:key]
 
-    if @status.sharekey.present? && @sharekey == @status.sharekey
+    if @status.sharekey.present? && @sharekey == @status.sharekey.key
       skip_authorization
     elsif @account.block_anon && !user_signed_in?
       raise ActiveRecord::RecordNotFound
@@ -203,11 +203,9 @@ class StatusesController < ApplicationController
     case params[:rekey]
     when '1'
       @status.sharekey = SecureRandom.urlsafe_base64(32)
-      @status.save
       Rails.cache.delete("statuses/#{@status.id}")
     when '0'
       @status.sharekey = nil
-      @status.save
       Rails.cache.delete("statuses/#{@status.id}")
     end
   end
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index 4e7f922e9..1839a649e 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -92,7 +92,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
   end
 
   def find_imported_status
-    status   = Status.find_by(origin: @origin_hash)
+    status = Status.joins(:imported_status).select('statuses.*').find_by(origin: @origin_hash)
   end
 
   def obfuscate_origin(key)
@@ -138,7 +138,6 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
       if @options[:imported]
         @params.except!(:uri, :url)
         @params[:content_type] = 'text/html'
-        @params[:imported] = true
         @params[:origin] = @origin_hash unless @origin_hash.nil?
       end
 
diff --git a/app/lib/bangtags.rb b/app/lib/bangtags.rb
index 5d8389892..a1963aa6c 100644
--- a/app/lib/bangtags.rb
+++ b/app/lib/bangtags.rb
@@ -303,7 +303,6 @@ class Bangtags
                 roars.each do |roar|
                   if roar.sharekey.present?
                     roar.sharekey = nil
-                    roar.save
                     Rails.cache.delete("statuses/#{roar.id}")
                   end
                 end
@@ -315,15 +314,13 @@ class Bangtags
                 if cmd[2] == 'new' || earliest_roar.sharekey.blank?
                   sharekey = SecureRandom.urlsafe_base64(32)
                   earliest_roar.sharekey = sharekey
-                  earliest_roar.save
                   Rails.cache.delete("statuses/#{earliest_roar.id}")
                 else
-                  sharekey = earliest_roar.sharekey
+                  sharekey = earliest_roar.sharekey.key
                 end
                 roars.each do |roar|
-                  if roar.sharekey != sharekey
+                  if roar.sharekey.nil? || roar.sharekey.key != sharekey
                     roar.sharekey = sharekey
-                    roar.save
                     Rails.cache.delete("statuses/#{roar.id}")
                   end
                 end
diff --git a/app/models/imported_status.rb b/app/models/imported_status.rb
new file mode 100644
index 000000000..038301f3e
--- /dev/null
+++ b/app/models/imported_status.rb
@@ -0,0 +1,13 @@
+# == Schema Information
+#
+# Table name: imported_statuses
+#
+#  id        :bigint(8)        not null, primary key
+#  status_id :bigint(8)
+#  origin    :string
+#
+
+class ImportedStatus < ApplicationRecord
+  belongs_to :status, inverse_of: :imported_status
+  validates_uniqueness_of :status_id
+end
diff --git a/app/models/normalized_status.rb b/app/models/normalized_status.rb
index 10c2bf788..ad1ffaffc 100644
--- a/app/models/normalized_status.rb
+++ b/app/models/normalized_status.rb
@@ -9,4 +9,5 @@
 
 class NormalizedStatus < ApplicationRecord
   belongs_to :status, inverse_of: :normalized_status
+  validates_uniqueness_of :status_id
 end
diff --git a/app/models/sharekey.rb b/app/models/sharekey.rb
new file mode 100644
index 000000000..baa1c20a0
--- /dev/null
+++ b/app/models/sharekey.rb
@@ -0,0 +1,13 @@
+# == Schema Information
+#
+# Table name: sharekeys
+#
+#  id        :bigint(8)        not null, primary key
+#  status_id :bigint(8)
+#  key       :string
+#
+
+class Sharekey < ApplicationRecord
+  belongs_to :status, inverse_of: :sharekey
+  validates_uniqueness_of :status_id
+end
diff --git a/app/models/status.rb b/app/models/status.rb
index 27184591b..e46e36403 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -24,13 +24,10 @@
 #  local_only             :boolean
 #  poll_id                :bigint(8)
 #  curated                :boolean          default(FALSE), not null
-#  sharekey               :string
 #  network                :boolean          default(FALSE), not null
 #  content_type           :string
 #  footer                 :text
 #  edited                 :boolean
-#  imported               :boolean
-#  origin                 :string
 #  boostable              :boolean
 #  reject_replies         :boolean
 #
@@ -86,6 +83,8 @@ class Status < ApplicationRecord
   has_one :poll, inverse_of: :status, dependent: :destroy
   has_one :destructing_status, inverse_of: :status, dependent: :destroy
   has_one :normalized_status, inverse_of: :status, dependent: :destroy
+  has_one :imported_status, inverse_of: :status, dependent: :destroy
+  has_one :sharekey, inverse_of: :status, dependent: :destroy
 
   validates :uri, uniqueness: true, presence: true, unless: :local?
   validates :text, presence: true, unless: -> { with_media? || reblog? }
@@ -318,12 +317,22 @@ class Status < ApplicationRecord
     update_status_stat!(key => [public_send(key) - 1, 0].max)
   end
 
-  def session=(value)
-    @session = value
+  def sharekey=(value)
+    if value.nil? && !(new_record? || self.sharekey.nil?)
+      self.sharekey.destroy
+    else
+      @_sharekey = value
+      update_sharekey unless new_record? || changed?
+    end
   end
 
-  def session
-    @session || nil
+  def origin=(value)
+    if value.nil? && !(new_record? || self.imported_status.nil?)
+      self.imported_status.destroy
+    else
+      @_origin = value
+      update_origin unless new_record? || changed?
+    end
   end
 
   after_create_commit  :increment_counter_caches
@@ -344,8 +353,11 @@ class Status < ApplicationRecord
   before_validation :infer_reject_replies
 
   after_create :set_poll_id
-  after_create :update_normalized_text
-  after_create :process_bangtags, if: :local?
+
+  after_save :update_sharekey, if: :local?
+  after_save :update_origin, if: :local?
+  after_save :update_normalized_text
+  after_save :process_bangtags, if: :local?
 
   class << self
     include SearchHelper
@@ -629,9 +641,28 @@ class Status < ApplicationRecord
   end
 
   def process_bangtags
+    return unless text_changed? || saved_change_to_text?
     Bangtags.new(self).process
   end
 
+  def update_sharekey
+    return if @_sharekey.nil?
+    if self.sharekey.nil?
+      self.create_sharekey(key: @_sharekey)
+    else
+      self.sharekey.update_attributes(key: @_sharekey)
+    end
+  end
+
+  def update_origin
+    return if @_origin.nil?
+    if self.imported_status.nil?
+      self.create_imported_status(origin: @_origin)
+    else
+      self.imported_status.update_attributes(origin: @_origin)
+    end
+  end
+
   def update_normalized_text
     return if destroyed? || text.blank? || !(text_changed? || saved_change_to_text?)
     normalized_text = normalize_status(self)
diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb
index 75a1dc591..8b0bce61e 100644
--- a/app/serializers/rest/status_serializer.rb
+++ b/app/serializers/rest/status_serializer.rb
@@ -14,7 +14,7 @@ class REST::StatusSerializer < ActiveModel::Serializer
   attribute :bookmarked, if: :current_user?
   attribute :pinned, if: :pinnable?
   attribute :local_only if :local?
-  attribute :sharekey, if: :owner?
+  attribute :sharekey, if: :has_sharekey?
   attribute :delete_after, if: :current_user?
 
   attribute :content, unless: :source_requested?
@@ -53,12 +53,16 @@ class REST::StatusSerializer < ActiveModel::Serializer
     current_user? && current_user.account_id == object.account_id
   end
 
+  def has_sharekey?
+    owner? && object.sharekey.present?
+  end
+
   def show_application?
     object.account.user_shows_application? || owner?
   end
 
-  def spoiler_text
-    redis.hget("custom_cw:#{current_user&.account_id}", object.id) || redis.hget("custom_cw:#{current_user&.account_id}", "c#{object.conversation_id}") || object.spoiler_text
+  def sharekey
+    object.sharekey.key
   end
 
   def visibility
diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb
index 04be5e4db..f070e7900 100644
--- a/app/services/post_status_service.rb
+++ b/app/services/post_status_service.rb
@@ -285,7 +285,7 @@ class PostStatusService < BaseService
       local_only: @local_only,
       delete_after: @delete_after,
       reject_replies: @options[:noreplies] || false,
-      sharekey: @sharekey,
+      sharekey: @options[:sharekey],
       language: language_from_option(@options[:language]) || @account.user_default_language&.presence || 'en',
       application: @options[:application],
       content_type: @options[:content_type] || @account.user&.setting_default_content_type,
diff --git a/db/migrate/20191211235208_create_normalized_statuses.rb b/db/migrate/20191211235208_create_normalized_statuses.rb
index 9baaa3f62..d47c4feb4 100644
--- a/db/migrate/20191211235208_create_normalized_statuses.rb
+++ b/db/migrate/20191211235208_create_normalized_statuses.rb
@@ -1,7 +1,7 @@
 class CreateNormalizedStatuses < ActiveRecord::Migration[5.2]
   def up
     create_table :normalized_statuses do |t|
-      t.references :status, foreign_key: true
+      t.references :status, foreign_key: true, index: {unique: true}
       t.text :text
     end
 
diff --git a/db/migrate/20191212022020_create_sharekeys.rb b/db/migrate/20191212022020_create_sharekeys.rb
new file mode 100644
index 000000000..c0027babe
--- /dev/null
+++ b/db/migrate/20191212022020_create_sharekeys.rb
@@ -0,0 +1,19 @@
+class CreateSharekeys < ActiveRecord::Migration[5.2]
+  def up
+    create_table :sharekeys do |t|
+      t.references :status, foreign_key: true, index: {unique: true}
+      t.string :key
+    end
+
+    safety_assured do
+      execute 'INSERT INTO sharekeys (status_id, key) SELECT id, sharekey FROM statuses WHERE local AND sharekey IS NOT NULL'
+      remove_column :statuses, :sharekey
+    end
+  end
+
+  def down
+    add_column :statuses, :sharekey, :string
+    execute 'UPDATE statuses SET sharekey = s.key FROM (SELECT status_id, key FROM sharekeys) AS s WHERE statuses.id = s.id'
+    drop_table :sharekeys
+  end
+end
diff --git a/db/migrate/20191212022653_create_imported_statuses.rb b/db/migrate/20191212022653_create_imported_statuses.rb
new file mode 100644
index 000000000..3d7a9c99d
--- /dev/null
+++ b/db/migrate/20191212022653_create_imported_statuses.rb
@@ -0,0 +1,21 @@
+class CreateImportedStatuses < ActiveRecord::Migration[5.2]
+  def up
+    create_table :imported_statuses do |t|
+      t.references :status, foreign_key: true, index: {unique: true}
+      t.string :origin, index: {unique: true}
+    end
+
+    safety_assured { execute 'INSERT INTO imported_statuses (status_id, origin) SELECT id, origin FROM statuses WHERE imported' }
+    safety_assured do
+      remove_column :statuses, :imported
+      remove_column :statuses, :origin
+    end
+  end
+
+  def down
+    add_column :statuses, :imported, :boolean
+    add_column :statuses, :origin, :string, index: { unique: true }
+    execute 'UPDATE statuses SET imported = true, origin = s.origin FROM (SELECT status_id, origin FROM imported_statuses) AS s WHERE statuses.id = s.id'
+    drop_table :imported_statuses
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 96e9148ed..47b792a8b 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 2019_12_12_002705) do
+ActiveRecord::Schema.define(version: 2019_12_12_022653) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "pg_trgm"
@@ -335,6 +335,13 @@ ActiveRecord::Schema.define(version: 2019_12_12_002705) do
     t.index ["user_id"], name: "index_identities_on_user_id"
   end
 
+  create_table "imported_statuses", force: :cascade do |t|
+    t.bigint "status_id"
+    t.string "origin"
+    t.index ["origin"], name: "index_imported_statuses_on_origin", unique: true
+    t.index ["status_id"], name: "index_imported_statuses_on_status_id", unique: true
+  end
+
   create_table "imports", force: :cascade do |t|
     t.integer "type", null: false
     t.boolean "approved", default: false, null: false
@@ -636,6 +643,12 @@ ActiveRecord::Schema.define(version: 2019_12_12_002705) do
     t.index ["thing_type", "thing_id", "var"], name: "index_settings_on_thing_type_and_thing_id_and_var", unique: true
   end
 
+  create_table "sharekeys", force: :cascade do |t|
+    t.bigint "status_id"
+    t.string "key"
+    t.index ["status_id"], name: "index_sharekeys_on_status_id", unique: true
+  end
+
   create_table "site_uploads", force: :cascade do |t|
     t.string "var", default: "", null: false
     t.string "file_file_name"
@@ -687,13 +700,10 @@ ActiveRecord::Schema.define(version: 2019_12_12_002705) do
     t.boolean "local_only"
     t.bigint "poll_id"
     t.boolean "curated", default: false, null: false
-    t.string "sharekey"
     t.boolean "network", default: false, null: false
     t.string "content_type"
     t.text "footer"
     t.boolean "edited"
-    t.boolean "imported"
-    t.string "origin"
     t.boolean "boostable"
     t.boolean "reject_replies"
     t.index ["account_id", "id", "visibility", "updated_at"], name: "index_statuses_20180106", order: { id: :desc }
@@ -701,7 +711,6 @@ ActiveRecord::Schema.define(version: 2019_12_12_002705) do
     t.index ["in_reply_to_account_id"], name: "index_statuses_on_in_reply_to_account_id"
     t.index ["in_reply_to_id"], name: "index_statuses_on_in_reply_to_id"
     t.index ["network"], name: "index_statuses_on_network", where: "network"
-    t.index ["origin"], name: "index_statuses_on_origin", unique: true
     t.index ["reblog_of_id", "account_id"], name: "index_statuses_on_reblog_of_id_and_account_id"
     t.index ["uri"], name: "index_statuses_on_uri", unique: true
   end
@@ -850,6 +859,7 @@ ActiveRecord::Schema.define(version: 2019_12_12_002705) do
   add_foreign_key "follows", "accounts", column: "target_account_id", name: "fk_745ca29eac", on_delete: :cascade
   add_foreign_key "follows", "accounts", name: "fk_32ed1b5560", on_delete: :cascade
   add_foreign_key "identities", "users", name: "fk_bea040f377", on_delete: :cascade
+  add_foreign_key "imported_statuses", "statuses"
   add_foreign_key "imports", "accounts", name: "fk_6db1b6e408", on_delete: :cascade
   add_foreign_key "invites", "users", on_delete: :cascade
   add_foreign_key "linked_users", "users", column: "target_user_id", on_delete: :cascade
@@ -888,6 +898,7 @@ ActiveRecord::Schema.define(version: 2019_12_12_002705) do
   add_foreign_key "scheduled_statuses", "accounts", on_delete: :cascade
   add_foreign_key "session_activations", "oauth_access_tokens", column: "access_token_id", name: "fk_957e5bda89", on_delete: :cascade
   add_foreign_key "session_activations", "users", name: "fk_e5fda67334", on_delete: :cascade
+  add_foreign_key "sharekeys", "statuses"
   add_foreign_key "status_pins", "accounts", name: "fk_d4cb435b62", on_delete: :cascade
   add_foreign_key "status_pins", "statuses", on_delete: :cascade
   add_foreign_key "status_stats", "statuses", on_delete: :cascade
diff --git a/spec/fabricators/imported_status_fabricator.rb b/spec/fabricators/imported_status_fabricator.rb
new file mode 100644
index 000000000..475ecd94f
--- /dev/null
+++ b/spec/fabricators/imported_status_fabricator.rb
@@ -0,0 +1,4 @@
+Fabricator(:imported_status) do
+  status nil
+  origin "MyString"
+end
diff --git a/spec/fabricators/sharekey_fabricator.rb b/spec/fabricators/sharekey_fabricator.rb
new file mode 100644
index 000000000..9e346603a
--- /dev/null
+++ b/spec/fabricators/sharekey_fabricator.rb
@@ -0,0 +1,4 @@
+Fabricator(:sharekey) do
+  status nil
+  key    "MyString"
+end
diff --git a/spec/models/imported_status_spec.rb b/spec/models/imported_status_spec.rb
new file mode 100644
index 000000000..f571a561a
--- /dev/null
+++ b/spec/models/imported_status_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe ImportedStatus, type: :model do
+  pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/models/sharekey_spec.rb b/spec/models/sharekey_spec.rb
new file mode 100644
index 000000000..99fbf0d8c
--- /dev/null
+++ b/spec/models/sharekey_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe Sharekey, type: :model do
+  pending "add some examples to (or delete) #{__FILE__}"
+end