#1955: Migrate tags to belong to named users for enhanced privacy.

This commit is contained in:
Jyri-Petteri Paloposki 2019-06-25 03:15:23 +03:00
parent 5ec2c77f78
commit 5394973346
9 changed files with 97 additions and 24 deletions

View file

@ -0,0 +1,72 @@
class AddUserIdToTag < ActiveRecord::Migration[5.2]
def self.up
add_column :tags, :user_id, :integer
# Find uses of each tag for both Todos and RecurringTodos to
# figure out which users use which tags.
@tags = execute <<-EOQ
SELECT t.id AS tid, tds.user_id AS todo_uid, rt.user_id AS rtodo_uid
FROM tags t
JOIN taggings tgs ON tgs.tag_id = t.id
LEFT OUTER JOIN todos tds
ON tgs.taggable_type = "Todo" AND tds.id = tgs.taggable_id
LEFT OUTER JOIN recurring_todos rt
ON tgs.taggable_type = "RecurringTodo" AND rt.id = tgs.taggable_id
WHERE rt.id IS NOT NULL OR tds.id IS NOT NULL
GROUP BY t.id, tds.user_id, rt.user_id
EOQ
# Map each tag to the users using it.
@tag_users = {}
@tags.each do |row|
uid = (row[1] ? row[1] : row[2])
if not @tag_users[row[0]]
@tag_users[row[0]] = [uid]
elsif not @tag_users[row[0]].include? uid
@tag_users[row[0]] << uid
end
end
# Go through the tags assigning users and duplicating as necessary.
@tag_users.each do |tid, uids|
tag = Tag.find(tid)
# One of the users will get the original tag instance, but first
# duplicate their own copy to all the others.
extras = uids.length - 1
extras.times do |n|
uid = uids[n+1]
# Create a duplicate of the tag assigned to the user.
new_tag = tag.dup
new_tag.user_id = uid
new_tag.save!
# Move all the user's regular todos to the new tag.
connection.execute(<<-EOQ)
UPDATE taggings ta
JOIN todos t
ON ta.taggable_type = "Todo" AND t.id = ta.taggable_id
SET ta.tag_id = #{new_tag.id}
WHERE t.user_id = #{uid}
EOQ
# Move all the user's recurring todos to the new tag.
connection.execute(<<-EOQ)
UPDATE taggings ta
JOIN recurring_todos t
ON ta.taggable_type = "RecurringTodo" AND t.id = ta.taggable_id
SET ta.tag_id = #{new_tag.id}
WHERE t.user_id = #{uid}
EOQ
end
tag.user_id = uids[0]
tag.save!
end
end
def self.down
remove_column :tags, :user_id
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2016_01_31_233303) do
ActiveRecord::Schema.define(version: 2019_06_18_202817) do
create_table "attachments", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
t.integer "todo_id"
@ -159,6 +159,7 @@ ActiveRecord::Schema.define(version: 2016_01_31_233303) do
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
t.index ["name"], name: "index_tags_on_name"
end