Delete User Functionality (#1615)
* add full delete route and update banisher * add user deletion spec * enhance styling * remove availability if banned from mentorship * add specs * do not show banned mentors * delete addiional associations * include more associations for deletion * simplify activity deletion wtih delete_all
This commit is contained in:
parent
ec2ce5d6e6
commit
0eb5402926
7 changed files with 248 additions and 120 deletions
|
|
@ -32,7 +32,7 @@ class Internal::UsersController < Internal::ApplicationController
|
|||
@new_mentor = user_params[:add_mentor]
|
||||
ban_from_mentorship
|
||||
make_matches
|
||||
warn_or_ban_user
|
||||
update_role
|
||||
add_note
|
||||
@user.update!(user_params)
|
||||
if user_params[:quick_match]
|
||||
|
|
@ -42,17 +42,26 @@ class Internal::UsersController < Internal::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def warn_or_ban_user
|
||||
if user_params[:ban_user] == "1"
|
||||
@user.add_role :banned
|
||||
create_note("banned", user_params[:note_for_current_role])
|
||||
elsif user_params[:warn_user] == "1"
|
||||
@user.add_role :warned
|
||||
create_note("warned", user_params[:note_for_current_role])
|
||||
elsif user_params[:good_standing_user] == "1"
|
||||
@user.remove_role :warned
|
||||
create_note("good_standing", user_params[:note_for_current_role])
|
||||
end
|
||||
def update_role
|
||||
ban_user if user_params[:ban_user] == "1"
|
||||
warn_user if user_params[:warn_user] == "1"
|
||||
return_to_good_standing if user_params[:good_standing_user] == "1"
|
||||
end
|
||||
|
||||
def return_to_good_standing
|
||||
@user.remove_role :banned if @user.banned
|
||||
@user.remove_role :warned if @user.warned
|
||||
create_note("good_standing", user_params[:note_for_current_role])
|
||||
end
|
||||
|
||||
def ban_user
|
||||
@user.add_role :banned
|
||||
create_note("banned", user_params[:note_for_current_role])
|
||||
end
|
||||
|
||||
def warn_user
|
||||
@user.add_role :warned
|
||||
create_note("warned", user_params[:note_for_current_role])
|
||||
end
|
||||
|
||||
def add_note
|
||||
|
|
@ -97,6 +106,7 @@ class Internal::UsersController < Internal::ApplicationController
|
|||
mentor_relationships = MentorRelationship.where(mentee_id: @user.id)
|
||||
deactivate_mentorship(mentee_relationships)
|
||||
deactivate_mentorship(mentor_relationships)
|
||||
@user.update(offering_mentorship: false, seeking_mentorship: false)
|
||||
create_note("banned_from_mentorship", user_params[:note_for_mentorship_ban])
|
||||
end
|
||||
|
||||
|
|
@ -109,13 +119,25 @@ class Internal::UsersController < Internal::ApplicationController
|
|||
def banish
|
||||
@user = User.find(params[:id])
|
||||
begin
|
||||
Moderator::Banisher.call(admin: current_user, offender: @user)
|
||||
Moderator::Banisher.call_banish(admin: current_user, offender: @user)
|
||||
rescue StandardError => e
|
||||
flash[:error] = e.message
|
||||
end
|
||||
redirect_to "/internal/users/#{@user.id}/edit"
|
||||
end
|
||||
|
||||
def full_delete
|
||||
@user = User.find(params[:id])
|
||||
username = @user.username
|
||||
begin
|
||||
Moderator::Banisher.call_delete_activity(admin: current_user, offender: @user)
|
||||
flash[:notice] = "@" + username + " has been fully deleted. If this is a GDPR delete, remember to delete them from Mailchimp and Google Analytics."
|
||||
rescue StandardError => e
|
||||
flash[:error] = e.message
|
||||
end
|
||||
redirect_to "/internal/users"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user_params
|
||||
|
|
|
|||
|
|
@ -2,10 +2,14 @@ module Moderator
|
|||
class Banisher
|
||||
attr_reader :user, :admin
|
||||
|
||||
def self.call(admin:, offender:)
|
||||
def self.call_banish(admin:, offender:)
|
||||
new(offender: offender, admin: admin).banish
|
||||
end
|
||||
|
||||
def self.call_delete_activity(admin:, offender:)
|
||||
new(offender: offender, admin: admin).full_delete
|
||||
end
|
||||
|
||||
def initialize(admin:, offender:)
|
||||
@user = offender
|
||||
@admin = admin
|
||||
|
|
@ -39,29 +43,23 @@ module Moderator
|
|||
end
|
||||
end
|
||||
|
||||
def delete_reactions
|
||||
user.reactions.find_each(&:delete)
|
||||
end
|
||||
|
||||
def delete_comments
|
||||
return unless user.comments.count.positive?
|
||||
return unless user.comments.any?
|
||||
|
||||
user.comments.find_each do |comment|
|
||||
comment.reactions.find_each(&:delete)
|
||||
comment.reactions.delete_all
|
||||
CacheBuster.new.bust_comment(comment.commentable, user.username)
|
||||
comment.delete
|
||||
end
|
||||
end
|
||||
|
||||
def delete_follows
|
||||
user.follows.find_each(&:delete)
|
||||
end
|
||||
|
||||
def delete_articles
|
||||
return unless user.articles.any?
|
||||
|
||||
user.articles.find_each do |article|
|
||||
article.reactions.find_each(&:delete)
|
||||
article.reactions.delete_all
|
||||
article.comments.find_each do |comment|
|
||||
comment.reactions.find_each(&:delete)
|
||||
comment.reactions.delete_all
|
||||
CacheBuster.new.bust_comment(comment.commentable, comment.user.username)
|
||||
comment.delete
|
||||
end
|
||||
|
|
@ -71,15 +69,30 @@ module Moderator
|
|||
end
|
||||
end
|
||||
|
||||
def delete_user_activity
|
||||
user.notifications.delete_all
|
||||
user.reactions.delete_all
|
||||
user.follows.delete_all
|
||||
Follow.where(followable_id: user.id, followable_type: "User").delete_all
|
||||
user.chat_channel_memberships.delete_all
|
||||
user.mentions.delete_all
|
||||
user.badge_achievements.delete_all
|
||||
user.github_repos.delete_all
|
||||
delete_comments
|
||||
delete_articles
|
||||
end
|
||||
|
||||
def full_delete
|
||||
delete_user_activity
|
||||
CacheBuster.new.bust("/#{user.old_username}")
|
||||
user.delete
|
||||
end
|
||||
|
||||
def banish
|
||||
# return unless user.comments.where("created_at < ?", 150.days.ago).empty?
|
||||
reassign_and_bust_username
|
||||
remove_profile_info
|
||||
add_banned_role
|
||||
delete_reactions
|
||||
delete_comments
|
||||
delete_articles
|
||||
delete_follows
|
||||
delete_user_activity
|
||||
user.remove_from_algolia_index
|
||||
user.save!
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,23 +1,45 @@
|
|||
<h1><a href="<%= @user.path %>"><%= @user.name %></a></h1>
|
||||
<h2>@<%= @user.username %></h2>
|
||||
<h4><%= @user.comments.size %> comments</h4>
|
||||
<h4><%= @user.articles.size %> articles</h4>
|
||||
<h4><%= @user.reactions.size %> reactions</h4>
|
||||
<h4>Joined <%= @user.created_at.to_formatted_s(:long_ordinal) %></h4>
|
||||
<% if @user.banned %>
|
||||
<h1 style="color:red">User is banned</h1>
|
||||
<% @user.notes.each do |note| %>
|
||||
<b><%= note.reason %></b> | <%= note.content %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<h1>
|
||||
<%= @user.name%><a href="/<%= @user.username %>" target="_blank"> (@<%= @user.username %>)</a>
|
||||
</h1>
|
||||
<p><u><a style="color: green" href="/internal/users/<%= @user.id %>">click here view user details & take other actions</a></u></p>
|
||||
<p><em>Member since <%= @user.created_at.strftime("%b %e '%y") %></em></p>
|
||||
<p><strong>Activity:</strong></p>
|
||||
<ul>
|
||||
<li><%= @user.comments.size %> comments</li>
|
||||
<li><%= @user.articles.size %> articles</li>
|
||||
<li><%= @user.reactions.size %> reactions</li>
|
||||
</ul>
|
||||
<div class="row">
|
||||
<% if @user.comments.where("created_at < ?", 100.days.ago).empty? %>
|
||||
<%= form_for(@user, :url => banish_internal_user_path(@user), :html => {:method => :post, :onsubmit => "confirm('Are you sure? This is extremely destructive and will change their username to @spam_###. Do not do it lightly.')"}) do %>
|
||||
<h2>Banish User</h2>
|
||||
<% if @user.comments.where("created_at < ?", 100.days.ago).empty? && current_user.has_role?(:super_admin) %>
|
||||
<p><strong>This is not a new user.</strong> You are only allowed to take this action because you are a <strong>super admin.</strong></p>
|
||||
<p><em>This is extremely destructive. Banishing will delete all the user's existing content and change their username to @spam_###.</em></p>
|
||||
<p><strong>Do not do this lightly.</strong></p>
|
||||
<%= form_for(@user, :url => banish_internal_user_path(@user), :html => {:method => :post, :onsubmit => "confirm('Are you sure? This is extremely destructive. Banishing will delete all the user's existing content and change their username to @spam_###. Do not do it lightly.')"}) do %>
|
||||
<button class="btn btn-danger" style="font-size:2em;">Banish User for Spam!</button>
|
||||
<% end %>
|
||||
<em>This is extremely destructive and will change their username to @spam_###. Do not do it lightly.</em>
|
||||
<% elsif @user.comments.where("created_at < ?", 100.days.ago).empty? %>
|
||||
<p><em>This is extremely destructive. Banishing will delete all the user's existing content and change their username to @spam_###.</em></p>
|
||||
<p><strong>Do not do this lightly.</strong></p>
|
||||
<%= form_for(@user, :url => banish_internal_user_path(@user), :html => {:method => :post, :onsubmit => "confirm('Are you sure? This is extremely destructive. Banishing will delete all the user's existing content and change their username to @spam_###. Do not do it lightly.')"}) do %>
|
||||
<button class="btn btn-danger" style="font-size:2em;">Banish User for Spam</button>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<em>You cannot take admin action from this view because this is not a newish user. For safety.</em>
|
||||
<p><em>This is not a new user so you'll need to contact a super admin to banish this user.</em></p>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="row">
|
||||
<h2>Fully Delete User</h2>
|
||||
<% if current_user.has_role?(:super_admin) %>
|
||||
<p>This will <strong>completely destroy the user</strong> and all of their activity from our database. This action is irreversible.</p>
|
||||
<p><strong>Do not do this lightly.</strong></p>
|
||||
<%= form_for(@user, :url => full_delete_internal_user_path(@user), :html => {:method => :post, :onsubmit => "confirm('Are you sure? This is extremely destructive and irreversible.')"}) do %>
|
||||
<button class="btn btn-danger" style="font-size:2em;">Fully Delete User & All Activity</button>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<p>Only super admins can fully delete users.</p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
<style>
|
||||
.alert {
|
||||
border: 2px red solid;
|
||||
}
|
||||
</style>
|
||||
<h3 class="top-nav">
|
||||
<a href="/internal/users">All Users</a> ||
|
||||
<a href="/internal/users?state=mentors">Mentors Only </a>||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,18 @@
|
|||
<h1>
|
||||
<%= @user.name%><a href="/<%= @user.username %>" target="_blank"> (@<%= @user.username %>)</a>
|
||||
</h1>
|
||||
<p><u><a style="color: red" href="/internal/users/<%= @user.id %>/edit">click here to banish or delete user</a></u></p>
|
||||
<p><em>Member since <%= @user.created_at.strftime("%b %e '%y") %></em></p>
|
||||
<p><strong>Email:</strong> <%= @user.email %></p>
|
||||
<p><strong>Activity:</strong></p>
|
||||
<ul>
|
||||
<li><%= @user.comments.size %> comments</li>
|
||||
<li><%= @user.articles.size %> articles</li>
|
||||
<li><%= @user.reactions.size %> reactions</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
<h3><u>Current Roles</u></h3>
|
||||
<ul>
|
||||
<% @user.roles.each do |role| %>
|
||||
|
|
@ -11,9 +21,17 @@
|
|||
<% end %>
|
||||
</ul>
|
||||
<%= form_for ([:internal, @user]) do |f| %>
|
||||
<% if @user.banned %>
|
||||
<% if @user.banned && current_user.has_role?(:super_admin) %>
|
||||
<p style="background-color:red;color:white">🚨 Banned User 🚨</p>
|
||||
<p>You can only unban this user through the admin panel.</p>
|
||||
<%= f.label "Un-ban User (return to good standing)" %>
|
||||
<%= f.check_box :good_standing_user %>
|
||||
<br>
|
||||
|
||||
<br>
|
||||
<%= f.submit "Update User Status" %>
|
||||
<% elsif @user.banned %>
|
||||
<p style="background-color:red;color:white">🚨 Banned User 🚨</p>
|
||||
<p>Only super-admins can unban users.</p>
|
||||
<% elsif @user.warned %>
|
||||
<p style="background-color: orange;color:white">Warned User</p>
|
||||
<%= f.label :ban_user %>
|
||||
|
|
@ -107,7 +125,7 @@
|
|||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if @user.seeking_mentorship && @user.mentee_description.present? %>
|
||||
<% if @user.seeking_mentorship && @user.mentee_description.present? && !@user.banned_from_mentorship %>
|
||||
<h2> Mentee Description </h2>
|
||||
<div class="row" style="font-size:0.85em;position:sticky;top:50px;background:white;z-index:1000;border:2px solid black">
|
||||
<div class="col-md-2">
|
||||
|
|
@ -139,39 +157,40 @@
|
|||
order("mentor_form_updated_at DESC").limit(175).
|
||||
sort_by { |possible_mentor| UserSimilarity.new(@user, possible_mentor).score }.reverse.
|
||||
first(40).each do |possible_mentor| %>
|
||||
<div class="row" style="font-size:0.9em">
|
||||
<div class="col-md-2">
|
||||
<img src="<%= possible_mentor.profile_image_90 %>" style="border-radius:100px;width:50px;height:50px;" />
|
||||
<br/>
|
||||
<a href="/<%= possible_mentor.username %>" target="_blank">@<%= possible_mentor.username %></a>
|
||||
<br/>
|
||||
<a href="/internal/users/<%= possible_mentor.id %>" target="_blank">Internal(<%= possible_mentor.id %>)</a>
|
||||
|
||||
<% if !possible_mentor.banned_from_mentorship %>
|
||||
<div class="row" style="font-size:0.9em">
|
||||
<div class="col-md-2">
|
||||
<img src="<%= possible_mentor.profile_image_90 %>" style="border-radius:100px;width:50px;height:50px;" />
|
||||
<br/>
|
||||
<a href="/<%= possible_mentor.username %>" target="_blank">@<%= possible_mentor.username %></a>
|
||||
<br/>
|
||||
<a href="/internal/users/<%= possible_mentor.id %>" target="_blank">Internal Profile (id #<%= possible_mentor.id %>)</a>
|
||||
</div>
|
||||
<div class="col-md-3" style="border-left:1px solid black">
|
||||
<h4>Tag Intersection</h4>
|
||||
<%= UserSimilarity.new(@user, possible_mentor).tag_intersection.join(", ") %>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h4>Mentor description</h4>
|
||||
<%= possible_mentor.mentor_description %>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h4>Skills/Languages</h4>
|
||||
<%= possible_mentor.mostly_work_with %>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<h4>Action</h4>
|
||||
<%= form_for ([:internal, @user]) do |f| %>
|
||||
<%= f.hidden_field :quick_match, value: true %>
|
||||
<%= f.hidden_field :add_mentor, value: possible_mentor.id %>
|
||||
<%= f.submit "Match!" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3" style="border-left:1px solid black">
|
||||
<h4>Tag Intersection</h4>
|
||||
<%= UserSimilarity.new(@user, possible_mentor).tag_intersection.join(", ") %>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h4>Mentor description</h4>
|
||||
<%= possible_mentor.mentor_description %>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h4>Skills/Languages</h4>
|
||||
<%= possible_mentor.mostly_work_with %>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<h4>Action</h4>
|
||||
<%= form_for ([:internal, @user]) do |f| %>
|
||||
<%= f.hidden_field :quick_match, value: true %>
|
||||
<%= f.hidden_field :add_mentor, value: possible_mentor.id %>
|
||||
<%= f.submit "Match!" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<div class="row">
|
||||
<h2><u>Recent Emails</u></h2>
|
||||
<ul>
|
||||
<% @user.email_messages.order("sent_at DESC").limit(50).each do |email| %>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ Rails.application.routes.draw do
|
|||
resources :users do
|
||||
member do
|
||||
post "banish"
|
||||
post "full_delete"
|
||||
end
|
||||
end
|
||||
resources :events
|
||||
|
|
|
|||
|
|
@ -1,57 +1,103 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe "internal/users", type: :request do
|
||||
context "when banishing user" do
|
||||
let(:user) { create(:user) }
|
||||
let(:user2) { create(:user) }
|
||||
let(:user3) { create(:user) }
|
||||
let(:super_admin) { create(:user, :super_admin) }
|
||||
let(:article) { create(:article, user: user) }
|
||||
let(:article2) { create(:article, user: user2) }
|
||||
let(:user) { create(:user) }
|
||||
let(:user2) { create(:user) }
|
||||
let(:user3) { create(:user) }
|
||||
let(:super_admin) { create(:user, :super_admin) }
|
||||
let(:article) { create(:article, user: user) }
|
||||
let(:article2) { create(:article, user: user2) }
|
||||
|
||||
before do
|
||||
sign_in super_admin
|
||||
user
|
||||
user2
|
||||
Delayed::Worker.delay_jobs = true
|
||||
dependents_for_offending_user_article
|
||||
offender_activity_on_other_content
|
||||
end
|
||||
|
||||
after do
|
||||
Delayed::Worker.delay_jobs = false
|
||||
end
|
||||
|
||||
def dependents_for_offending_user_article
|
||||
# create user2 comment on offending user article
|
||||
comment = create(:comment, commentable_type: "Article", commentable: article, user: user2)
|
||||
# create user3 reaction to user2 comment
|
||||
create(:reaction, reactable: comment, reactable_type: "Comment", user: user3)
|
||||
# create user3 comment response to user2 comment
|
||||
comment2 = create(:comment, commentable_type: "Article", commentable: article, user: user3, ancestry: comment.id)
|
||||
# create user2 reaction to user3 comment response
|
||||
create(:reaction, reactable: comment2, reactable_type: "Comment", user: user2)
|
||||
# create user3 reaction to offending article
|
||||
create(:reaction, reactable: article, reactable_type: "Article", user: user3, category: "like")
|
||||
Delayed::Worker.new(quiet: true).work_off
|
||||
end
|
||||
|
||||
def offender_activity_on_other_content
|
||||
# offender reacts to user2 article
|
||||
create(:reaction, reactable: article2, reactable_type: "Article", user: user)
|
||||
# offender comments on user2 article
|
||||
comment = create(:comment, commentable_type: "Article", commentable: article2, user: user)
|
||||
# user3 reacts to offender comment
|
||||
create(:reaction, reactable: comment, reactable_type: "Comment", user: user3)
|
||||
Delayed::Worker.new(quiet: true).work_off
|
||||
end
|
||||
|
||||
context "when deleting user" do
|
||||
def create_mention
|
||||
comment = create(
|
||||
:comment,
|
||||
body_markdown: "Hello @#{user.username}, you are cool.",
|
||||
user_id: user2.id,
|
||||
commentable_id: article2.id,
|
||||
)
|
||||
Mention.create_all_without_delay(comment)
|
||||
end
|
||||
|
||||
def create_mutual_follows
|
||||
user.follow(user3)
|
||||
follow = user3.follow(user)
|
||||
Notification.send_new_follower_notification_without_delay(follow)
|
||||
end
|
||||
|
||||
before do
|
||||
sign_in super_admin
|
||||
user
|
||||
user2
|
||||
Delayed::Worker.delay_jobs = true
|
||||
dependents_for_offending_user_article
|
||||
offender_activity_on_other_content
|
||||
create_mutual_follows
|
||||
create_mention
|
||||
create(:badge_achievement, rewarder_id: 1, rewarding_context_message: "yay", user_id: user.id)
|
||||
Delayed::Worker.new(quiet: true).work_off
|
||||
end
|
||||
|
||||
after do
|
||||
Delayed::Worker.delay_jobs = false
|
||||
it "raises a 'record not found' error after deletion" do
|
||||
post "/internal/users/#{user.id}/full_delete"
|
||||
expect { User.find(user.id) }.to raise_exception(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
|
||||
context "when banning from mentorship" do
|
||||
before do
|
||||
user.update(offering_mentorship: true, mentor_description: "I want to be a mentor")
|
||||
end
|
||||
|
||||
it "adds banned from mentorship role" do
|
||||
put "/internal/users/#{user.id}", params: { user: { ban_from_mentorship: "1", note_for_mentorship_ban: "banned" } }
|
||||
expect(user.roles.first.name).to eq("banned_from_mentorship")
|
||||
end
|
||||
|
||||
it "returns user to good standing if unbanned" do
|
||||
put "/internal/users/#{user.id}", params: { user: { good_standing_user: "1" } }
|
||||
expect(user.roles.count).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "when banishing user" do
|
||||
def banish_user
|
||||
post "/internal/users/#{user.id}/banish"
|
||||
Delayed::Worker.new(quiet: true).work_off
|
||||
user.reload
|
||||
end
|
||||
|
||||
def dependents_for_offending_user_article
|
||||
# create user2 comment on offending user article
|
||||
comment = create(:comment, commentable_type: "Article", commentable: article, user: user2)
|
||||
# create user3 reaction to user2 comment
|
||||
create(:reaction, reactable: comment, reactable_type: "Comment", user: user3)
|
||||
# create user3 comment response to user2 comment
|
||||
comment2 = create(:comment, commentable_type: "Article", commentable: article, user: user3, ancestry: comment.id)
|
||||
# create user2 reaction to user3 comment response
|
||||
create(:reaction, reactable: comment2, reactable_type: "Comment", user: user2)
|
||||
# create user3 reaction to offending article
|
||||
create(:reaction, reactable: article, reactable_type: "Article", user: user3, category: "like")
|
||||
Delayed::Worker.new(quiet: true).work_off
|
||||
end
|
||||
|
||||
def offender_activity_on_other_content
|
||||
# offender reacts to user2 article
|
||||
create(:reaction, reactable: article2, reactable_type: "Article", user: user)
|
||||
# offender comments on user2 article
|
||||
comment = create(:comment, commentable_type: "Article", commentable: article2, user: user)
|
||||
# user3 reacts to offender comment
|
||||
create(:reaction, reactable: comment, reactable_type: "Comment", user: user3)
|
||||
Delayed::Worker.new(quiet: true).work_off
|
||||
end
|
||||
|
||||
it "reassigns username and removes profile info" do
|
||||
user.currently_hacking_on = "currently hackin on !!!!!!!!!!!!"
|
||||
user.save
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue