allow users to delete their own accounts

not much can actually be deleted, but it can be put into a deleted
state
This commit is contained in:
joshua stein 2014-01-13 10:12:17 -06:00
parent 1ef58d6496
commit e12d91cd43
13 changed files with 124 additions and 30 deletions

View file

@ -507,12 +507,12 @@ li .byline a {
color: #888; color: #888;
text-decoration: none; text-decoration: none;
} }
.new_user, span.new_user, a.new_user,
li .byline a.new_user { li .byline a.new_user {
color: green; color: green;
} }
.banned_user, span.inactive_user, a.inactive_user,
li .byline a.banned_user { li .byline a.inactive_user {
color: gray; color: gray;
text-decoration: line-through; text-decoration: line-through;
} }

View file

@ -10,7 +10,7 @@ class ApplicationController < ActionController::Base
def authenticate_user def authenticate_user
if session[:u] && if session[:u] &&
(user = User.where(:session_token => session[:u].to_s).first) && (user = User.where(:session_token => session[:u].to_s).first) &&
!user.is_banned? user.is_active?
@user = user @user = user
Rails.logger.info " Logged in as user #{@user.id} (#{@user.username})" Rails.logger.info " Logged in as user #{@user.id} (#{@user.username})"
end end

View file

@ -21,7 +21,7 @@ class LoginController < ApplicationController
user = User.where(:username => params[:email]).first user = User.where(:username => params[:email]).first
end end
if user && !user.is_banned? && if user && user.is_active? &&
user.try(:authenticate, params[:password].to_s) user.try(:authenticate, params[:password].to_s)
session[:u] = user.session_token session[:u] = user.session_token
return redirect_to "/" return redirect_to "/"
@ -70,7 +70,7 @@ class LoginController < ApplicationController
# this will get reset upon save # this will get reset upon save
@reset_user.session_token = nil @reset_user.session_token = nil
if @reset_user.save && !@reset_user.is_banned? if @reset_user.save && @reset_user.is_active?
session[:u] = @reset_user.session_token session[:u] = @reset_user.session_token
return redirect_to "/" return redirect_to "/"
end end

View file

@ -7,6 +7,18 @@ class SettingsController < ApplicationController
@edit_user = @user.dup @edit_user = @user.dup
end end
def delete_account
if @user.try(:authenticate, params[:user][:password].to_s)
@user.delete!
reset_session
flash[:success] = "Your account has been deleted."
return redirect_to "/"
end
flash[:error] = "Your password could not be verified."
return redirect_to settings_url
end
def update def update
@edit_user = @user.clone @edit_user = @user.clone

View file

@ -2,10 +2,11 @@ class StoriesController < ApplicationController
before_filter :require_logged_in_user_or_400, before_filter :require_logged_in_user_or_400,
:only => [ :upvote, :downvote, :unvote, :preview ] :only => [ :upvote, :downvote, :unvote, :preview ]
before_filter :require_logged_in_user, :only => [ :delete, :create, :edit, before_filter :require_logged_in_user, :only => [ :destroy, :create, :edit,
:fetch_url_title, :new ] :fetch_url_title, :new ]
before_filter :find_user_story, :only => [ :destroy, :edit, :undelete, :update ] before_filter :find_user_story, :only => [ :destroy, :edit, :undelete,
:update ]
def create def create
@title = "Submit Story" @title = "Submit Story"

View file

@ -18,6 +18,7 @@ class User < ActiveRecord::Base
:class_name => "User" :class_name => "User"
belongs_to :banned_by_user, belongs_to :banned_by_user,
:class_name => "User" :class_name => "User"
has_many :invitations
has_secure_password has_secure_password
@ -38,7 +39,7 @@ class User < ActiveRecord::Base
attr_accessible :username, :email, :password, :password_confirmation, attr_accessible :username, :email, :password, :password_confirmation,
:about, :email_replies, :pushover_replies, :pushover_user_key, :about, :email_replies, :pushover_replies, :pushover_user_key,
:pushover_device, :email_messages, :pushover_messages, :email_mentions, :pushover_device, :email_messages, :pushover_messages, :email_mentions,
:pushover_mentions, :mailing_list_enabled :pushover_mentions, :mailing_list_enabled, :delete_me
before_save :check_session_token before_save :check_session_token
before_validation :on => :create do before_validation :on => :create do
@ -80,10 +81,7 @@ class User < ActiveRecord::Base
self.banned_by_user_id = banner.id self.banned_by_user_id = banner.id
self.banned_reason = reason self.banned_reason = reason
self.session_token = nil self.delete!
self.check_session_token
self.save!
BanNotification.notify(self, banner, reason) BanNotification.notify(self, banner, reason)
@ -124,6 +122,29 @@ class User < ActiveRecord::Base
Keystore.value_for("user:#{self.id}:comments_posted").to_i Keystore.value_for("user:#{self.id}:comments_posted").to_i
end end
def delete!
User.transaction do
self.comments.each{|c| c.delete_for_user(self) }
self.sent_messages.each do |m|
m.deleted_by_author = true
m.save
end
self.received_messages.each do |m|
m.deleted_by_recipient = true
m.save
end
self.invitations.destroy_all
self.session_token = nil
self.check_session_token
self.deleted_at = Time.now
self.save!
end
end
def initiate_password_reset_for_ip(ip) def initiate_password_reset_for_ip(ip)
self.password_reset_token = Utils.random_str(40) self.password_reset_token = Utils.random_str(40)
self.save! self.save!
@ -131,6 +152,10 @@ class User < ActiveRecord::Base
PasswordReset.password_reset_link(self, ip).deliver PasswordReset.password_reset_link(self, ip).deliver
end end
def is_active?
!(deleted_at? || is_banned?)
end
def is_banned? def is_banned?
banned_at? banned_at?
end end

View file

@ -29,8 +29,8 @@ class="comment <%= comment.current_vote ? (comment.current_vote[:vote] == 1 ?
just now just now
<% else %> <% else %>
<a href="/u/<%= comment.user.username %>" <a href="/u/<%= comment.user.username %>"
<% if comment.user.is_banned? %> <% if !comment.user.is_active? %>
class="banned_user" class="inactive_user"
<% elsif comment.user.is_new? %> <% elsif comment.user.is_new? %>
class="new_user" class="new_user"
<% end %> <% end %>

View file

@ -165,6 +165,32 @@
<br> <br>
<br> <br>
<%= form_for @edit_user, :url => delete_account_url, :method => :post do |f| %>
<div class="legend">
Delete Account
</div>
<p>
To permanently delete your account, verify your current password below.
Your account will be put into a deleted state, your comments will be marked
as deleted and no longer readable by any other users, and your private
messages will be deleted. Your submitted stories will not be deleted.
Your username will remain reserved and will not be available to use on any
other account.
</p>
<div class="boxline">
<%= f.label :password, "Verify Password:", :class => "required" %>
<%= f.password_field :password, :size => 40, :autocomplete => "off" %>
</div>
<br>
<%= f.submit "Yes, Delete My Account" %>
<% end %>
<br>
<br>
<a name="invite"></a> <a name="invite"></a>
<div class="legend"> <div class="legend">
Invite a New User Invite a New User

View file

@ -1,19 +1,31 @@
<div class="box wide"> <div class="box wide">
<div class="legend"> <div class="legend">
<%= @showing_user.username %> <% if !@showing_user.is_active? %>
<span class="inactive_user">
<% elsif @showing_user.is_new? %>
<span class="new_user">
<% else %>
<span>
<% end %>
<%= @showing_user.username %>
</span>
<% if @user %> <% if @user %>
(<a href="/messages?to=<%= @showing_user.username %>">Send a Message</a>) (<a href="/messages?to=<%= @showing_user.username %>">Send a Message</a>)
<% end %> <% end %>
</div> </div>
<div id="gravatar"> <% if @showing_user.is_active? %>
<img src="<%= @showing_user.avatar_url %>"> <div id="gravatar">
</div> <img src="<%= @showing_user.avatar_url %>">
</div>
<% end %>
<label class="required">Status:</label> <label class="required">Status:</label>
<span class="d" <span class="d"
<%= @showing_user.is_banned? ? raw("style=\"color: red;\"") : "" %>> <%= @showing_user.is_banned? ? raw("style=\"color: red;\"") : "" %>>
<% if @showing_user.is_banned? %> <% if @showing_user.is_banned? %>
Banned
<% elsif !@showing_user.is_active? %>
Inactive Inactive
<% else %> <% else %>
Active Active
@ -47,6 +59,14 @@
<br> <br>
<% end %> <% end %>
<% if @showing_user.deleted_at? %>
<label class="required">Left:</label>
<span class="d">
<%= raw(time_ago_in_words_label(@showing_user.deleted_at)) %> ago
</span>
<br>
<% end %>
<label class="required">Karma:</label> <label class="required">Karma:</label>
<span class="d"> <span class="d">
<%= @showing_user.karma %>, averaging <%= <%= @showing_user.karma %>, averaging <%=
@ -75,13 +95,15 @@
</span> </span>
<br> <br>
<label class="required">About:</label> <% if @showing_user.is_active? %>
<label class="required">About:</label>
<div id="user_about" class="shorten_first_p"> <div id="user_about" class="shorten_first_p">
<% if @showing_user.about.present? %> <% if @showing_user.about.present? %>
<%= raw @showing_user.linkified_about %> <%= raw @showing_user.linkified_about %>
<% else %> <% else %>
<span class="na">A mystery...</span> <span class="na">A mystery...</span>
<% end %> <% end %>
</div> </div>
<% end %>
</div> </div>

View file

@ -10,8 +10,8 @@
<% if (user = subtree.pop) %> <% if (user = subtree.pop) %>
<li> <li>
<a href="/u/<%= user.username %>" <a href="/u/<%= user.username %>"
<% if user.is_banned? %> <% if !user.is_active? %>
class="banned_user" class="inactive_user"
<% elsif user.is_new? %> <% elsif user.is_new? %>
class="new_user" class="new_user"
<% end %> <% end %>

View file

@ -72,6 +72,8 @@ Lobsters::Application.routes.draw do
get "/settings" => "settings#index" get "/settings" => "settings#index"
post "/settings" => "settings#update" post "/settings" => "settings#update"
post "/settings/delete_account" => "settings#delete_account",
:as => "delete_account"
get "/filters" => "filters#index" get "/filters" => "filters#index"
post "/filters" => "filters#update" post "/filters" => "filters#update"

View file

@ -0,0 +1,5 @@
class AddAccountDeletion < ActiveRecord::Migration
def change
add_column :users, :deleted_at, :datetime
end
end

View file

@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20140112192936) do ActiveRecord::Schema.define(version: 20140113153413) do
create_table "comments", force: true do |t| create_table "comments", force: true do |t|
t.datetime "created_at", null: false t.datetime "created_at", null: false
@ -161,6 +161,7 @@ ActiveRecord::Schema.define(version: 20140112192936) do
t.datetime "banned_at" t.datetime "banned_at"
t.integer "banned_by_user_id" t.integer "banned_by_user_id"
t.string "banned_reason", limit: 200 t.string "banned_reason", limit: 200
t.datetime "deleted_at"
end end
add_index "users", ["mailing_list_enabled"], name: "mailing_list_enabled", using: :btree add_index "users", ["mailing_list_enabled"], name: "mailing_list_enabled", using: :btree