Commit a2f9612de8f01df1ad464a93d212ef4043c4ed73

Authored by Daniela Feitosa
Committed by Antonio Terceiro
1 parent 90844dbf

Allowing users to delete profile

Users can delete own profiles
Organization admins can delete organizations
Environment admins also can remove others profiles

(ActionItem1716)
app/controllers/my_profile/memberships_controller.rb
@@ -24,15 +24,4 @@ class MembershipsController < MyProfileController @@ -24,15 +24,4 @@ class MembershipsController < MyProfileController
24 render :layout => 'wizard' 24 render :layout => 'wizard'
25 end 25 end
26 end 26 end
27 -  
28 - def destroy_community  
29 - @community = Community.find(params[:id])  
30 - if request.post?  
31 - if @community.destroy  
32 - session[:notice] = _('%s was removed.') % @community.short_name  
33 - redirect_to :action => 'index'  
34 - end  
35 - end  
36 - end  
37 -  
38 end 27 end
app/controllers/my_profile/profile_editor_controller.rb
1 class ProfileEditorController < MyProfileController 1 class ProfileEditorController < MyProfileController
2 2
3 - protect 'edit_profile', :profile 3 + protect 'edit_profile', :profile, :except => [:destroy_profile]
  4 + protect 'destroy_profile', :profile, :only => [:destroy_profile]
4 5
5 def index 6 def index
6 @pending_tasks = profile.all_pending_tasks.select{|i| user.has_permission?(i.permission, profile)} 7 @pending_tasks = profile.all_pending_tasks.select{|i| user.has_permission?(i.permission, profile)}
@@ -72,4 +73,14 @@ class ProfileEditorController &lt; MyProfileController @@ -72,4 +73,14 @@ class ProfileEditorController &lt; MyProfileController
72 end 73 end
73 end 74 end
74 75
  76 + def destroy_profile
  77 + if request.post?
  78 + if @profile.destroy
  79 + session[:notice] = _('The profile was deleted.')
  80 + redirect_to :controller => 'home'
  81 + else
  82 + session[:notice] = _('Could not delete profile')
  83 + end
  84 + end
  85 + end
75 end 86 end
app/models/person.rb
@@ -19,7 +19,7 @@ class Person &lt; Profile @@ -19,7 +19,7 @@ class Person &lt; Profile
19 19
20 has_many :mailings 20 has_many :mailings
21 21
22 - has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id 22 + has_many :scraps_sent, :class_name => 'Scrap', :foreign_key => :sender_id, :dependent => :destroy
23 23
24 named_scope :more_popular, 24 named_scope :more_popular,
25 :select => "#{Profile.qualified_column_names}, count(friend_id) as total", 25 :select => "#{Profile.qualified_column_names}, count(friend_id) as total",
app/models/profile.rb
@@ -91,7 +91,7 @@ class Profile &lt; ActiveRecord::Base @@ -91,7 +91,7 @@ class Profile &lt; ActiveRecord::Base
91 91
92 has_many :action_tracker_notifications, :foreign_key => 'profile_id' 92 has_many :action_tracker_notifications, :foreign_key => 'profile_id'
93 has_many :tracked_notifications, :through => :action_tracker_notifications, :source => :action_tracker, :order => 'updated_at DESC' 93 has_many :tracked_notifications, :through => :action_tracker_notifications, :source => :action_tracker, :order => 'updated_at DESC'
94 - has_many :scraps_received, :class_name => 'Scrap', :foreign_key => :receiver_id, :order => "updated_at DESC" 94 + has_many :scraps_received, :class_name => 'Scrap', :foreign_key => :receiver_id, :order => "updated_at DESC", :dependent => :destroy
95 95
96 # FIXME ugly workaround 96 # FIXME ugly workaround
97 def self.human_attribute_name(attrib) 97 def self.human_attribute_name(attrib)
app/views/memberships/destroy_community.rhtml
@@ -1,9 +0,0 @@ @@ -1,9 +0,0 @@
1 -<h1><%= _('To remove %s') % @community.short_name %></h1>  
2 -  
3 -<p><strong><%= _('Are you sure you want to <u>remove</u> "%s"?') % content_tag( 'i', @community.name ) %></strong></p>  
4 -  
5 -<% form_tag do %>  
6 - <%= hidden_field_tag(:confirmation, 1) %>  
7 - <%= submit_button(:ok, _("Yes, I want to remove.") % @community.short_name) %>  
8 - <%= button(:cancel, _("No, I don't want."), :action => 'index') %>  
9 -<% end %>  
app/views/memberships/index.rhtml
@@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
25 <%= button 'menu-ctrl-panel', _('Control panel of this group'), membership.admin_url %> 25 <%= button 'menu-ctrl-panel', _('Control panel of this group'), membership.admin_url %>
26 <%= lightbox_button 'menu-logout', _('Leave'), membership.leave_url %> 26 <%= lightbox_button 'menu-logout', _('Leave'), membership.leave_url %>
27 <% if (membership.community? && user.has_permission?(:destroy_profile, membership)) %> 27 <% if (membership.community? && user.has_permission?(:destroy_profile, membership)) %>
28 - <%= button 'delete', _('Remove'), { :action => 'destroy_community', :id => membership } %> 28 + <%= button 'delete', _('Remove'), { :controller => 'profile_editor', :action => 'destroy_profile', :profile => membership.identifier } %>
29 <% end %> 29 <% end %>
30 <% end %> 30 <% end %>
31 </span> 31 </span>
app/views/profile_editor/destroy_profile.rhtml 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +<h1><%= _('Deleting profile %s') % profile.short_name(30) %></h1>
  2 +
  3 +<p><%= _('Are you sure you want to delete this profile?') %></p>
  4 +<p><%= _('You must be aware that all content of this profile (articles, events, files and pictures) will also be deleted.') %></p>
  5 +
  6 +<% button_bar do %>
  7 + <%= button(:remove, _('Yes, I am sure'), {:action => 'destroy_profile'}, :method => :post) %>
  8 + <%= button(:cancel, _('No, I gave up'), profile.url) %>
  9 +<% end %>
  10 +
app/views/profile_editor/edit.rhtml
@@ -76,6 +76,10 @@ @@ -76,6 +76,10 @@
76 76
77 <%= select_categories(:profile_data, _('Select the categories of your interest'), 2) %> 77 <%= select_categories(:profile_data, _('Select the categories of your interest'), 2) %>
78 78
  79 + <% if user && user.has_permission?('destroy_profile', profile) %>
  80 + <%= link_to _('Delete profile'), {:action => :destroy_profile}, :id => 'delete-profile-link' %>
  81 + <% end %>
  82 +
79 <% button_bar do %> 83 <% button_bar do %>
80 <%= submit_button('save', _('Save'), :cancel => {:action => 'index'}) %> 84 <%= submit_button('save', _('Save'), :cancel => {:action => 'index'}) %>
81 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> 85 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %>
features/delete_profile.feature 0 → 100644
@@ -0,0 +1,126 @@ @@ -0,0 +1,126 @@
  1 +Feature: delete profile
  2 + As a noosfero user
  3 + I want to delete my profile
  4 + In order to leave the network
  5 +
  6 + Background:
  7 + Given the following users
  8 + | login | name |
  9 + | joaosilva | Joao Silva |
  10 +
  11 + Scenario: deleting profile
  12 + Given I am logged in as "joaosilva"
  13 + And I am on Joao Silva's control panel
  14 + And I follow "Profile Info and settings"
  15 + And I follow "Delete profile"
  16 + Then I should see "Are you sure you want to delete this profile?"
  17 + When I follow "Yes, I am sure"
  18 + Then I should be on the homepage
  19 + When I go to /joaosilva
  20 + Then I should see "There is no such page"
  21 +
  22 + Scenario: deleting other profile
  23 + Given the following users
  24 + | login | name |
  25 + | mariasilva | Maria Silva |
  26 + And I am logged in as "mariasilva"
  27 + And I go to /myprofile/joaosilva/profile_editor/destroy_profile
  28 + Then I should see "Access denied"
  29 +
  30 + Scenario: giving up of deleting profile
  31 + Given I am logged in as "joaosilva"
  32 + And I am on Joao Silva's control panel
  33 + And I follow "Profile Info and settings"
  34 + And I follow "Delete profile"
  35 + Then I should see "Are you sure you want to delete this profile?"
  36 + When I follow "No, I gave up"
  37 + Then I should be on Joao Silva's homepage
  38 +
  39 + Scenario: community admin can see link to delete profile
  40 + Given the following community
  41 + | identifier | name |
  42 + | sample-community | Sample Community |
  43 + And "Joao Silva" is admin of "Sample Community"
  44 + And I am logged in as "joaosilva"
  45 + And I am on Sample Community's control panel
  46 + When I follow "Community Info and settings"
  47 + Then I should see "Delete profile"
  48 +
  49 + Scenario: community admin deletes the community
  50 + Given the following community
  51 + | identifier | name |
  52 + | sample-community | Sample Community |
  53 + And "Joao Silva" is admin of "Sample Community"
  54 + And I am logged in as "joaosilva"
  55 + And I am on Sample Community's control panel
  56 + And I follow "Community Info and settings"
  57 + And I follow "Delete profile"
  58 + Then I should see "Are you sure you want to delete this profile?"
  59 + When I follow "Yes, I am sure"
  60 + Then I should be on the homepage
  61 + When I go to /sample-community
  62 + Then I should see "There is no such page"
  63 +
  64 + Scenario: community regular member tries to delete the community
  65 + Given the following community
  66 + | identifier | name |
  67 + | sample-community | Sample Community |
  68 + And "Joao Silva" is a member of "Sample Community"
  69 + And I am logged in as "joaosilva"
  70 + And I go to /myprofile/sample-community/profile_editor/destroy_profile
  71 + Then I should see "Access denied"
  72 +
  73 + Scenario: enterprise admin can see link to delete enterprise
  74 + Given the following enterprise
  75 + | identifier | name |
  76 + | sample-enterprise | Sample Enterprise |
  77 + And "Joao Silva" is admin of "Sample Enterprise"
  78 + And I am logged in as "joaosilva"
  79 + And I am on Sample Enterprise's control panel
  80 + When I follow "Enterprise Info and settings"
  81 + Then I should see "Delete profile"
  82 +
  83 + Scenario: enterprise admin deletes the enterprise
  84 + Given the following enterprise
  85 + | identifier | name |
  86 + | sample-enterprise | Sample Enterprise |
  87 + And "Joao Silva" is admin of "Sample Enterprise"
  88 + And I am logged in as "joaosilva"
  89 + And I am on Sample Enterprise's control panel
  90 + When I follow "Enterprise Info and settings"
  91 + And I follow "Delete profile"
  92 + Then I should see "Are you sure you want to delete this profile?"
  93 + When I follow "Yes, I am sure"
  94 + Then I should be on the homepage
  95 + When I go to /sample-enterprise
  96 + Then I should see "There is no such page"
  97 +
  98 + Scenario: enterprise regular member tries to delete the enterprise
  99 + Given the following community
  100 + | identifier | name |
  101 + | sample-enterprise | Sample Enterprise |
  102 + And "Joao Silva" is a member of "Sample Enterprise"
  103 + And I am logged in as "joaosilva"
  104 + And I go to /myprofile/sample-enterprise/profile_editor/destroy_profile
  105 + Then I should see "Access denied"
  106 +
  107 + Scenario: community regular member cannot see link to delete profile
  108 + Given the following community
  109 + | identifier | name |
  110 + | sample-community | Sample Community |
  111 + And "Joao Silva" is a member of "Sample Community"
  112 + And I am logged in as "joaosilva"
  113 + And I am on Sample Community's control panel
  114 + When I follow "Community Info and settings"
  115 + Then I should not see "Delete profile"
  116 +
  117 + Scenario: environment admin deletes profile
  118 + Given I am logged in as admin
  119 + And I am on Joao Silva's control panel
  120 + And I follow "Profile Info and settings"
  121 + And I follow "Delete profile"
  122 + Then I should see "Are you sure you want to delete this profile?"
  123 + When I follow "Yes, I am sure"
  124 + Then I should be on the homepage
  125 + When I go to /joaosilva
  126 + Then I should see "There is no such page"
public/stylesheets/application.css
@@ -3503,6 +3503,10 @@ h1#agenda-title { @@ -3503,6 +3503,10 @@ h1#agenda-title {
3503 -webkit-border-radius: 3px; 3503 -webkit-border-radius: 3px;
3504 } 3504 }
3505 3505
  3506 +.controller-profile_editor #delete-profile-link {
  3507 + float: right;
  3508 +}
  3509 +
3506 .controller-profile_editor a.control-panel-groups { background-image: url(../images/control-panel/system-users.png) } 3510 .controller-profile_editor a.control-panel-groups { background-image: url(../images/control-panel/system-users.png) }
3507 .controller-profile_editor .msie6 a.control-panel-groups { background-image: url(../images/control-panel/system-users.gif) } 3511 .controller-profile_editor .msie6 a.control-panel-groups { background-image: url(../images/control-panel/system-users.gif) }
3508 3512
test/fixtures/roles.yml
@@ -86,3 +86,5 @@ environment_administrator: @@ -86,3 +86,5 @@ environment_administrator:
86 - manage_environment_validators 86 - manage_environment_validators
87 - moderate_comments 87 - moderate_comments
88 - manage_environment_users 88 - manage_environment_users
  89 + - edit_profile
  90 + - destroy_profile
test/functional/memberships_controller_test.rb
@@ -122,15 +122,9 @@ class MembershipsControllerTest &lt; Test::Unit::TestCase @@ -122,15 +122,9 @@ class MembershipsControllerTest &lt; Test::Unit::TestCase
122 assert_tag :tag => 'a', :attributes => { :href => "/myprofile/testuser/memberships/new_community" } 122 assert_tag :tag => 'a', :attributes => { :href => "/myprofile/testuser/memberships/new_community" }
123 end 123 end
124 124
125 - should 'render destroy_community template' do  
126 - community = Community.create!(:name => 'A community to destroy')  
127 - get :destroy_community, :profile => 'testuser', :id => community.id  
128 - assert_template 'destroy_community'  
129 - end  
130 -  
131 should 'display destroy link only to communities' do 125 should 'display destroy link only to communities' do
132 community = Community.create!(:name => 'A community to destroy') 126 community = Community.create!(:name => 'A community to destroy')
133 - enterprise = fast_create(Enterprise, :name => 'A enterprise test', :identifier => 'enterprise-test') 127 + enterprise = fast_create(Enterprise, :name => 'A enterprise test')
134 128
135 person = Person['testuser'] 129 person = Person['testuser']
136 community.add_admin(person) 130 community.add_admin(person)
@@ -138,19 +132,8 @@ class MembershipsControllerTest &lt; Test::Unit::TestCase @@ -138,19 +132,8 @@ class MembershipsControllerTest &lt; Test::Unit::TestCase
138 132
139 get :index, :profile => 'testuser' 133 get :index, :profile => 'testuser'
140 134
141 - assert_tag :tag => 'a', :attributes => { :href => "/myprofile/testuser/memberships/destroy_community/#{community.id}" }  
142 - assert_no_tag :tag => 'a', :attributes => { :href => "/myprofile/testuser/memberships/destroy_community/#{enterprise.id}" }  
143 - end  
144 -  
145 - should 'be able to destroy communities' do  
146 - community = Community.create!(:name => 'A community to destroy')  
147 -  
148 - person = Person['testuser']  
149 - community.add_admin(person)  
150 -  
151 - assert_difference Community, :count, -1 do  
152 - post :destroy_community, :profile => 'testuser', :id => community.id  
153 - end 135 + assert_tag :tag => 'a', :attributes => { :href => "/myprofile/#{community.identifier}/profile_editor/destroy_profile" }
  136 + assert_no_tag :tag => 'a', :attributes => { :href => "/myprofile/#{enterprise.identifier}/profile_editor/destroy_profile" }
154 end 137 end
155 138
156 should 'not display destroy link to normal members' do 139 should 'not display destroy link to normal members' do
@@ -163,7 +146,7 @@ class MembershipsControllerTest &lt; Test::Unit::TestCase @@ -163,7 +146,7 @@ class MembershipsControllerTest &lt; Test::Unit::TestCase
163 get :index, :profile => 'testuser' 146 get :index, :profile => 'testuser'
164 147
165 assert_template 'index' 148 assert_template 'index'
166 - assert_no_tag :tag => 'a', :attributes => { :href => "/myprofile/testuser/memberships/destroy_community/#{community.id}" } 149 + assert_no_tag :tag => 'a', :attributes => { :href => "/myprofile/#{community.identifier}/profile_editor/destroy_profile" }
167 end 150 end
168 151
169 should 'use the current environment for the template of user' do 152 should 'use the current environment for the template of user' do
test/functional/profile_controller_test.rb
@@ -647,6 +647,23 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -647,6 +647,23 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
647 assert_equal "You can't leave an empty message.", assigns(:message) 647 assert_equal "You can't leave an empty message.", assigns(:message)
648 end 648 end
649 649
  650 + should "display a scrap sent" do
  651 + another_person = fast_create(Person)
  652 + Scrap.create!(defaults_for_scrap(:sender => another_person, :receiver => profile, :content => 'A scrap'))
  653 + login_as(profile.identifier)
  654 + get :index, :profile => profile.identifier
  655 + assert_tag :tag => 'p', :content => 'A scrap'
  656 + end
  657 +
  658 + should "not display a scrap sent by a removed user" do
  659 + another_person = fast_create(Person)
  660 + Scrap.create!(defaults_for_scrap(:sender => another_person, :receiver => profile, :content => 'A scrap'))
  661 + login_as(profile.identifier)
  662 + another_person.destroy
  663 + get :index, :profile => profile.identifier
  664 + assert_no_tag :tag => 'p', :content => 'A scrap'
  665 + end
  666 +
650 should 'see all activities of the current profile' do 667 should 'see all activities of the current profile' do
651 p1= Person.first 668 p1= Person.first
652 p2= fast_create(Person) 669 p2= fast_create(Person)
test/functional/profile_editor_controller_test.rb
@@ -798,4 +798,64 @@ class ProfileEditorControllerTest &lt; Test::Unit::TestCase @@ -798,4 +798,64 @@ class ProfileEditorControllerTest &lt; Test::Unit::TestCase
798 } 798 }
799 end 799 end
800 800
  801 + should 'render destroy_profile template' do
  802 + community = fast_create(Community)
  803 + get :destroy_profile, :profile => community.identifier
  804 + assert_template 'destroy_profile'
  805 + end
  806 +
  807 + should 'be able to destroy a person' do
  808 + person = fast_create(Person)
  809 +
  810 + assert_difference Person, :count, -1 do
  811 + post :destroy_profile, :profile => person.identifier
  812 + end
  813 + end
  814 +
  815 + should 'be able to destroy communities' do
  816 + community = fast_create(Community)
  817 +
  818 + person = fast_create(Person)
  819 + community.add_admin(person)
  820 +
  821 + assert_difference Community, :count, -1 do
  822 + post :destroy_profile, :profile => community.identifier
  823 + end
  824 + end
  825 +
  826 + should 'not be able to destroy communities if is a regular member' do
  827 + community = fast_create(Community)
  828 +
  829 + person = fast_create(Person)
  830 + community.add_admin(person)
  831 +
  832 + login_as(person.identifier)
  833 + assert_difference Community, :count, 0 do
  834 + post :destroy_profile, :profile => community.identifier
  835 + end
  836 + end
  837 +
  838 + should 'be able to destroy enterprise' do
  839 + enterprise = fast_create(Enterprise)
  840 +
  841 + person = fast_create(Person)
  842 + enterprise.add_admin(person)
  843 +
  844 + assert_difference Enterprise, :count, -1 do
  845 + post :destroy_profile, :profile => enterprise.identifier
  846 + end
  847 + end
  848 +
  849 + should 'not be able to destroy enterprise if is a regular member' do
  850 + enterprise = fast_create(Enterprise)
  851 +
  852 + person = fast_create(Person)
  853 + enterprise.add_admin(person)
  854 +
  855 + login_as(person.identifier)
  856 + assert_difference Enterprise, :count, 0 do
  857 + post :destroy_profile, :profile => enterprise.identifier
  858 + end
  859 + end
  860 +
801 end 861 end
test/unit/person_test.rb
@@ -786,6 +786,14 @@ class PersonTest &lt; Test::Unit::TestCase @@ -786,6 +786,14 @@ class PersonTest &lt; Test::Unit::TestCase
786 assert_equal s2, person.scraps(s2.id.to_s) 786 assert_equal s2, person.scraps(s2.id.to_s)
787 end 787 end
788 788
  789 + should "destroy scrap if sender was removed" do
  790 + person = fast_create(Person)
  791 + scrap = fast_create(Scrap, :sender_id => person.id)
  792 + assert_not_nil Scrap.find_by_id(scrap.id)
  793 + person.destroy
  794 + assert_nil Scrap.find_by_id(scrap.id)
  795 + end
  796 +
789 should "the tracked action be notified to person friends and herself" do 797 should "the tracked action be notified to person friends and herself" do
790 p1 = Person.first 798 p1 = Person.first
791 p2 = fast_create(Person) 799 p2 = fast_create(Person)
test/unit/profile_test.rb
@@ -1805,6 +1805,15 @@ class ProfileTest &lt; Test::Unit::TestCase @@ -1805,6 +1805,15 @@ class ProfileTest &lt; Test::Unit::TestCase
1805 assert_nil profile.profile_custom_icon 1805 assert_nil profile.profile_custom_icon
1806 end 1806 end
1807 1807
  1808 + should "destroy scrap if receiver was removed" do
  1809 + person = fast_create(Person)
  1810 + scrap = fast_create(Scrap, :receiver_id => person.id)
  1811 + assert_not_nil Scrap.find_by_id(scrap.id)
  1812 + person.destroy
  1813 + assert_nil Scrap.find_by_id(scrap.id)
  1814 + end
  1815 +
  1816 +
1808 private 1817 private
1809 1818
1810 def assert_invalid_identifier(id) 1819 def assert_invalid_identifier(id)