]> git.openstreetmap.org Git - rails.git/commitdiff
Add earliest allowed deletion time to user model
authorAnton Khorev <tony29@yandex.ru>
Tue, 24 Oct 2023 17:42:23 +0000 (20:42 +0300)
committerAnton Khorev <tony29@yandex.ru>
Wed, 22 Nov 2023 14:02:48 +0000 (17:02 +0300)
.rubocop_todo.yml
app/models/changeset.rb
app/models/user.rb
db/migrate/20231117170422_add_closed_at_index_to_changesets.rb [new file with mode: 0644]
db/structure.sql
test/models/user_test.rb

index e3407c6dc0111d811f1b34377429a46d63a2d14a..bd2f92309886c83b83e4dfdaecd5cc8153f23cc7 100644 (file)
@@ -61,7 +61,7 @@ Metrics/BlockNesting:
 # Offense count: 26
 # Configuration parameters: CountComments, CountAsOne.
 Metrics/ClassLength:
-  Max: 286
+  Max: 297
 
 # Offense count: 59
 # Configuration parameters: AllowedMethods, AllowedPatterns.
index ce09438245844be0ff4ba241818973cdf26b5bab..137de18fd6479640c42688df2aceff3f56f1bfbb 100644 (file)
 #
 # Indexes
 #
-#  changesets_bbox_idx                (min_lat,max_lat,min_lon,max_lon) USING gist
-#  changesets_closed_at_idx           (closed_at)
-#  changesets_created_at_idx          (created_at)
-#  changesets_user_id_created_at_idx  (user_id,created_at)
-#  changesets_user_id_id_idx          (user_id,id)
+#  changesets_bbox_idx                        (min_lat,max_lat,min_lon,max_lon) USING gist
+#  changesets_closed_at_idx                   (closed_at)
+#  changesets_created_at_idx                  (created_at)
+#  changesets_user_id_created_at_idx          (user_id,created_at)
+#  changesets_user_id_id_idx                  (user_id,id)
+#  index_changesets_on_user_id_and_closed_at  (user_id,closed_at)
 #
 # Foreign Keys
 #
index 7571dd9dc5c8011f4615ebf970b6f0daa377adc9..1942a25cc237a784394b91f9ba64c844f36e3309 100644 (file)
@@ -419,6 +419,18 @@ class User < ApplicationRecord
     end
   end
 
+  def deletion_allowed_at
+    unless Settings.user_account_deletion_delay.nil?
+      last_changeset = changesets.reorder(:closed_at => :desc).first
+      return last_changeset.closed_at.utc + Settings.user_account_deletion_delay.hours if last_changeset
+    end
+    creation_time.utc
+  end
+
+  def deletion_allowed?
+    deletion_allowed_at <= Time.now.utc
+  end
+
   private
 
   def encrypt_password
diff --git a/db/migrate/20231117170422_add_closed_at_index_to_changesets.rb b/db/migrate/20231117170422_add_closed_at_index_to_changesets.rb
new file mode 100644 (file)
index 0000000..e9d7e62
--- /dev/null
@@ -0,0 +1,7 @@
+class AddClosedAtIndexToChangesets < ActiveRecord::Migration[7.1]
+  disable_ddl_transaction!
+
+  def change
+    add_index :changesets, [:user_id, :closed_at], :algorithm => :concurrently
+  end
+end
index 56e778523f7a7597d3a26670cc0dae97187a57e7..f74d4d571e2f58c8d3ef65009af3345d6128ea7b 100644 (file)
@@ -2499,6 +2499,13 @@ CREATE INDEX index_changeset_comments_on_changeset_id_and_created_at ON public.c
 CREATE INDEX index_changeset_comments_on_created_at ON public.changeset_comments USING btree (created_at);
 
 
+--
+-- Name: index_changesets_on_user_id_and_closed_at; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_changesets_on_user_id_and_closed_at ON public.changesets USING btree (user_id, closed_at);
+
+
 --
 -- Name: index_changesets_subscribers_on_changeset_id; Type: INDEX; Schema: public; Owner: -
 --
@@ -3499,6 +3506,7 @@ INSERT INTO "schema_migrations" (version) VALUES
 ('23'),
 ('22'),
 ('21'),
+('20231117170422'),
 ('20231101222146'),
 ('20231029151516'),
 ('20231010194809'),
index a4ed07e09eac0079a610f8e03762b0b89aeda105..5c48bb9698a6a73d56b7ab120b871d24902d18c5 100644 (file)
@@ -282,4 +282,62 @@ class UserTest < ActiveSupport::TestCase
     oauth_access_token.reload
     assert_predicate oauth_access_token, :revoked?
   end
+
+  def test_deletion_allowed_when_no_changesets
+    with_user_account_deletion_delay(10000) do
+      user = create(:user)
+      assert_predicate user, :deletion_allowed?
+    end
+  end
+
+  def test_deletion_allowed_without_delay
+    with_user_account_deletion_delay(nil) do
+      user = create(:user)
+      create(:changeset, :user => user)
+      user.reload
+      assert_predicate user, :deletion_allowed?
+    end
+  end
+
+  def test_deletion_allowed_past_delay
+    with_user_account_deletion_delay(10) do
+      user = create(:user)
+      create(:changeset, :user => user, :created_at => Time.now.utc - 12.hours, :closed_at => Time.now.utc - 10.hours)
+      user.reload
+      assert_predicate user, :deletion_allowed?
+    end
+  end
+
+  def test_deletion_allowed_during_delay
+    with_user_account_deletion_delay(10) do
+      user = create(:user)
+      create(:changeset, :user => user, :created_at => Time.now.utc - 11.hours, :closed_at => Time.now.utc - 9.hours)
+      user.reload
+      assert_not_predicate user, :deletion_allowed?
+      assert_equal Time.now.utc + 1.hour, user.deletion_allowed_at
+    end
+  end
+
+  def test_deletion_allowed_past_zero_delay
+    with_user_account_deletion_delay(0) do
+      user = create(:user)
+      create(:changeset, :user => user, :created_at => Time.now.utc, :closed_at => Time.now.utc + 1.hour)
+      travel 90.minutes do
+        user.reload
+        assert_predicate user, :deletion_allowed?
+      end
+    end
+  end
+
+  def test_deletion_allowed_during_zero_delay
+    with_user_account_deletion_delay(0) do
+      user = create(:user)
+      create(:changeset, :user => user, :created_at => Time.now.utc, :closed_at => Time.now.utc + 1.hour)
+      travel 30.minutes do
+        user.reload
+        assert_not_predicate user, :deletion_allowed?
+        assert_equal Time.now.utc + 30.minutes, user.deletion_allowed_at
+      end
+    end
+  end
 end