Merge pull request #5504 from consuldemocracy/remove_ahoy_cookies

Use a GDPR-compliant configuration for Ahoy
This commit is contained in:
Javi Martín
2024-05-13 15:41:37 +02:00
committed by GitHub
9 changed files with 77 additions and 12 deletions

View File

@@ -396,6 +396,8 @@ Rails/FindBy:
Enabled: true
Include:
- "**/*.rb"
Exclude:
- "config/initializers/ahoy.rb"
Rails/FindEach:
Enabled: true

View File

@@ -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)

View File

@@ -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?

View File

@@ -0,0 +1,5 @@
class RemoveVisitIdFromDebates < ActiveRecord::Migration[7.0]
def change
remove_column :debates, :visit_id, :string
end
end

View File

@@ -0,0 +1,5 @@
class AddVisitorIdAndStartedAtIndexToVisits < ActiveRecord::Migration[7.0]
def change
add_index :visits, [:visitor_id, :started_at]
end
end

View File

@@ -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|

View File

@@ -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

View File

@@ -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

27
spec/lib/tasks/db_spec.rb Normal file
View File

@@ -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