Skip to content

Commit a4c6cc7

Browse files
author
Irene
committed
Add tests and password confirmation
Remove admin priviledge of verifying destroying an account. User also has to give the password of the removable account.
1 parent d2b7f6a commit a4c6cc7

File tree

8 files changed

+160
-20
lines changed

8 files changed

+160
-20
lines changed

app/controllers/users_controller.rb

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -85,40 +85,46 @@ def confirm_email
8585
end
8686

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

9495
def verify_destroying_user
95-
@user = authenticate_current_user
96+
@user = authenticate_current_user_destroy
9697
token = VerificationToken.delete_user.find_by!(user: @user, token: params[:id])
9798
end
9899

99100
def destroy_user
100-
im_sure = params[:id]
101+
im_sure = params[:im_sure]
101102
if im_sure != "1"
102103
redirect_to verify_destroying_user_url, notice: "Please check the checkbox after you have read the instructions."
103-
else
104-
user = authenticate_current_user
105-
token = VerificationToken.delete_user.find_by!(user: user, token: params[:id])
106-
username = user.login
107-
sign_out if current_user == user
108-
user.destroy
109-
redirect_to root_url, notice: "The account #{username} has been permanently destroyed."
104+
return
105+
end
106+
user = authenticate_current_user_destroy
107+
user_authentication = User.authenticate(user.login, params[:user][:password])
108+
if user_authentication.nil?
109+
redirect_to verify_destroying_user_url, { alert: "The password was incorrect." }
110+
return
110111
end
112+
token = VerificationToken.delete_user.find_by!(user: user, token: params[:id])
113+
username = user.login
114+
sign_out if current_user == user
115+
user.destroy
116+
redirect_to root_url, notice: "The account #{username} has been permanently destroyed."
111117
end
112118

113119
def send_destroy_email
114-
user = authenticate_current_user
120+
user = authenticate_current_user_destroy
115121
UserMailer.destroy_confirmation(user).deliver_now
116122
redirect_to root_path, notice: "Verification email sent to #{user.email}."
117123
end
118124

119125
private
120126

121-
def authenticate_current_user
127+
def authenticate_current_user_destroy
122128
user = User.find(params[:user_id])
123129
authorize! :destroy, user
124130
user

app/models/ability.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ def initialize(user)
3939
can :create, User if SiteSetting.value(:enable_signup)
4040
cannot :destroy, User
4141
can :destroy, User do |u|
42-
user.administrator? ||
4342
u == user
4443
end
4544

app/views/users/show.html.erb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@
44

55
<%= render :partial => 'users/form', :user => @user %>
66

7-
<%= button_to 'Request deleting account', send_destroy_email_path(@user.id), method: :post, class: 'btn btn-danger' %>
7+
<% if can? :destroy, @user %>
8+
<%= button_to 'Request deleting account', send_destroy_email_path(@user.id), method: :post, class: 'btn btn-danger' %>
9+
<% end %>

app/views/users/verify_destroying_user.html.erb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
<h1>Deleting the account <%= @user.login %></h1>
22

3-
<div class="alert alert-danger">
3+
<div class="jumbotron hero-unit-alert alert-danger">
44
Deleting your account will have the following consequences:
55
<ul>
66
<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>
7+
<li>You will not be able to receive a grade from any course that uses TestMyCode.</li>
88
<li>We will not be able to verify the authenticity of any certificates that you have generated.</li>
99
<ul>
1010
</div>
1111

12-
<p><strong>Pressing the button below will permanently destroy your TestMyCode account.</strong></p>
1312

1413
<%= form_tag(destroy_user_path, method: :delete, class: 'form-horizontal') do %>
1514
<div class="form-group">
1615
<%= check_box_tag :im_sure %>
1716
<%= label_tag "I've read the above and I'm sure I understand the consequences", nil, class: "control-label", for: :im_sure %>
1817
</div>
18+
<div class="form-group">
19+
<%= bs_labeled_field("Your password", password_field(:user, :password, :autocomplete => 'off', class: 'form-control')) %>
20+
</div>
21+
<p><strong>Pressing the button below will permanently destroy your TestMyCode account.</strong></p>
1922
<%= 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) %>
2023
<% end %>
2124

bin/spec_integration

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/bin/sh
22

3-
RSPEC_PATTERN="spec/integration/**/*.rb"
3+
RSPEC_PATTERN="spec/integration/destroying_user_spec.rb"
44
bundle exec rake spec SPEC_OPTS="--pattern $RSPEC_PATTERN --format documentation"

config/routes.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@
232232

233233
post '/users/:user_id/send_destroy_email', to: 'users#send_destroy_email', as: 'send_destroy_email'
234234
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'
235+
delete '/users/:user_id/destroy/:id', to: 'users#destroy_user', as: 'destroy_user'
236236

237237
resources :certificates, only: [:show, :create]
238238

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
require 'spec_helper'
2+
3+
describe "Deleting own user", type: :request, integration: true do
4+
include IntegrationTestActions
5+
6+
it 'sending email should generate token' do
7+
user = User.create!(login: 'user', password: 'password', email: '[email protected]')
8+
9+
visit '/'
10+
log_in_as('user', 'password')
11+
12+
visit '/user'
13+
14+
click_button 'Request deleting account'
15+
16+
# Yay, you got mail!
17+
18+
token = user.verification_tokens.delete_user[0]
19+
20+
expect(token.nil? == false)
21+
expect(User.find_by(login: user.login) == user)
22+
end
23+
24+
it 'verify destroy page should have a verification button and password field' do
25+
user = User.create!(login: 'user', password: 'password', email: '[email protected]')
26+
27+
visit '/'
28+
log_in_as('user', 'password')
29+
30+
visit '/user'
31+
32+
click_button 'Request deleting account'
33+
34+
# Yay, you got mail!
35+
36+
token = user.verification_tokens.delete_user[0]
37+
38+
visit"/users/#{user.id}/destroy/#{token.token}"
39+
40+
expect(page).to have_content("Deleting the account #{user.login}")
41+
42+
expect(page).to have_button('Destroy my account permanently', disabled: true)
43+
44+
check "I've read the above and i'm sure i understand the consequences"
45+
46+
expect(page).to have_button('Destroy my account permanently', disabled: false)
47+
expect(User.find_by(login: user.login) == user)
48+
expect(page).to have_content('Your password')
49+
end
50+
51+
it 'pressing verification button destroys user' do
52+
user = User.create!(login: 'user', password: 'password', email: '[email protected]')
53+
username = user.login
54+
55+
visit '/'
56+
log_in_as('user', 'password')
57+
58+
visit '/user'
59+
60+
click_button 'Request deleting account'
61+
62+
# Yay, you got mail!
63+
64+
token = user.verification_tokens.delete_user[0]
65+
66+
visit"/users/#{user.id}/destroy/#{token.token}"
67+
68+
check "I've read the above and i'm sure i understand the consequences"
69+
70+
fill_in 'user[password]', with: user.password
71+
72+
click_button 'Destroy my account permanently'
73+
74+
page.accept_alert
75+
76+
expect { User.find_by!(login: username) }.to raise_error ActiveRecord::RecordNotFound
77+
expect(page).to have_content("The account #{username} has been permanently destroyed")
78+
end
79+
80+
it 'will not destroy user if password incorrect' do
81+
user = User.create!(login: 'user', password: 'password', email: '[email protected]')
82+
83+
visit '/'
84+
log_in_as('user', 'password')
85+
86+
visit '/user'
87+
88+
click_button 'Request deleting account'
89+
90+
# Yay, you got mail!
91+
92+
token = user.verification_tokens.delete_user[0]
93+
94+
visit"/users/#{user.id}/destroy/#{token.token}"
95+
96+
check "I've read the above and i'm sure i understand the consequences"
97+
98+
fill_in 'user[password]', with: 'thisiswrongpassword'
99+
100+
click_button 'Destroy my account permanently'
101+
102+
page.accept_alert
103+
104+
expect(User.find_by(login: user.login) == user)
105+
expect(page).to have_content('The password was incorrect')
106+
end
107+
108+
it 'cannot be verified by another user' do
109+
user1 = User.create!(login: 'user1', password: 'password1', email: '[email protected]')
110+
user2 = User.create!(login: 'user2', password: 'password2', email: '[email protected]')
111+
112+
visit '/'
113+
log_in_as('user1', 'password1')
114+
115+
visit '/user'
116+
117+
click_button 'Request deleting account'
118+
119+
log_out
120+
121+
log_in_as('user2', 'password2')
122+
123+
token = user1.verification_tokens.delete_user[0]
124+
125+
visit "/users/#{user1.id}/destroy/#{token.token}"
126+
127+
expect(page).to have_content("Access denied")
128+
end
129+
130+
end

spec/support/integration_test_actions.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def log_in_as(username, password)
1515
end
1616

1717
def log_out
18-
click_link 'Sign out'
18+
visit '/logout'
1919
end
2020

2121
def create_new_course(options = {})

0 commit comments

Comments
 (0)