Merge pull request #621 from AyuntamientoMadrid/erase-account

Erase account
This commit is contained in:
Raimond Garcia
2015-10-20 13:52:40 +02:00
18 changed files with 154 additions and 18 deletions

View File

@@ -199,7 +199,7 @@ body.admin {
font-size: rem-calc(12);
&:hover, &:active, &:focus {
border: 0;
border-bottom: 1px dotted white;
color: #cf2a0e;
}
}

View File

@@ -886,12 +886,6 @@ footer {
font-weight: bolder;
}
}
form {
.button {
margin-top: rem-calc(24);
}
}
}
// 08. Forms

View File

@@ -10,6 +10,16 @@ class Users::RegistrationsController < Devise::RegistrationsController
end
end
def delete_form
build_resource({})
end
def delete
current_user.erase(erase_params[:erase_reason])
sign_out
redirect_to root_url, notice: t("devise.registrations.destroyed")
end
def success
end
@@ -32,6 +42,10 @@ class Users::RegistrationsController < Devise::RegistrationsController
params.require(:user).permit(:username, :email, :password, :password_confirmation, :captcha, :captcha_key, :terms_of_service)
end
def erase_params
params.require(:user).permit(:erase_reason)
end
def after_inactive_sign_up_path_for(resource_or_scope)
users_sign_up_success_path
end

View File

@@ -23,9 +23,10 @@ class User < ActiveRecord::Base
has_many :comments, -> { with_hidden }
has_many :failed_census_calls
validates :username, presence: true, unless: :organization?
validates :username, uniqueness: true, unless: :organization?
validates :username, presence: true, if: :username_required?
validates :username, uniqueness: true, if: :username_required?
validates :document_number, uniqueness: { scope: :document_type }, allow_nil: true
validate :validate_username_length
validates :official_level, inclusion: {in: 0..5}
@@ -145,6 +146,21 @@ class User < ActiveRecord::Base
Proposal.hide_all proposal_ids
end
def erase(erase_reason = nil)
self.hide
self.update(
erase_reason: erase_reason,
username: nil,
email: nil,
unconfirmed_email: nil,
document_number: nil,
phone_number: nil,
encrypted_password: "",
confirmation_token: nil,
reset_password_token: nil,
email_verification_token: nil
)
end
def email_provided?
!!(email && email !~ OMNIAUTH_EMAIL_REGEX) ||
@@ -172,8 +188,15 @@ class User < ActiveRecord::Base
super
end
private
def username_required?
!organization? && !hidden?
end
def email_required?
!hidden?
end
private
def clean_document_number
self.document_number = self.document_number.gsub(/[^a-z0-9]+/i, "").upcase unless self.document_number.blank?
end

View File

@@ -1,6 +1,10 @@
<div class="row account">
<div class="small-12 column">
<%= link_to t("account.show.change_credentials_link"), edit_user_registration_path, class: "button radius small secondary right" %>
<div class="right text-right">
<%= link_to t("account.show.change_credentials_link"), edit_user_registration_path, class: "button radius small secondary" %>
<br>
<%= link_to t("account.show.erase_account_link"), users_registrations_delete_form_path, class: "delete" %>
</div>
<%= avatar_image(@account, seed: @account.id, size: 60) %>

View File

@@ -13,6 +13,7 @@
<%= link_to t("debates.debate.comments", count: debate.comments_count), debate_path(debate, anchor: "comments") %>
<span class="bullet">&nbsp;&bull;&nbsp;</span>
<%= l debate.created_at.to_date %>
<% if debate.author.hidden? %>
<span class="bullet">&nbsp;&bull;&nbsp;</span>
<span class="author">
@@ -37,6 +38,7 @@
<%= t("shared.collective") %>
</span>
<% end %>
</p>
<div class="debate-description">
<%= link_to debate.description, debate %>

View File

@@ -0,0 +1,23 @@
<i class="icon-angle-left left"></i>&nbsp;<%= link_to t("devise_views.users.registrations.edit.back_link"), :back, class: "left back" %>
<h1><%= t("devise_views.users.registrations.delete_form.title") %></h1>
<%= form_for(resource, as: resource_name,
url: users_registrations_path,
html: { method: :delete }) do |f| %>
<%= devise_error_messages! %>
<div class="alert-box alert radius margin-top">
<%= t("devise_views.users.registrations.delete_form.info") %>
</div>
<p>
<%= t("devise_views.users.registrations.delete_form.info_reason") %>
</p>
<%= f.text_field :erase_reason,
autofocus: true,
placeholder: t("devise_views.users.registrations.delete_form.erase_reason_label"),
label: t("devise_views.users.registrations.delete_form.erase_reason_label") %>
<%= f.submit t("devise_views.users.registrations.delete_form.submit"), class: "button radius alert expand" %>
<% end %>

View File

@@ -96,6 +96,7 @@ ignore_missing:
- 'unauthorized.*'
- 'errors.messages.blank'
- 'errors.messages.taken'
- 'devise.registrations.destroyed'
## Consider these keys used:
ignore_unused:

View File

@@ -77,6 +77,12 @@ en:
instructions_1_html: "Please <b>review your email inbox</b> - we have sent you a <b>link to confirm your account</b>."
instructions_2_html: "Once you click that link, you will be able to start participating"
back_to_index: "Understood, take me back to the home page"
delete_form:
title: "Erase account"
info: "This action can not be undone. Please make sure this is what you want."
info_reason: "If you want, leave us a reason (optional)"
erase_reason_label: "Reason"
submit: "Erase my account"
organizations:
registrations:
new:

View File

@@ -77,6 +77,12 @@ es:
instructions_1_html: "Por favor <b>revisa tu correo electrónico</b> - te hemos enviado un <b>enlace para confirmar tu cuenta</b>."
instructions_2_html: "Una vez confirmado, podrás empezar a participar."
back_to_index: "Entendido, volver a la página principal"
delete_form:
title: "Darme de baja"
info: "Esta acción no se puede deshacer. Una vez que des de baja tu cuenta, no podrás volver a hacer login con ella."
info_reason: "Si quieres, escribe el motivo por el que te das de baja (opcional)."
erase_reason_label: "Razón de la baja"
submit: "Borrar mi cuenta"
organizations:
registrations:
new:

View File

@@ -282,6 +282,7 @@ en:
change_credentials_link: "Change my credentials"
email_on_comment_label: "Receive email when someone comments on my debates or proposals"
email_on_comment_reply_label: "Receive email when someone replies to my comments"
erase_account_link: "Erase my account"
personal: "Personal data"
username_label: "Username"
phone_number_label: "Phone number"

View File

@@ -282,6 +282,7 @@ es:
change_credentials_link: "Cambiar mis datos de acceso"
email_on_comment_label: "Recibir un email cuando alguien comenta en mis propuestas o debates"
email_on_comment_reply_label: "Recibir un email cuando alguien contesta a mis comentarios"
erase_account_link: "Darme de baja"
personal: "Datos personales"
username_label: "Nombre de usuario"
phone_number_label: "Teléfono"

View File

@@ -1,9 +1,5 @@
Rails.application.routes.draw do
as :user do
match '/user/confirmation' => 'users/confirmations#update', :via => :patch, :as => :update_user_confirmation
end
devise_for :users, controllers: {
registrations: 'users/registrations',
sessions: 'users/sessions',
@@ -22,7 +18,11 @@ Rails.application.routes.draw do
end
devise_scope :user do
patch '/user/confirmation', to: 'users/confirmations#update', as: :update_user_confirmation
get 'users/sign_up/success', to: 'users/registrations#success'
get 'users/registrations/delete_form', to: 'users/registrations#delete_form'
delete 'users/registrations', to: 'users/registrations#delete'
get :finish_signup, to: 'users/registrations#finish_signup'
patch :do_finish_signup, to: 'users/registrations#do_finish_signup'
end
@@ -60,7 +60,9 @@ Rails.application.routes.draw do
end
end
resource :account, controller: "account", only: [:show, :update]
resource :account, controller: "account", only: [:show, :update, :delete] do
collection { get :erase }
end
resource :verification, controller: "verification", only: [:show]
scope module: :verification do

View File

@@ -0,0 +1,5 @@
class AddEraseReasonToUsers < ActiveRecord::Migration
def change
add_column :users, :erase_reason, :string
end
end

View File

@@ -0,0 +1,5 @@
class RemoveUserConstraints < ActiveRecord::Migration
def change
change_column(:users, :email, :string, null: true, unique: true)
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20151015135154) do
ActiveRecord::Schema.define(version: 20151019133719) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -257,7 +257,7 @@ ActiveRecord::Schema.define(version: 20151015135154) do
add_index "tags", ["proposals_count"], name: "index_tags_on_proposals_count", using: :btree
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "email", default: ""
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
@@ -294,6 +294,7 @@ ActiveRecord::Schema.define(version: 20151015135154) do
t.string "letter_verification_code"
t.integer "failed_census_calls_count", default: 0
t.datetime "level_two_verified_at"
t.string "erase_reason"
end
add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree

View File

@@ -81,4 +81,20 @@ feature 'Account' do
expect(page).to have_content error_message
end
scenario 'Erasing account' do
visit account_path
click_link 'Erase my account'
fill_in 'user_erase_reason', with: 'a test'
click_button 'Erase my account'
expect(page).to have_content "Your account has been successfully cancelled"
login_through_form_as(@user)
expect(page).to have_content "Invalid email or password"
end
end

View File

@@ -302,4 +302,36 @@ describe User do
end
describe "#erase" do
it "anonymizes a user and marks him as hidden" do
user = create(:user,
username: "manolo",
unconfirmed_email: "a@a.com",
document_number: "1234",
phone_number: "5678",
encrypted_password: "foobar",
confirmation_token: "token1",
reset_password_token: "token2",
email_verification_token: "token3")
user.erase('a test')
user.reload
expect(user.erase_reason).to eq('a test')
expect(user.hidden_at).to be
expect(user.username).to be_nil
expect(user.email).to be_nil
expect(user.unconfirmed_email).to be_nil
expect(user.document_number).to be_nil
expect(user.phone_number).to be_nil
expect(user.encrypted_password).to be_empty
expect(user.confirmation_token).to be_nil
expect(user.reset_password_token).to be_nil
expect(user.email_verification_token).to be_nil
end
end
end