Automatically delete old accounts after 14 days. TODO: Tests

pull/1578/head
Rick Carlino 2019-11-20 17:49:39 -06:00
parent 8ac0c0625e
commit a0e69bdb4a
7 changed files with 101 additions and 2 deletions

View File

@ -213,6 +213,7 @@ module Api
# Devices have a `last_saw_api` field to assist users with debugging.
# We update this column every time an FBOS device talks to the API.
def mark_as_seen(bot = (current_user && current_user.device))
current_user && current_user.reset_inactivity_tracking!
when_farmbot_os do
if bot
v = fbos_version

View File

@ -0,0 +1,55 @@
# Recurring task that deletes inactive accounts.
class InactiveAccountJob < ApplicationJob
queue_as :default
LIMIT = 1000
INACTIVE_WITH_DEVICE = 11.months + 15.days
INACTIVE_NO_DEVICE = 2.months + 15.days
def perform
notify_old_accounts
delete_old_accounts
end
private
def notify_old_accounts
all_inactive
.where(inactivity_warning_sent_at: nil)
.map(&:send_inactivity_warning)
end
def delete_old_accounts
all_inactive
.where
.not(inactivity_warning_sent_at: nil)
.where("inactivity_warning_sent_at < ?", 14.days.ago)
.map(&:deactivate_account)
end
# Returns a Map. Key is the number of warnings sent, value is a User object
# (not a device, but device is preloaded)
def all_inactive
return @all_inactive if @all_inactive
users = User.includes(:device)
# They signed up for an account, but never configured a device.
no_device = users
.where("devices.fbos_version" => nil)
.references(:devices)
# They signed up for an account and once had a working device.
ok_device = users
.where
.not("devices.fbos_version" => nil)
.references(:devices)
inactive_3mo = no_device
.where("last_sign_in_at < ?", INACTIVE_NO_DEVICE.ago)
inactive_11mo = ok_device
.where("last_sign_in_at < ?", INACTIVE_WITH_DEVICE.ago)
@all_inactive = inactive_11mo
.or(inactive_3mo)
.order("RANDOM()")
.limit(LIMIT)
end
end

View File

@ -0,0 +1,11 @@
class InactivityMailer < ApplicationMailer
attr_reader :user
SUBJECT = "Your FarmBot Account Will Be Deleted Due to Inactivity"
ORDER = { 1 => "First", 2 => "Second", 3 => "Final" }
def send_warning(user)
@user = user
mail to: user.email, subject: SUBJECT
end
end

View File

@ -54,4 +54,26 @@ class User < ApplicationRecord
.current
.raw_amqp_send(msg.to_json, Api::RmqUtilsController::PUBLIC_BROADCAST)
end
# The web app deletes account that go inactive for long periods.
# It is called when the user logs in to the app.
def reset_inactivity_tracking!
update!(inactivity_warning_sent_at: nil)
end
def send_inactivity_warning
User.transaction do
update!(inactivity_warning_sent_at: Time.now)
InactivityMailer.send_warning(self).deliver_later
end
end
def deactivate_account
User.transaction do
raise "HALTING ERRONEOUS DELETION" if last_sign_in_at > 3.months.ago
# Prevent double deletion / race conditions.
u.update!(last_sign_in_at: Time.now, inactivity_warning_sent_at: nil)
u.delay.destroy!
end
end
end

View File

@ -0,0 +1,3 @@
You have not logged in <%= time_ago_in_words(user.last_sign_in_at) %>. Your account will be automatically deleted after 14 days of inactivity.
To halt the deletion process, please log in to your account.

View File

@ -0,0 +1,5 @@
class AddInactivityFieldsToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :inactivity_warning_sent_at, :datetime
end
end

View File

@ -1648,7 +1648,8 @@ CREATE TABLE public.users (
confirmation_token character varying,
agreed_to_terms_at timestamp without time zone,
confirmation_sent_at timestamp without time zone,
unconfirmed_email character varying
unconfirmed_email character varying,
inactivity_warning_sent_at timestamp without time zone
);
@ -3366,6 +3367,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20190924190539'),
('20190930202839'),
('20191002125625'),
('20191107170431');
('20191107170431'),
('20191119204916');