diff --git a/app/controllers/web/account/profiles_controller.rb b/app/controllers/web/account/profiles_controller.rb index 83dd0f63..938ed986 100644 --- a/app/controllers/web/account/profiles_controller.rb +++ b/app/controllers/web/account/profiles_controller.rb @@ -18,6 +18,16 @@ def update end end + def destroy + UserService.remove!(current_user) + sign_out + f(:success) + redirect_to root_path + rescue StandardError + f(:error) + redirect_to edit_account_profile_path + end + private def profile_params diff --git a/app/controllers/web/users_controller.rb b/app/controllers/web/users_controller.rb index f3e1f8ca..06bdf982 100644 --- a/app/controllers/web/users_controller.rb +++ b/app/controllers/web/users_controller.rb @@ -13,7 +13,7 @@ def index end def show - @user = User.find(params[:id]) + @user = User.permitted.find(params[:id]) @user_resume_answers = @user.resume_answers.web @user_resume_answers_likes_count = @user.resume_answers.sum('likes_count') @user_resumes = @user.resumes.web diff --git a/app/models/user.rb b/app/models/user.rb index c5ef54a3..2ec21527 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -51,7 +51,7 @@ class User < ApplicationRecord include UserRepository include UserPresenter - validates :email, 'valid_email_2/email': true + validates :email, 'valid_email_2/email': true, if: :email_required? # https://github.com/heartcombo/devise/wiki/How-To:-Add-an-Admin-Role enumerize :role, in: %i[user admin], default: :user, predicates: true, scope: true @@ -77,6 +77,7 @@ class User < ApplicationRecord aasm :state, column: :state do state :permitted, initial: true state :banned + state :removed event :ban do transitions from: %i[permitted], to: :banned @@ -85,6 +86,10 @@ class User < ApplicationRecord event :unban do transitions from: %i[banned], to: :permitted end + + event :remove do + transitions to: :removed + end end # https://github.com/heartcombo/devise/wiki/How-to:-Soft-delete-a-user-when-user-deletes-account @@ -144,6 +149,13 @@ def self.ransackable_associations(_auth_object = nil) %w[resumes careers career_members] end + protected + + # NOTE: override Devise method + def email_required? + !removed? + end + # NOTE: https://github.com/plataformatec/devise#activejob-integration # def send_devise_notification(notification, *args) # devise_mailer.send(notification, self, *args).deliver_later diff --git a/app/services/user_service.rb b/app/services/user_service.rb new file mode 100644 index 00000000..7a33f05b --- /dev/null +++ b/app/services/user_service.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class UserService + class << self + def remove!(user) + ActiveRecord::Base.transaction do + user.remove! + + user.email = nil + user.first_name = nil + user.last_name = nil + user.reset_password_token = nil + user.confirmation_token = nil + + user.save! + end + end + end +end diff --git a/app/views/web/account/profiles/edit.html.slim b/app/views/web/account/profiles/edit.html.slim index 31f246a5..ccc2966e 100644 --- a/app/views/web/account/profiles/edit.html.slim +++ b/app/views/web/account/profiles/edit.html.slim @@ -2,3 +2,6 @@ = t('.header') = render 'form', user: @user + +.mt-5 + = link_to t('.remove'), account_profile_path, class: 'btn btn-danger', method: :delete, data: { confirm: t('.confirm_remove') } diff --git a/config/locales/en.flash.yml b/config/locales/en.flash.yml index 7d6cad13..f5cf6654 100644 --- a/config/locales/en.flash.yml +++ b/config/locales/en.flash.yml @@ -8,6 +8,9 @@ en: profiles: update: success: Data updated + destroy: + success: Your account has been deleted + error: Failed to delete account. Please reach out to our support team via support@hexlet.io resumes: update: success: Resume updated diff --git a/config/locales/ru.flash.yml b/config/locales/ru.flash.yml index 6004be8d..aa42a04a 100644 --- a/config/locales/ru.flash.yml +++ b/config/locales/ru.flash.yml @@ -7,6 +7,9 @@ ru: update: success: Данные обновлены error: Не удалось обновить данные + destroy: + success: Ваш аккаунт удалён + error: Не удалось удалить аккаунт. Обратитесь в поддержку support@hexlet.io resumes: update: success: Резюме обновлено diff --git a/config/locales/ru.views.yml b/config/locales/ru.views.yml index dad1d853..4e2d81a4 100644 --- a/config/locales/ru.views.yml +++ b/config/locales/ru.views.yml @@ -346,6 +346,8 @@ ru: info_for_user: Давайте познакомимся =). Заполните, пожалуйста, фамилию, имя и можете рассказать немного о себе. edit: header: Настройки + remove: Удалить аккаунт + confirm_remove: Вы уверены, что хотите удалить свой аккаунт? show: header: Мой профиль edit_profile: Редактировать профиль diff --git a/config/routes.rb b/config/routes.rb index f1a5b418..9e724d16 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -76,7 +76,7 @@ resources :vacancies resources :notifications, only: %i[index update] resource :newsletters, only: %i[edit update] - resource :profile, only: %i[edit update] + resource :profile, only: %i[edit update destroy] scope module: :careers do resources :members, only: %i[index] end diff --git a/db/schema.rb b/db/schema.rb index b10723c5..67d671d1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -271,7 +271,7 @@ t.string "last_name" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.string "encrypted_password", default: "", null: false + t.string "encrypted_password" t.string "reset_password_token" t.datetime "reset_password_sent_at", precision: nil t.datetime "remember_created_at", precision: nil diff --git a/test/controllers/web/account/profiles_controller_test.rb b/test/controllers/web/account/profiles_controller_test.rb index a9ba74ae..21407935 100644 --- a/test/controllers/web/account/profiles_controller_test.rb +++ b/test/controllers/web/account/profiles_controller_test.rb @@ -48,4 +48,14 @@ class Web::Account::ProfilesControllerTest < ActionDispatch::IntegrationTest patch account_profile_path(user, locale: I18n.locale), params: { web_account_profile_form: attrs } assert_response :redirect end + + test 'destroy' do + delete account_profile_path + assert_response :redirect + + @user.reload + + assert { @user.removed? } + # TODO: add signed out checking + end end