diff --git a/app/controllers/maintenance/user/deletions_controller.rb b/app/controllers/maintenance/user/deletions_controller.rb deleted file mode 100644 index f029066b6..000000000 --- a/app/controllers/maintenance/user/deletions_controller.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -module Maintenance - module User - class DeletionsController < ApplicationController - respond_to :html, :json, :xml - - def show - end - - def destroy - deletion = UserDeletion.new(user: CurrentUser.user, deleter: CurrentUser.user, password: params.dig(:user, :password), request: request) - deletion.delete! - - if deletion.errors.none? - session.delete(:user_id) - flash[:notice] = "Your account has been deactivated" - respond_with(deletion, location: posts_path) - else - flash[:notice] = deletion.errors.full_messages.join("; ") - redirect_to maintenance_user_deletion_path - end - end - end - end -end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 9dc0639f9..6ab1a14c4 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -114,6 +114,32 @@ class UsersController < ApplicationController end end + def deactivate + if params[:id].present? + @user = authorize User.find(params[:id]) + else + @user = authorize CurrentUser.user + end + + respond_with(@user) + end + + def destroy + @user = authorize User.find(params[:id]) + + user_deletion = UserDeletion.new(user: @user, deleter: CurrentUser.user, password: params.dig(:user, :password), request: request) + user_deletion.delete! + + if user_deletion.errors.none? + session.delete(:user_id) + flash[:notice] = "Your account has been deactivated" + respond_with(user_deletion, location: posts_path) + else + flash[:notice] = user_deletion.errors.full_messages.join("; ") + redirect_to deactivate_user_path(@user) + end + end + def custom_style @custom_css = CurrentUser.user.custom_css expires_in 10.years diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index 9ad9f1fb1..e8145fbf1 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -13,6 +13,14 @@ class UserPolicy < ApplicationPolicy record.id == user.id || user.is_admin? end + def deactivate? + (record.id == user.id && !user.is_anonymous?) || user.is_owner? + end + + def destroy? + deactivate? + end + def promote? user.is_moderator? end diff --git a/app/views/maintenance/user/deletions/show.html.erb b/app/views/maintenance/user/deletions/show.html.erb deleted file mode 100644 index 7334839bb..000000000 --- a/app/views/maintenance/user/deletions/show.html.erb +++ /dev/null @@ -1,40 +0,0 @@ -<% page_title "Deactivate Account" %> - -
-
-

Deactivate Account

- -

- You can deactivate your <%= Danbooru.config.app_name %> account using - the form below. Deactivating your account will do the following things: -

- - - -

- The following things will not be deleted: -

- - - -

- Enter your password below to deactivate your account. This cannot be - undone. Your account cannot be recovered after it is deactivated. -

- - <%= edit_form_for(:user, url: maintenance_user_deletion_path, method: :delete) do |f| %> - <%= f.input :password %> - <%= f.submit "Deactivate account", "data-confirm": "Are you sure you want to deactivate your account? This cannot be undone" %> - <% end %> -
-
diff --git a/app/views/static/privacy_policy.html.erb b/app/views/static/privacy_policy.html.erb index 6f1e7da32..c62736662 100644 --- a/app/views/static/privacy_policy.html.erb +++ b/app/views/static/privacy_policy.html.erb @@ -353,8 +353,8 @@

Summary: You may deactivate your account, but we may retain your IP address and your public contributions to the Site.

-

If you would like to delete your account, you may request your - account to be deactivated <%= link_to "here", maintenance_user_deletion_path %>.

+

If you wish to to close your <%= @app_name %> account, you may deactivate your account + <%= link_to "here", deactivate_users_path %>.

When your account is deactivated, we will delete your non-public personal information from our active systems, including your email address, diff --git a/app/views/users/deactivate.html.erb b/app/views/users/deactivate.html.erb new file mode 100644 index 000000000..3528325ef --- /dev/null +++ b/app/views/users/deactivate.html.erb @@ -0,0 +1,47 @@ +<% page_title "Deactivate Account" %> +<%= render "secondary_links" %> + +

+
+ <% if @user == CurrentUser.user %> +

Deactivate Account

+ <% else %> +

Deactivate Account: <%= link_to_user @user %>

+ <% end %> + +
+

+ You can deactivate your <%= Danbooru.config.app_name %> account by entering your password below. Deactivating + your account will do the following things: +

+ +
    +
  • Change your username to a generic username (user_<%= @user.id %>).
  • +
  • Delete your password, email address, and account settings.
  • +
  • Delete your favorites.
  • +
  • Delete your saved searches.
  • +
+ +

+ The following things will not be deleted: +

+ +
    +
  • Posts you've uploaded.
  • +
  • Your comments, forum posts, and private messages.
  • +
  • Your tag edits, wiki edits, translation notes, and any other contributions you've made to the site.
  • +
  • Your login history, including your IP address and geographic location. This is kept for moderation purposes.
  • +
+ +

+ Enter your password below to deactivate your account. This cannot be + undone. Your account cannot be recovered after it is deactivated. +

+
+ + <%= edit_form_for(:user, url: user_path(@user), method: :delete) do |f| %> + <%= f.input :password %> + <%= f.submit "Deactivate account", "data-confirm": "Are you sure you want to deactivate your account? This cannot be undone" %> + <% end %> +
+
diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index 33eb21260..875c4b7ab 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb @@ -53,7 +53,7 @@

- <%= link_to "Deactivate account", maintenance_user_deletion_path, id: "delete-account" %> + <%= link_to "Deactivate account", deactivate_user_path(@user), id: "delete-account" %> (requires confirmation)

diff --git a/config/routes.rb b/config/routes.rb index 8ffb5d8e3..f85bc97be 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -50,7 +50,6 @@ Rails.application.routes.draw do namespace :user do resource :count_fixes, only: [:new, :create] resource :email_notification, only: [:show, :create, :destroy] - resource :deletion, :only => [:show, :destroy] end end @@ -274,6 +273,8 @@ Rails.application.routes.draw do get :change_name, on: :member, to: "user_name_change_requests#new" get :custom_style, on: :collection + get :deactivate, on: :member # /users/:id/deactivate + get :deactivate, on: :collection # /users/deactivate end get "/upgrade", to: "user_upgrades#new", as: "new_user_upgrade" get "/user_upgrades/new", to: redirect("/upgrade") @@ -354,6 +355,7 @@ Rails.application.routes.draw do get "/static/contact", to: redirect("/contact") get "/user_upgrade/new", to: redirect("/upgrade") get "/delayed_jobs", to: redirect("/jobs") + get "/maintenance/user/deletion", to: redirect("/users/deactivate") get "/mock/recommender/recommend/:user_id" => "mock_services#recommender_recommend", as: "mock_recommender_recommend" get "/mock/recommender/similiar/:post_id" => "mock_services#recommender_similar", as: "mock_recommender_similar" diff --git a/test/functional/maintenance/user/deletions_controller_test.rb b/test/functional/maintenance/user/deletions_controller_test.rb deleted file mode 100644 index 07fab37c3..000000000 --- a/test/functional/maintenance/user/deletions_controller_test.rb +++ /dev/null @@ -1,42 +0,0 @@ -require "test_helper" - -module Maintenance - module User - class DeletionsControllerTest < ActionDispatch::IntegrationTest - context "in all cases" do - setup do - @user = create(:user) - end - - context "#show" do - should "render" do - get_auth maintenance_user_deletion_path, @user - assert_response :success - end - end - - context "#destroy" do - should "delete the user when given the correct password" do - delete_auth maintenance_user_deletion_path, @user, params: { user: { password: "password" }} - - assert_redirected_to posts_path - assert_equal(true, @user.reload.is_deleted?) - assert_equal("Your account has been deactivated", flash[:notice]) - assert_nil(session[:user_id]) - assert_equal(true, @user.user_events.user_deletion.exists?) - end - - should "not delete the user when given an incorrect password" do - delete_auth maintenance_user_deletion_path, @user, params: { user: { password: "hunter2" }} - - assert_redirected_to maintenance_user_deletion_path - assert_equal(false, @user.reload.is_deleted?) - assert_equal("Password is incorrect", flash[:notice]) - assert_equal(@user.id, session[:user_id]) - assert_equal(false, @user.user_events.user_deletion.exists?) - end - end - end - end - end -end diff --git a/test/functional/users_controller_test.rb b/test/functional/users_controller_test.rb index 05238427f..df3a3df97 100644 --- a/test/functional/users_controller_test.rb +++ b/test/functional/users_controller_test.rb @@ -102,6 +102,82 @@ class UsersControllerTest < ActionDispatch::IntegrationTest end end + context "#deactivate action" do + should "render /users/:id/deactivate for the current user" do + get_auth deactivate_user_path(@user), @user + assert_response :success + end + + should "render /users/:id/deactivate for the Owner user" do + get_auth deactivate_user_path(@user), create(:owner) + assert_response :success + end + + should "not render /users/:id/deactivate for a different user" do + get_auth deactivate_user_path(@user), create(:user) + assert_response 403 + end + + should "render /users/deactivate for a logged-in user" do + get_auth deactivate_users_path, @user + assert_response :success + end + + should "not render /users/deactivate for a logged-out user" do + get deactivate_users_path + assert_response 403 + end + + should "redirect /maintenance/user/deletion to /users/deactivate" do + get "/maintenance/user/deletion" + assert_redirected_to deactivate_users_path + end + end + + context "#destroy action" do + should "delete the user when given the correct password" do + delete_auth user_path(@user), @user, params: { user: { password: "password" }} + + assert_redirected_to posts_path + assert_equal(true, @user.reload.is_deleted?) + assert_equal("Your account has been deactivated", flash[:notice]) + assert_nil(session[:user_id]) + assert_equal(true, @user.user_events.user_deletion.exists?) + end + + should "not delete the user when given an incorrect password" do + delete_auth user_path(@user), @user, params: { user: { password: "hunter2" }} + + assert_redirected_to deactivate_user_path(@user) + assert_equal(false, @user.reload.is_deleted?) + assert_equal("Password is incorrect", flash[:notice]) + assert_equal(@user.id, session[:user_id]) + assert_equal(false, @user.user_events.user_deletion.exists?) + end + + should "allow the Owner to delete other users" do + delete_auth user_path(@user), create(:owner) + + assert_redirected_to posts_path + assert_equal(true, @user.reload.is_deleted?) + assert_equal("Your account has been deactivated", flash[:notice]) + assert_nil(session[:user_id]) + assert_equal(true, @user.user_events.user_deletion.exists?) + end + + should "not allow users to delete other users" do + delete_auth user_path(@user), create(:user), params: { user: { password: "password" }} + + assert_response 403 + end + + should "not allow logged-out users to delete other users" do + delete user_path(@user), params: { user: { password: "password" }} + + assert_response 403 + end + end + context "custom_style action" do should "work" do @user.update!(custom_style: "span { color: red; }")