diff --git a/.rubocop.yml b/.rubocop.yml index c0d760493..eef2eaac0 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -396,6 +396,8 @@ Rails/FindBy: Enabled: true Include: - "**/*.rb" + Exclude: + - "config/initializers/ahoy.rb" Rails/FindEach: Enabled: true diff --git a/app/models/debate.rb b/app/models/debate.rb index c4ca74af0..a6185beac 100644 --- a/app/models/debate.rb +++ b/app/models/debate.rb @@ -46,8 +46,6 @@ class Debate < ApplicationRecord scope :featured, -> { where.not(featured_at: nil) } scope :public_for_api, -> { all } - visitable class_name: "Visit" - attr_accessor :link_required def self.recommendations(user) diff --git a/config/initializers/ahoy.rb b/config/initializers/ahoy.rb index 91a848443..b4e8817ec 100644 --- a/config/initializers/ahoy.rb +++ b/config/initializers/ahoy.rb @@ -1,10 +1,14 @@ -Ahoy.geocode = false Ahoy.api = true Ahoy.server_side_visits = :when_needed +Ahoy.mask_ips = true +Ahoy.cookies = :none # Most code comes from: # https://github.com/ankane/ahoy/blob/3661b7f9a/docs/Ahoy-2-Upgrade.md class Ahoy::Store < Ahoy::DatabaseStore + def authenticate(...) + end + def track_visit(data) data[:id] = ensure_uuid(data.delete(:visit_token)) data[:visitor_id] = ensure_uuid(data.delete(:visitor_token)) @@ -18,19 +22,30 @@ class Ahoy::Store < Ahoy::DatabaseStore end def visit - @visit ||= visit_model.find_by(id: ensure_uuid(ahoy.visit_token)) if ahoy.visit_token + unless defined?(@visit) + if ahoy.send(:existing_visit_token) || ahoy.instance_variable_get(:@visit_token) + @visit = visit_model.where(id: ensure_uuid(ahoy.visit_token)).take if ahoy.visit_token + elsif !Ahoy.cookies? && ahoy.visitor_token + @visit = visit_model.where(visitor_id: ensure_uuid(ahoy.visitor_token)) + .where(started_at: Ahoy.visit_duration.ago..) + .order(started_at: :desc) + .first + else + @visit = nil + end + end + + @visit end def visit_model Visit end - UUID_NAMESPACE = UUIDTools::UUID.parse("a82ae811-5011-45ab-a728-569df7499c5f") - def ensure_uuid(id) UUIDTools::UUID.parse(id).to_s rescue - UUIDTools::UUID.sha1_create(UUID_NAMESPACE, id).to_s + UUIDTools::UUID.sha1_create(UUIDTools::UUID.parse(Ahoy::Tracker::UUID_NAMESPACE), id).to_s end def exclude? diff --git a/db/migrate/20240424002959_remove_visit_id_from_debates.rb b/db/migrate/20240424002959_remove_visit_id_from_debates.rb new file mode 100644 index 000000000..67ecd2c8e --- /dev/null +++ b/db/migrate/20240424002959_remove_visit_id_from_debates.rb @@ -0,0 +1,5 @@ +class RemoveVisitIdFromDebates < ActiveRecord::Migration[7.0] + def change + remove_column :debates, :visit_id, :string + end +end diff --git a/db/migrate/20240424013913_add_visitor_id_and_started_at_index_to_visits.rb b/db/migrate/20240424013913_add_visitor_id_and_started_at_index_to_visits.rb new file mode 100644 index 000000000..b61bafaf2 --- /dev/null +++ b/db/migrate/20240424013913_add_visitor_id_and_started_at_index_to_visits.rb @@ -0,0 +1,5 @@ +class AddVisitorIdAndStartedAtIndexToVisits < ActiveRecord::Migration[7.0] + def change + add_index :visits, [:visitor_id, :started_at] + end +end diff --git a/db/schema.rb b/db/schema.rb index 761958871..0b5dfa0d5 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[7.0].define(version: 2024_03_22_223950) do +ActiveRecord::Schema[7.0].define(version: 2024_04_24_013913) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" enable_extension "plpgsql" @@ -528,7 +528,6 @@ ActiveRecord::Schema[7.0].define(version: 2024_03_22_223950) do t.integer "author_id" t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false - t.string "visit_id" t.datetime "hidden_at", precision: nil t.integer "flags_count", default: 0 t.datetime "ignored_flag_at", precision: nil @@ -1713,6 +1712,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_03_22_223950) do t.datetime "started_at", precision: nil t.index ["started_at"], name: "index_visits_on_started_at" t.index ["user_id"], name: "index_visits_on_user_id" + t.index ["visitor_id", "started_at"], name: "index_visits_on_visitor_id_and_started_at" end create_table "votation_types", force: :cascade do |t| diff --git a/lib/tasks/consul.rake b/lib/tasks/consul.rake index 0e3a5aad0..fcc23ff26 100644 --- a/lib/tasks/consul.rake +++ b/lib/tasks/consul.rake @@ -2,8 +2,10 @@ namespace :consul do desc "Runs tasks needed to upgrade to the latest version" task execute_release_tasks: ["settings:rename_setting_keys", "settings:add_new_settings", - "execute_release_2.1.0_tasks"] + "execute_release_2.2.0_tasks"] - desc "Runs tasks needed to upgrade from 2.0.1 to 2.1.0" - task "execute_release_2.1.0_tasks": [] + desc "Runs tasks needed to upgrade from 2.1.1 to 2.2.0" + task "execute_release_2.2.0_tasks": [ + "db:mask_ips" + ] end diff --git a/lib/tasks/db.rake b/lib/tasks/db.rake index 3c1d00166..c8b50e7cc 100644 --- a/lib/tasks/db.rake +++ b/lib/tasks/db.rake @@ -4,4 +4,15 @@ namespace :db do I18n.enforce_available_locales = false Tenant.switch(args[:tenant]) { load(Rails.root.join("db", "dev_seeds.rb")) } end + + desc "Mask IPs collected with Ahoy" + task mask_ips: :environment do + ApplicationLogger.new.info "Masking tracked IPs collected with Ahoy" + + Tenant.run_on_each do + Visit.find_each do |visit| + visit.update_column :ip, Ahoy.mask_ip(visit.ip) + end + end + end end diff --git a/spec/lib/tasks/db_spec.rb b/spec/lib/tasks/db_spec.rb new file mode 100644 index 000000000..084128d2e --- /dev/null +++ b/spec/lib/tasks/db_spec.rb @@ -0,0 +1,27 @@ +require "rails_helper" + +describe "rake db:mask_ips" do + before { Rake::Task["db:mask_ips"].reenable } + + it "mask IPs on all tenants" do + create(:visit, ip: "1.1.1.1") + create(:visit, ip: "1.1.1.2") + create(:visit, ip: "1.1.2.2") + + create(:tenant, schema: "myhometown") + + Tenant.switch("myhometown") do + create(:visit, ip: "1.1.1.1") + create(:visit, ip: "1.1.1.2") + create(:visit, ip: "1.1.3.3") + end + + Rake.application.invoke_task("db:mask_ips") + + expect(Visit.pluck(:ip)).to match_array %w[1.1.1.0 1.1.1.0 1.1.2.0] + + Tenant.switch("myhometown") do + expect(Visit.pluck(:ip)).to match_array %w[1.1.1.0 1.1.1.0 1.1.3.0] + end + end +end