Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Sync anon'ed members #76

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions app/lib/identity_tijuana/user_ghosting.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
module IdentityTijuana
# TODO add AnonymisationLog in TJ
class UserGhosting
def initialize(user_ids, reason)
@user_ids = user_ids
@reason = reason
end

def ghost_users
tj_conn = IdentityTijuana::ReadWrite.connection
# log_ids = log_anonymisation_started
begin
tj_conn.transaction do
anon_basic_info(tj_conn)
# anon_automation_events(tj_conn)
# anon_call_outcomes(tj_conn)
# anon_comments(tj_conn)
end
rescue ActiveRecord::RecordInvalid => e
# log_anonymisation_failed(log_ids, e.message, e)
Rails.logger.error "Anonymisation failed: #{e.message}"
end

# log_anonymisation_finished(log_ids)
end

private

def log_anonymisation_started
log_ids = []

@user_ids.each do |user_id|
logged = AnonymisationLog.create!(
user_id: user_id,
reason: @reason,
status: 'started',
started_at: DateTime.current.utc,
)
log_ids << logged.id
end

log_ids
end

def log_anonymisation_finished(log_ids)
# rubocop:disable Rails/SkipsModelValidations
AnonymisationLog.where(id: log_ids)
.update_all(
finished_at: DateTime.current.utc,
status: 'completed'
)
# rubocop:enable Rails/SkipsModelValidations
end

def log_anonymisation_failed(log_ids, error_msg, error_stack)
# rubocop:disable Rails/SkipsModelValidations
AnonymisationLog.where(id: log_ids)
.update_all(
finished_at: DateTime.current.utc,
status: 'failed',
message: error_msg,
error_stack: error_stack
)
# rubocop:enable Rails/SkipsModelValidations
end

def anon_basic_info(tj_conn)
tj_conn.execute(<<~SQL.squish)
UPDATE users
SET email = concat(id, '@#{Settings.ghoster.email_domain}'),
first_name = null,
last_name = null,
mobile_number = null,
home_number = null,
street_address = null,
country_iso = null,
is_member = 0,
encrypted_password = null,
password_salt = null,
reset_password_token = null,
remember_created_at = null,
sign_in_count = 0,
current_sign_in_at = null,
last_sign_in_at = null,
current_sign_in_ip = null,
last_sign_in_ip = null,
is_admin = 0,
postcode_id = null,
old_tags = '',
is_volunteer = 0,
random = null,
notes = null,
quick_donate_trigger_id = null,
facebook_id = null,
otp_secret_key = null,
tracking_token = null,
do_not_call = 1,
active = 0,
do_not_sms = 1,
updated_at = CURRENT_TIMESTAMP
WHERE id IN (#{@user_ids.join(',')});
SQL
end
# FIX
# exist in production but missing in testing db
# -- new_tags = null,
# -- fragment = null,
# mautic_id = null,

def anon_automation_events(tj_conn)
tj_conn.execute(<<~SQL.squish)
UPDATE automation_events
SET payload = null
WHERE id IN (#{@user_ids.join(',')});
SQL
end

def anon_call_outcomes(tj_conn)
tj_conn.execute(<<~SQL.squish)
UPDATE call_outcomes
SET email = null,
payload = null,
dialed_number = null
WHERE id IN (#{@user_ids.join(',')});
SQL
end

def anon_comments(tj_conn)
tj_conn.execute(<<~SQL.squish)
UPDATE comments
SET body = null,
dialed_number = null,
updated_at = CURRENT_TIMESTAMP
WHERE id IN (#{@user_ids.join(',')});
SQL
end
end
end
12 changes: 12 additions & 0 deletions lib/identity_tijuana.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ module IdentityTijuana
MEMBER_RECORD_DATA_TYPE = 'object'.freeze
MUTEX_EXPIRY_DURATION = 10.minutes

def self.ghost_members(member_ids:, reason:, admin_member_id:)
return if member_ids.empty?

# check that we have the matching user ids for TJ system
user_ids = MemberExternalId.where(system: 'tijuana', member_id: member_ids)
.pluck(:external_id)
.map(&:to_i)

anon_reason = "#{reason} - via Id - admin:#{admin_member_id}"
UserGhosting.new(user_ids, anon_reason).ghost_users if user_ids.any?
end

def self.push(_sync_id, member_ids, _external_system_params)
members = Member.where(id: member_ids).with_email.order(:id)
yield members, nil
Expand Down
51 changes: 51 additions & 0 deletions spec/app/lib/user_ghosting_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
require 'rails_helper'

describe IdentityTijuana::UserGhosting do
before(:each) do
allow(Settings).to(
receive_message_chain("tijuana.database_url") { ENV['TIJUANA_DATABASE_URL'] }
)
allow(Settings).to(
receive_message_chain("ghoster.email_domain") { 'anoned.non' }
)
end

context '#ghosting' do
context 'user with all attributes' do
it 'should ghost all attributes' do
u = FactoryBot.create(:tijuana_user_with_everything)

anon_domain = Settings.ghoster.email_domain
described_class.new([u.id], 'test-reason').ghost_users

u.reload

expect(u.email).to eq("#{u.id}@#{anon_domain}")

nils = [:first_name, :last_name, :mobile_number,
:home_number, :street_address, :country_iso,
:encrypted_password, :password_salt, :reset_password_token,
:remember_created_at, :current_sign_in_at, :last_sign_in_at,
:current_sign_in_ip, :last_sign_in_ip, :postcode_id,
:random, :notes, :quick_donate_trigger_id, :facebook_id,
:otp_secret_key, :tracking_token]

nils.each do |prop|
expect(u.send(prop)).to be(nil)
end

falsey = [:is_member, :is_admin, :active, :is_volunteer]

falsey.each do |prop|
expect(u.send(prop)).to eq(false)
end

truthy = [:do_not_call, :do_not_sms]

truthy.each do |prop|
expect(u.send(prop)).to eq(true)
end
end
end
end
end
6 changes: 6 additions & 0 deletions spec/test_identity_app/app/lib/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ def self.databases
}
end

def self.ghoster
return {
"email_domain" => "example.com"
}
end

def self.redis_url
return ENV['REDIS_URL']
end
Expand Down
23 changes: 23 additions & 0 deletions spec/test_identity_app/spec/factories/tijuana/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,29 @@ module IdentityTijuana
suburb { Faker::Address.city }
postcode { IdentityTijuana::Postcode.new(number: Faker::Address.zip_code, state: Faker::Address.state_abbr) }
end

factory :tijuana_user_with_everything do
home_number { "612#{::Kernel.rand(10_000_000..99_999_999)}" }
mobile_number { "614#{::Kernel.rand(10_000_000..99_999_999)}" }
street_address { Faker::Address.street_address }
suburb { Faker::Address.city }
postcode { IdentityTijuana::Postcode.new(number: Faker::Address.zip_code, state: Faker::Address.state_abbr) }
country_iso { Faker::Address.country_code }
encrypted_password { Faker::Internet.password }
password_salt { Faker::Crypto.md5 }
reset_password_token { Faker::Crypto.md5 }
reset_password_sent_at { 20.days.ago }
remember_created_at { 2.hours.ago }
current_sign_in_at { 1.hours.ago }
last_sign_in_at { 10.days.ago }
last_sign_in_ip { Faker::Internet.ip_v4_address }
random { rand(0.0..0.001) }
notes { Faker::Lorem.paragraph }
quick_donate_trigger_id { Faker::Alphanumeric.alphanumeric(number: 12) }
facebook_id { Faker::Alphanumeric.alphanumeric(number: 12) }
otp_secret_key { Faker::Alphanumeric.alphanumeric(number: 32) }
tracking_token { Faker::Alphanumeric.alphanumeric(number: 8) }
end
end
end
end