Skip to content

Commit 298bede

Browse files
author
Irene
committed
Add deleting user
Requesting deletion sends a confirmation email. Clicking the link redirects to a site with some warnings and the final destroy button. Admins can delete any accounts, ordinary users can destroy their own account.
1 parent c148a3d commit 298bede

File tree

10 files changed

+107
-4
lines changed

10 files changed

+107
-4
lines changed

app/controllers/application_controller.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,15 @@ class ApplicationController < ActionController::Base
2121
include BreadcrumbHelpers
2222
include EmbeddableHelper
2323
include AuthorizeCollectionHelper
24+
include ApplicationHelper
2425
check_authorization
2526

2627
rescue_from CanCan::AccessDenied do |_exception|
27-
respond_access_denied
28+
if current_user.guest?
29+
redirect_to(login_path(return_to: return_to_link))
30+
else
31+
respond_access_denied
32+
end
2833
end
2934

3035
rescue_from ActiveRecord::RecordNotFound do |exception|

app/controllers/users_controller.rb

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,40 @@ def confirm_email
8585
end
8686

8787
def send_verification_email
88-
user = User.find(params[:user_id])
89-
raise 'Access denied' if user != current_user && !current_user.admin?
88+
user = authenticate_current_user
9089
raise 'Already verified' if user.email_verified?
9190
UserMailer.email_confirmation(user).deliver_now
9291
redirect_to root_path, notice: "Verification email sent to #{user.email}."
9392
end
9493

94+
def verify_destroying_user
95+
@user = authenticate_current_user
96+
token = VerificationToken.delete_user.find_by!(user: @user, token: params[:id])
97+
end
98+
99+
def destroy_user
100+
user = authenticate_current_user
101+
token = VerificationToken.delete_user.find_by!(user: user, token: params[:id])
102+
username = user.login
103+
sign_out if current_user == user
104+
user.destroy
105+
redirect_to root_url, notice: "The account #{username} has been permanently destroyed."
106+
end
107+
108+
def send_destroy_email
109+
user = authenticate_current_user
110+
UserMailer.destroy_confirmation(user).deliver_now
111+
redirect_to root_path, notice: "Verification email sent to #{user.email}."
112+
end
113+
95114
private
96115

116+
def authenticate_current_user
117+
user = User.find(params[:user_id])
118+
authorize! :destroy, user
119+
user
120+
end
121+
97122
def set_email
98123
user_params = params[:user]
99124

app/mailers/user_mailer.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ def email_confirmation(user)
66
mail(from: SiteSetting.value('emails')['from'], to: user.email, subject: "Confirm your TestMyCode Account email address")
77
end
88

9+
def destroy_confirmation(user)
10+
@user = user
11+
token = user.verification_tokens.delete_user.create!
12+
@url = base_url + verify_destroying_user_path(@user.id, token.token)
13+
mail(from: SiteSetting.value('emails')['from'], to: user.email, subject: "Confirm deleting your TestMyCode account")
14+
end
15+
916

1017
private
1118

app/models/ability.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ def initialize(user)
3737
end
3838

3939
can :create, User if SiteSetting.value(:enable_signup)
40+
cannot :destroy, User
41+
can :destroy, User do |u|
42+
user.administrator? ||
43+
u == user
44+
end
4045

4146
cannot :read, Course
4247
can :read, Course do |c|

app/models/verification_token.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class VerificationToken < ActiveRecord::Base
44

55
belongs_to :user
66

7-
enum type: [:email]
7+
enum type: [:email, :delete_user]
88

99
validates :type, presence: true
1010
validates :user, presence: true
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5+
</head>
6+
<body>
7+
<p>Hello!</p>
8+
9+
<p>You have requested deleting your TestMyCode account "<%= @user.login %>".</p>
10+
11+
<p>Please proceed to the following link to continue the deletion process.</p>
12+
13+
<a href="<%= @url %>"><%= @url %></a>
14+
15+
<p>If you didn't request deleting your account, just ignore this message.</p>
16+
</body>
17+
</html>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Hello!
2+
3+
You have requested deleting your TestMyCode account "<%= @user.login %>".
4+
5+
Please proceed to the following link to continue the deletion process.
6+
7+
<%= @url %>
8+
9+
If you didn't request deleting your account, just ignore this message.

app/views/users/show.html.erb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
<h1><%= @user.login %></h1>
44

55
<%= render :partial => 'users/form', :user => @user %>
6+
7+
<%= button_to 'Request deleting account', send_destroy_email_path(@user.id), method: :post, class: 'btn btn-danger' %>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<h1>Deleting the account <%= @user.login %></h1>
2+
3+
<div class="alert alert-danger">
4+
Deleting your account will have the following consequences:
5+
<ul>
6+
<li>You will lose all your acquired exercise points. We will not be able to recover them.</li>
7+
<li>You will not be able to receive a grade from any TestMyCode course.</li>
8+
<li>We will not be able to verify the authencity of any certificates that you have generated.</li>
9+
<ul>
10+
</div>
11+
12+
<p><strong>Pressing the button below will permanently destroy your TestMyCode account.</strong></p>
13+
14+
<%= form_tag(destroy_user_path, method: :delete, class: 'form-horizontal') do %>
15+
<div class="form-group">
16+
<%= check_box_tag :im_sure %>
17+
<%= label_tag "I've read the above and I'm sure I understand the consequences", nil, class: "control-label", for: :im_sure %>
18+
</div>
19+
<%= submit_tag("Destroy my account permanently", class: "btn btn-danger", data: { confirm: "Are you sure you want to delete the account #{@user.login}?"}, disabled: "disabled", id: :destroy_button) %>
20+
<% end %>
21+
22+
23+
<script>
24+
var checkBox = document.getElementById('im_sure')
25+
var destroyButton = document.getElementById('destroy_button')
26+
checkBox.addEventListener("click", function() {
27+
destroyButton.disabled = !checkBox.checked
28+
})
29+
</script>

config/routes.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@
230230
get '/users/:user_id/verify/:id', to: 'users#confirm_email', as: 'confirm_email'
231231
post '/users/:user_id/send_verification_email', to: 'users#send_verification_email', as: 'send_verification_email'
232232

233+
post '/users/:user_id/send_destroy_email', to: 'users#send_destroy_email', as: 'send_destroy_email'
234+
get '/users/:user_id/destroy/:id', to: 'users#verify_destroying_user', as: 'verify_destroying_user'
235+
delete '/users/:user_id/destroy/:id/destroy_user', to: 'users#destroy_user', as: 'destroy_user'
236+
233237
resources :certificates, only: [:show, :create]
234238

235239
resources :emails, only: [:index]

0 commit comments

Comments
 (0)