Allow users to delete their own accounts

This PR allows users to delete their own accounts. The logic implemented matches
that currently used by the admins when they manually close accounts, although
there is room to be more complex in future e.g. completely removing accounts
with no content.

The error handling has been slightly adapted for namespaced controllers, by
anchoring the controller name with a leading forward slash.
This commit is contained in:
Andy Allan 2021-12-09 16:12:42 +00:00
parent af273f5d6a
commit 6c1d73a509
10 changed files with 142 additions and 5 deletions

View file

@ -36,13 +36,14 @@ class Ability
if user
can :welcome, :site
can [:revoke, :authorize], :oauth
can [:show], :deletion
if Settings.status != "database_offline"
can [:index, :new, :create, :show, :edit, :update, :destroy], ClientApplication
can [:index, :new, :create, :show, :edit, :update, :destroy], :oauth2_application
can [:index, :destroy], :oauth2_authorized_application
can [:new, :show, :create, :destroy], :oauth2_authorization
can [:edit, :update], :account
can [:edit, :update, :destroy], :account
can [:show], :dashboard
can [:new, :create, :edit, :update, :comment, :subscribe, :unsubscribe], DiaryEntry
can [:make_friend, :remove_friend], Friendship

View file

@ -0,0 +1,12 @@
module Account
class DeletionsController < ApplicationController
layout "site"
before_action :authorize_web
before_action :set_locale
authorize_resource :class => false
def show; end
end
end

View file

@ -51,4 +51,14 @@ class AccountsController < ApplicationController
redirect_to auth_url(params[:user][:auth_provider], params[:user][:auth_uid]), :status => :temporary_redirect
end
end
def destroy
current_user.soft_destroy!
session.delete(:user)
session_expires_automatically
flash[:notice] = t ".success"
redirect_to root_path
end
end

View file

@ -349,7 +349,7 @@ class ApplicationController < ActionController::Base
elsif current_user
set_locale
respond_to do |format|
format.html { redirect_to :controller => "errors", :action => "forbidden" }
format.html { redirect_to :controller => "/errors", :action => "forbidden" }
format.any { report_error t("application.permission_denied"), :forbidden }
end
elsif request.get?

View file

@ -0,0 +1,38 @@
<% content_for :heading do %>
<h1><%= t ".title" %></h1>
<% end %>
<%= render :partial => "settings_menu" %>
<div class="alert alert-danger row mx-0 p-3 align-items-center">
<div class="col-auto">
<picture>
<source srcset="<%= image_path "notice.svg" %>" type="image/svg+xml"></source>
<%= image_tag("notice.png", :srcset => image_path("notice.svg")) %>
</picture>
</div>
<div class="col">
<p class="mb-0"><%= t ".warning" %></p>
</div>
</div>
<p><%= t ".delete_introduction" %></p>
<ul>
<li><%= t ".delete_profile" %></li>
<li><%= t ".delete_display_name" %></li>
</ul>
<p><%= t ".retain_caveats" %></p>
<ul>
<li><%= t ".retain_edits" %></li>
<li><%= t ".retain_traces" %></li>
<li><%= t ".retain_diary_entries" %></li>
<li><%= t ".retain_notes" %></li>
<li><%= t ".retain_changeset_discussions" %></li>
<li><%= t ".retain_email" %></li>
</ul>
<%= link_to t(".delete_account"), account_path, { :method => :delete, :class => "btn btn-danger", :data => { :confirm => t(".confirm_delete") } } %>
<%= link_to t(".cancel"), edit_account_path, :class => "btn btn-link" %>

View file

@ -54,7 +54,14 @@
</span>
</div>
<%= f.primary t(".save changes button") %>
<div class="row justify-content-between">
<div class="col-auto btn-wrapper">
<%= f.primary t(".save changes button") %>
</div>
<div class="col-auto btn-wrapper">
<%= link_to t(".delete_account"), account_deletion_path, :class => "btn btn-outline-danger" %>
</div>
</div>
<% end %>
<% unless current_user.data_public? %>

View file

@ -3,7 +3,7 @@
<% content_for :heading do %>
<ul class="nav nav-tabs flex-column flex-sm-row">
<li class="nav-item">
<%= link_to t(".account_settings"), edit_account_path, :class => "nav-link #{'active' if controller_name == 'accounts'}" %>
<%= link_to t(".account_settings"), edit_account_path, :class => "nav-link #{'active' if %w[accounts deletions].include?(controller_name)}" %>
</li>
<li class="nav-item">
<%= link_to t(".oauth1_settings"), oauth_clients_path(current_user), :class => "nav-link #{'active' if controller_name == 'oauth_clients'}" %>