Commit b8ade54001d3480693016e52353b96a1bc79f9a2

Authored by Daniela Feitosa
1 parent c0cb6076

Procedure after last admin leaves organization

* if he is also last member, the next user to join organization will become admin
* if has other members, admin must choose some user to become admin
* Generalized enterprise add_member interface.
* Using json to manage action after join/leave/add/remove
community/friend through ajax.
* Person.members_of now returns unique profiles

(ActionItem1400)
app/controllers/my_profile/profile_members_controller.rb
@@ -15,26 +15,29 @@ class ProfileMembersController < MyProfileController @@ -15,26 +15,29 @@ class ProfileMembersController < MyProfileController
15 rescue ActiveRecord::RecordNotFound 15 rescue ActiveRecord::RecordNotFound
16 @person = nil 16 @person = nil
17 end 17 end
18 - if @person && @person.define_roles(@roles, profile)  
19 - session[:notice] = _('Roles successfuly updated') 18 + if !params[:confirmation] && @person && @person.is_last_admin_leaving?(profile, @roles)
  19 + redirect_to :action => :last_admin, :roles => params[:roles], :person => @person
20 else 20 else
21 - session[:notice] = _('Couldn\'t change the roles') 21 + if @person && @person.define_roles(@roles, profile)
  22 + session[:notice] = _('Roles successfuly updated')
  23 + else
  24 + session[:notice] = _('Couldn\'t change the roles')
  25 + end
  26 + if params[:confirmation]
  27 + redirect_to profile.url
  28 + else
  29 + redirect_to :action => :index
  30 + end
22 end 31 end
23 - redirect_to :action => :index  
24 end 32 end
25 33
26 - def change_role  
27 - @roles = Profile::Roles.organization_member_roles(environment.id)  
28 - begin  
29 - @member = profile.members.find(params[:id])  
30 - rescue ActiveRecord::RecordNotFound  
31 - @member = nil  
32 - end  
33 - if @member  
34 - @associations = @member.find_roles(@profile)  
35 - else  
36 - redirect_to :action => :index  
37 - end 34 + def last_admin
  35 + @person = params[:person]
  36 + @roles = params[:roles] || []
  37 + @members = profile.members.select {|member| !profile.admins.include?(member)}
  38 + @title = _('Current admins')
  39 + @collection = :profile_admins
  40 + @remove_action = {:action => 'remove_admin'}
38 end 41 end
39 42
40 def add_role 43 def add_role
@@ -59,14 +62,28 @@ class ProfileMembersController < MyProfileController @@ -59,14 +62,28 @@ class ProfileMembersController < MyProfileController
59 render :layout => false 62 render :layout => false
60 end 63 end
61 64
  65 + def change_role
  66 + @roles = Profile::Roles.organization_member_roles(environment.id)
  67 + begin
  68 + @member = profile.members.find(params[:id])
  69 + rescue ActiveRecord::RecordNotFound
  70 + @member = nil
  71 + end
  72 + if @member
  73 + @associations = @member.find_roles(@profile)
  74 + else
  75 + redirect_to :action => :index
  76 + end
  77 + end
  78 +
62 def unassociate 79 def unassociate
63 member = Person.find(params[:id]) 80 member = Person.find(params[:id])
64 associations = member.find_roles(profile) 81 associations = member.find_roles(profile)
65 RoleAssignment.transaction do 82 RoleAssignment.transaction do
66 if associations.map(&:destroy) 83 if associations.map(&:destroy)
67 - session[:notice] = 'Member succefully unassociated' 84 + session[:notice] = _('Member succesfully unassociated')
68 else 85 else
69 - session[:notice] = 'Failed to unassociate member' 86 + session[:notice] = _('Failed to unassociate member')
70 end 87 end
71 end 88 end
72 render :layout => false 89 render :layout => false
@@ -83,11 +100,39 @@ class ProfileMembersController < MyProfileController @@ -83,11 +100,39 @@ class ProfileMembersController < MyProfileController
83 render :layout => false 100 render :layout => false
84 end 101 end
85 102
  103 + def add_admin
  104 + @title = _('Current admins')
  105 + @collection = :profile_admins
  106 +
  107 + if profile.community?
  108 + member = profile.members.find_by_identifier(params[:id])
  109 + profile.add_admin(member)
  110 + end
  111 + render :layout => false
  112 + end
  113 +
  114 + def remove_admin
  115 + @title = _('Current admins')
  116 + @collection = :profile_admins
  117 +
  118 + if profile.community?
  119 + member = profile.members.find_by_identifier(params[:id])
  120 + profile.remove_admin(member)
  121 + end
  122 + render :layout => false
  123 + end
  124 +
86 def find_users 125 def find_users
87 if !params[:query] || params[:query].length <= 2 126 if !params[:query] || params[:query].length <= 2
88 @users_found = [] 127 @users_found = []
89 - else  
90 - @users_found = Person.find_by_contents(params[:query] + '*') 128 + elsif params[:scope] == 'all_users'
  129 + @users_found = Person.find_by_contents(params[:query] + '*').select {|user| !profile.members.include?(user)}
  130 + @button_alt = _('Add member')
  131 + @add_action = {:action => 'add_member'}
  132 + elsif params[:scope] == 'new_admins'
  133 + @users_found = Person.find_by_contents(params[:query] + '*').select {|user| profile.members.include?(user) && !profile.admins.include?(user)}
  134 + @button_alt = _('Add member')
  135 + @add_action = {:action => 'add_admin'}
91 end 136 end
92 render :layout => false 137 render :layout => false
93 end 138 end
app/controllers/public/profile_controller.rb
@@ -82,13 +82,13 @@ class ProfileController &lt; PublicController @@ -82,13 +82,13 @@ class ProfileController &lt; PublicController
82 def join 82 def join
83 if !user.memberships.include?(profile) 83 if !user.memberships.include?(profile)
84 profile.add_member(user) 84 profile.add_member(user)
85 - if profile.closed?  
86 - render :text => _('%s administrator still needs to accept you as member.') % profile.name 85 + if !profile.members.include?(user)
  86 + render :text => {:message => _('%s administrator still needs to accept you as member.') % profile.name}.to_json
87 else 87 else
88 - render :text => _('You just became a member of %s.') % profile.name 88 + render :text => {:message => _('You just became a member of %s.') % profile.name}.to_json
89 end 89 end
90 else 90 else
91 - render :text => _('You are already a member of %s.') % profile.name 91 + render :text => {:message => _('You are already a member of %s.') % profile.name}.to_json
92 end 92 end
93 end 93 end
94 94
@@ -110,11 +110,14 @@ class ProfileController &lt; PublicController @@ -110,11 +110,14 @@ class ProfileController &lt; PublicController
110 end 110 end
111 111
112 def leave 112 def leave
113 - if user.memberships.include?(profile)  
114 - profile.remove_member(current_user.person)  
115 - render :text => _('You just left %s.') % profile.name 113 + if current_person.memberships.include?(profile)
  114 + if current_person.is_last_admin?(profile)
  115 + render :text => {:redirect_to => url_for({:controller => 'profile_members', :action => 'last_admin', :person => current_person.id})}.to_json
  116 + else
  117 + render :text => current_person.leave(profile, params[:reload])
  118 + end
116 else 119 else
117 - render :text => _('You are already a member of %s.') % profile.name 120 + render :text => {:message => _('You are not a member of %s.') % profile.name}.to_json
118 end 121 end
119 end 122 end
120 123
app/models/environment_mailing.rb
1 class EnvironmentMailing < Mailing 1 class EnvironmentMailing < Mailing
2 2
3 def recipients(offset=0, limit=100) 3 def recipients(offset=0, limit=100)
4 - source.people.all(:order => :id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :order => :id, :conditions => { "m.person_id" => nil }) 4 + source.people.all(:order => :id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :conditions => { "m.person_id" => nil })
5 end 5 end
6 6
7 def each_recipient 7 def each_recipient
app/models/organization_mailing.rb
@@ -5,7 +5,7 @@ class OrganizationMailing &lt; Mailing @@ -5,7 +5,7 @@ class OrganizationMailing &lt; Mailing
5 end 5 end
6 6
7 def recipients(offset=0, limit=100) 7 def recipients(offset=0, limit=100)
8 - source.members.all(:order => :id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :order => :id, :conditions => { "m.person_id" => nil }) 8 + source.members.all(:order => self.id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :conditions => { "m.person_id" => nil })
9 end 9 end
10 10
11 def each_recipient 11 def each_recipient
app/models/person.rb
@@ -4,7 +4,7 @@ class Person &lt; Profile @@ -4,7 +4,7 @@ class Person &lt; Profile
4 acts_as_trackable :after_add => Proc.new {|p,t| notify_activity(t)} 4 acts_as_trackable :after_add => Proc.new {|p,t| notify_activity(t)}
5 acts_as_accessor 5 acts_as_accessor
6 6
7 - named_scope :members_of, lambda { |resource| { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.resource_type = ? AND role_assignments.resource_id = ?', resource.class.base_class.name, resource.id ] } } 7 + named_scope :members_of, lambda { |resource| { :select => 'DISTINCT profiles.*', :include => :role_assignments, :group => 'profiles.id', :conditions => ['role_assignments.resource_type = ? AND role_assignments.resource_id = ?', resource.class.base_class.name, resource.id ] } }
8 8
9 def memberships 9 def memberships
10 Profile.memberships_of(self) 10 Profile.memberships_of(self)
@@ -363,10 +363,26 @@ class Person &lt; Profile @@ -363,10 +363,26 @@ class Person &lt; Profile
363 generate_url(:profile => identifier, :controller => 'profile', :action => 'index', :anchor => 'profile-wall') 363 generate_url(:profile => identifier, :controller => 'profile', :action => 'index', :anchor => 'profile-wall')
364 end 364 end
365 365
  366 + def is_last_admin?(organization)
  367 + organization.admins == [self]
  368 + end
  369 +
  370 + def is_last_admin_leaving?(organization, roles)
  371 + is_last_admin?(organization) && roles.select {|role| role.key == "profile_admin"}.blank?
  372 + end
  373 +
  374 + def leave(profile, reload = false)
  375 + leave_hash = {:message => _('You just left %s.') % profile.name}
  376 + if reload
  377 + leave_hash.merge!({:reload => true})
  378 + end
  379 + profile.remove_member(self)
  380 + leave_hash.to_json
  381 + end
  382 +
366 protected 383 protected
367 384
368 def followed_by?(profile) 385 def followed_by?(profile)
369 self == profile || self.is_a_friend?(profile) 386 self == profile || self.is_a_friend?(profile)
370 end 387 end
371 -  
372 end 388 end
app/models/profile.rb
@@ -424,8 +424,8 @@ class Profile &lt; ActiveRecord::Base @@ -424,8 +424,8 @@ class Profile &lt; ActiveRecord::Base
424 { :profile => identifier, :controller => 'profile_editor', :action => 'index' } 424 { :profile => identifier, :controller => 'profile_editor', :action => 'index' }
425 end 425 end
426 426
427 - def leave_url  
428 - { :profile => identifier, :controller => 'profile', :action => 'leave' } 427 + def leave_url(reload = false)
  428 + { :profile => identifier, :controller => 'profile', :action => 'leave', :reload => reload }
429 end 429 end
430 430
431 def join_url 431 def join_url
@@ -563,13 +563,16 @@ private :generate_url, :url_options @@ -563,13 +563,16 @@ private :generate_url, :url_options
563 # Adds a person as member of this Profile. 563 # Adds a person as member of this Profile.
564 def add_member(person) 564 def add_member(person)
565 if self.has_members? 565 if self.has_members?
566 - if self.closed? 566 + if self.closed? && members.count > 0
567 AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person) 567 AddMember.create!(:person => person, :organization => self) unless self.already_request_membership?(person)
568 else 568 else
  569 + if members.count == 0
  570 + self.affiliate(person, Profile::Roles.admin(environment.id))
  571 + end
569 self.affiliate(person, Profile::Roles.member(environment.id)) 572 self.affiliate(person, Profile::Roles.member(environment.id))
570 end 573 end
571 else 574 else
572 - raise _("%s can't has members") % self.class.name 575 + raise _("%s can't have members") % self.class.name
573 end 576 end
574 end 577 end
575 578
@@ -582,6 +585,10 @@ private :generate_url, :url_options @@ -582,6 +585,10 @@ private :generate_url, :url_options
582 self.affiliate(person, Profile::Roles.admin(environment.id)) 585 self.affiliate(person, Profile::Roles.admin(environment.id))
583 end 586 end
584 587
  588 + def remove_admin(person)
  589 + self.disaffiliate(person, Profile::Roles.admin(environment.id))
  590 + end
  591 +
585 def add_moderator(person) 592 def add_moderator(person)
586 if self.has_members? 593 if self.has_members?
587 self.affiliate(person, Profile::Roles.moderator(environment.id)) 594 self.affiliate(person, Profile::Roles.moderator(environment.id))
app/views/memberships/index.rhtml
@@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
23 <%= _('Created at: %s') % show_date(membership.created_at) unless membership.enterprise? %> <br/> 23 <%= _('Created at: %s') % show_date(membership.created_at) unless membership.enterprise? %> <br/>
24 <% button_bar do %> 24 <% button_bar do %>
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 + <%= button 'menu-logout', _('Leave'), membership.leave_url(true), :class => 'leave-community' %>
27 <% if (membership.community? && user.has_permission?(:destroy_profile, membership)) %> 27 <% if (membership.community? && user.has_permission?(:destroy_profile, membership)) %>
28 <%= button 'delete', _('Remove'), { :controller => 'profile_editor', :action => 'destroy_profile', :profile => membership.identifier } %> 28 <%= button 'delete', _('Remove'), { :controller => 'profile_editor', :action => 'destroy_profile', :profile => membership.identifier } %>
29 <% end %> 29 <% end %>
app/views/profile_members/_add_admins.rhtml 0 → 100644
@@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
  1 +<h2><%= _('Add admins to %s') % profile.name %></h2>
  2 +
  3 +<% form_remote_tag :url => {:action => 'find_users', :profile => profile.identifier, :scope => 'new_admins'}, :update => 'users-list', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")' do %>
  4 + <%= text_field_tag('query', '', :autocomplete => 'off') %>
  5 + <%= submit_tag(_('Search')) %>
  6 +<% end %>
  7 +
  8 +<%= observe_field('query', :url => {:action => 'find_users', :profile => profile.identifier, :scope => 'new_admins'}, :update => 'users-list', :frequency => 1, :with => 'query', :condition => '$("query").value.length > 2', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")') %>
  9 +<%= observe_field('query', :frequency => 1, :condition => '$("query").value.length <= 2', :function => '$("users-list").update($("empty-query").innerHTML)') %>
  10 +
  11 +<div id="users-list">
  12 + <%= render :partial => 'find_users' %>
  13 +</div>
  14 +
  15 +<div id='empty-query' style='display: none'>
  16 + <%= render :partial => 'find_users' %>
  17 +</div>
  18 +
  19 +<div id="members-list" class="add-members">
  20 + <%= render :partial => 'members_list' %>
  21 +</div>
  22 +<%= drop_receiving_element('members-list',
  23 + :url => {:action => 'add_admin', :profile => profile.identifier, :leaving_admin => @person},
  24 + :before => '$("tr-" + element.id).hide()',
  25 + :loading => '$("members-list").addClassName("loading")',
  26 + :update => 'members-list',
  27 + :success => '$("tr-" + element.id).hide(); $(element.id).show();',
  28 + :complete => '$("members-list").removeClassName("loading")') %>
  29 +
  30 +<br style="clear:both" />
app/views/profile_members/_members_list.rhtml
1 -<h3><%= _('Current Members') %></h3> 1 +<% collection = @collection == :profile_admins ? profile.admins : profile.members %>
  2 +<% title = @title ? @title : "Current members" %>
  3 +<% remove_action = @remove_action ? @remove_action : {:action => 'unassociate'} %>
  4 +
  5 +<h3><%= _(title) %></h3>
2 6
3 <table> 7 <table>
4 <tr> 8 <tr>
5 <th><%= _('Member') %></th> 9 <th><%= _('Member') %></th>
6 <th><%= _('Actions') %></th> 10 <th><%= _('Actions') %></th>
7 </tr> 11 </tr>
8 - <% profile.members.each do |m| %> 12 + <% collection.each do |m| %>
9 <tr> 13 <tr>
10 <td><%= link_to_profile m.short_name, m.identifier, :title => m.name %> </td> 14 <td><%= link_to_profile m.short_name, m.identifier, :title => m.name %> </td>
11 <td> 15 <td>
@@ -16,8 +20,7 @@ @@ -16,8 +20,7 @@
16 :loading => '$("members-list").addClassName("loading")', 20 :loading => '$("members-list").addClassName("loading")',
17 :success => "$('tr-#{m.identifier}').show()", 21 :success => "$('tr-#{m.identifier}').show()",
18 :complete => '$("members-list").removeClassName("loading")', 22 :complete => '$("members-list").removeClassName("loading")',
19 - :confirm => _('Are you sure that you want to remove this member?'),  
20 - :url => {:action => 'unassociate', :id => m}) if m != user %> 23 + :url => { :id => m }.merge(remove_action)) if m != user %>
21 </div> 24 </div>
22 </td> 25 </td>
23 </tr> 26 </tr>
app/views/profile_members/add_admin.rhtml 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +_members_list.rhtml
0 \ No newline at end of file 2 \ No newline at end of file
app/views/profile_members/add_members.rhtml
1 <h2><%= _('Add members to %s') % profile.name %></h2> 1 <h2><%= _('Add members to %s') % profile.name %></h2>
2 2
3 -<% form_remote_tag :url => {:action => 'find_users', :profile => profile.identifier}, :update => 'users-list', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")' do %> 3 +<% form_remote_tag :url => {:action => 'find_users', :profile => profile.identifier, :scope => 'all_users'}, :update => 'users-list', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")' do %>
4 <%= text_field_tag('query', '', :autocomplete => 'off') %> 4 <%= text_field_tag('query', '', :autocomplete => 'off') %>
5 <%= submit_tag(_('Search')) %> 5 <%= submit_tag(_('Search')) %>
6 <% end %> 6 <% end %>
7 7
8 -<%= observe_field('query', :url => {:action => 'find_users', :profile => profile.identifier}, :update => 'users-list', :frequency => 1, :with => 'query', :condition => '$("query").value.length > 2', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")') %> 8 +<%= observe_field('query', :url => {:action => 'find_users', :profile => profile.identifier, :scope => 'all_users'}, :update => 'users-list', :frequency => 1, :with => 'query', :condition => '$("query").value.length > 2', :loading => '$("users-list").addClassName("loading")', :complete => '$("users-list").removeClassName("loading")') %>
9 <%= observe_field('query', :frequency => 1, :condition => '$("query").value.length <= 2', :function => '$("users-list").update($("empty-query").innerHTML)') %> 9 <%= observe_field('query', :frequency => 1, :condition => '$("query").value.length <= 2', :function => '$("users-list").update($("empty-query").innerHTML)') %>
10 10
11 <div id="users-list"> 11 <div id="users-list">
app/views/profile_members/find_users.rhtml
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 <table> 2 <table>
3 <tr><th><%= _('Name') %></th><th></th></tr> 3 <tr><th><%= _('Name') %></th><th></th></tr>
4 <% @users_found.each do |user| %> 4 <% @users_found.each do |user| %>
5 - <tr id="tr-<%= user.identifier %>"<%= profile.members.include?(user) ? 'style="display:none"' : '' %>> 5 + <tr id="tr-<%= user.identifier %>">
6 <td> 6 <td>
7 <div id="<%= user.identifier %>" class="draggable-user"> 7 <div id="<%= user.identifier %>" class="draggable-user">
8 <%= image_tag('/images/grip-clue.png') %> 8 <%= image_tag('/images/grip-clue.png') %>
@@ -14,10 +14,10 @@ @@ -14,10 +14,10 @@
14 <%= draggable_element(user.identifier, :revert => true) %> 14 <%= draggable_element(user.identifier, :revert => true) %>
15 </td> 15 </td>
16 <td> 16 <td>
17 - <%= button_to_remote_without_text(:add, _('Add member'), 17 + <%= button_to_remote_without_text(:add, @button_alt,
18 { :loading => '$("members-list").addClassName("loading")', 18 { :loading => '$("members-list").addClassName("loading")',
19 :update => 'members-list', 19 :update => 'members-list',
20 - :url => {:action => 'add_member', :profile => profile.identifier, :id => user.id}, 20 + :url => {:id => user.id, :profile => profile.identifier}.merge(@add_action),
21 :success => "$('tr-#{user.identifier}').hide()", 21 :success => "$('tr-#{user.identifier}').hide()",
22 :complete => '$("members-list").removeClassName("loading")'}) %> 22 :complete => '$("members-list").removeClassName("loading")'}) %>
23 23
app/views/profile_members/last_admin.rhtml 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +<h1><%= _('Last administrator leaving %s') % profile.name %></h1>
  2 +
  3 +<% if profile.members.count > 1 %>
  4 + <div id='last-admin-message'>
  5 + <%= _('Since you are the last administrator, you must choose at least one member to administer this community.') % profile.name %>
  6 + </div>
  7 +
  8 + <%= render :partial => 'add_admins' %>
  9 +
  10 + <% form_tag :action => 'update_roles', :roles => @roles, :person => @person, :confirmation => profile.admins.count > 1 do %>
  11 + <% button_bar do %>
  12 + <%= submit_button(:save, _("Leave administration and save"), :cancel => {:action => 'index'}) %>
  13 + <% end %>
  14 + <% end %>
  15 +
  16 +<% else %>
  17 +
  18 + <div id='last-admin-message'>
  19 + <%= _('Since you are the last administrator and there is no other member in this community, the next member to join this community will assume the administrator role.') % profile.name %>
  20 + </div>
  21 +
  22 + <% form_tag :action => 'update_roles', :roles => @roles, :person => @person, :confirmation => true do %>
  23 + <% button_bar do %>
  24 + <%= submit_button(:ok, _("Ok, I want to leave"), :cancel => {:action => 'index'}) %>
  25 + <% end %>
  26 + <% end %>
  27 +<% end %>
app/views/profile_members/remove_admin.rhtml 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +_members_list.rhtml
0 \ No newline at end of file 2 \ No newline at end of file
features/delete_profile.feature
@@ -7,6 +7,11 @@ Feature: delete profile @@ -7,6 +7,11 @@ Feature: delete profile
7 Given the following users 7 Given the following users
8 | login | name | 8 | login | name |
9 | joaosilva | Joao Silva | 9 | joaosilva | Joao Silva |
  10 + | mariasilva | Maria Silva |
  11 + And the following community
  12 + | identifier | name |
  13 + | sample-community | Sample Community |
  14 + And "Maria Silva" is a member of "Sample Community"
10 15
11 Scenario: deleting profile 16 Scenario: deleting profile
12 Given I am logged in as "joaosilva" 17 Given I am logged in as "joaosilva"
@@ -20,10 +25,7 @@ Feature: delete profile @@ -20,10 +25,7 @@ Feature: delete profile
20 Then I should see "There is no such page" 25 Then I should see "There is no such page"
21 26
22 Scenario: deleting other profile 27 Scenario: deleting other profile
23 - Given the following users  
24 - | login | name |  
25 - | mariasilva | Maria Silva |  
26 - And I am logged in as "mariasilva" 28 + Given I am logged in as "mariasilva"
27 And I go to /myprofile/joaosilva/profile_editor/destroy_profile 29 And I go to /myprofile/joaosilva/profile_editor/destroy_profile
28 Then I should see "Access denied" 30 Then I should see "Access denied"
29 31
@@ -37,20 +39,14 @@ Feature: delete profile @@ -37,20 +39,14 @@ Feature: delete profile
37 Then I should be on Joao Silva's profile 39 Then I should be on Joao Silva's profile
38 40
39 Scenario: community admin can see link to delete profile 41 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" 42 + Given "Joao Silva" is admin of "Sample Community"
44 And I am logged in as "joaosilva" 43 And I am logged in as "joaosilva"
45 And I am on Sample Community's control panel 44 And I am on Sample Community's control panel
46 When I follow "Community Info and settings" 45 When I follow "Community Info and settings"
47 Then I should see "Delete profile" 46 Then I should see "Delete profile"
48 47
49 Scenario: community admin deletes the community 48 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" 49 + Given "Joao Silva" is admin of "Sample Community"
54 And I am logged in as "joaosilva" 50 And I am logged in as "joaosilva"
55 And I am on Sample Community's control panel 51 And I am on Sample Community's control panel
56 And I follow "Community Info and settings" 52 And I follow "Community Info and settings"
@@ -62,10 +58,7 @@ Feature: delete profile @@ -62,10 +58,7 @@ Feature: delete profile
62 Then I should see "There is no such page" 58 Then I should see "There is no such page"
63 59
64 Scenario: community regular member tries to delete the community 60 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" 61 + Given "Joao Silva" is a member of "Sample Community"
69 And I am logged in as "joaosilva" 62 And I am logged in as "joaosilva"
70 And I go to /myprofile/sample-community/profile_editor/destroy_profile 63 And I go to /myprofile/sample-community/profile_editor/destroy_profile
71 Then I should see "Access denied" 64 Then I should see "Access denied"
@@ -96,19 +89,17 @@ Feature: delete profile @@ -96,19 +89,17 @@ Feature: delete profile
96 Then I should see "There is no such page" 89 Then I should see "There is no such page"
97 90
98 Scenario: enterprise regular member tries to delete the enterprise 91 Scenario: enterprise regular member tries to delete the enterprise
99 - Given the following community 92 + Given the following enterprise
100 | identifier | name | 93 | identifier | name |
101 | sample-enterprise | Sample Enterprise | 94 | sample-enterprise | Sample Enterprise |
  95 + And "Maria Silva" is a member of "Sample Enterprise"
102 And "Joao Silva" is a member of "Sample Enterprise" 96 And "Joao Silva" is a member of "Sample Enterprise"
103 And I am logged in as "joaosilva" 97 And I am logged in as "joaosilva"
104 And I go to /myprofile/sample-enterprise/profile_editor/destroy_profile 98 And I go to /myprofile/sample-enterprise/profile_editor/destroy_profile
105 Then I should see "Access denied" 99 Then I should see "Access denied"
106 100
107 Scenario: community regular member cannot see link to delete profile 101 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" 102 + Given "Joao Silva" is a member of "Sample Community"
112 And I am logged in as "joaosilva" 103 And I am logged in as "joaosilva"
113 And I am on Sample Community's control panel 104 And I am on Sample Community's control panel
114 When I follow "Community Info and settings" 105 When I follow "Community Info and settings"
features/last_administrator_leaving.feature 0 → 100644
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +Feature: remove administrator role
  2 + As an organization administrator
  3 + I want to remove my administrator role
  4 + In order to stop administrating the organization
  5 +
  6 + Background:
  7 + Given the following users
  8 + | login | name |
  9 + | joaosilva | Joao Silva |
  10 + | mariasouza | Maria Souza |
  11 + And the following community
  12 + | name | identifier |
  13 + | Nice people | nice-people |
  14 + And "Joao Silva" is admin of "Nice people"
  15 + And I am logged in as "joaosilva"
  16 +
  17 + Scenario: the last administrator and member removes his administrator role and the next member to join becomes the new administrator
  18 + Given I am on Nice people's members management
  19 + And I follow "Edit"
  20 + And I uncheck "Profile Administrator"
  21 + When I press "Save changes"
  22 + Then I should see "Since you are the last administrator and there is no other member in this community"
  23 + And I press "Ok, I want to leave"
  24 + And I am logged in as "mariasouza"
  25 + When I go to Nice people's join page
  26 + Then "Maria Souza" should be admin of "Nice people"
  27 +
  28 + Scenario: the last administrator and member removes his administrator role and the next member to join becomes the new administrator even if the organization is closed.
  29 + Given the community "Nice people" is closed
  30 + And I am on Nice people's members management
  31 + And I follow "Edit"
  32 + And I uncheck "Profile Administrator"
  33 + When I press "Save changes"
  34 + Then I should see "Since you are the last administrator and there is no other member in this community"
  35 + And I press "Ok, I want to leave"
  36 + And I am logged in as "mariasouza"
  37 + When I go to Nice people's join page
  38 + Then "Maria Souza" should be admin of "Nice people"
features/register_enterprise.feature
@@ -93,7 +93,7 @@ Feature: register enterprise @@ -93,7 +93,7 @@ Feature: register enterprise
93 Then I should see "Enterprise registration completed" 93 Then I should see "Enterprise registration completed"
94 And I am logged in as admin 94 And I am logged in as admin
95 And I go to the Control panel 95 And I go to the Control panel
96 - When I follow "Tasks" 96 + When I follow "Tasks" within ".control-panel"
97 Then I should see "Joao Silva wants to create enterprise My Enterprise." 97 Then I should see "Joao Silva wants to create enterprise My Enterprise."
98 And the first mail is to admin_user@example.com 98 And the first mail is to admin_user@example.com
99 And I choose "Accept" 99 And I choose "Accept"
@@ -120,7 +120,7 @@ Feature: register enterprise @@ -120,7 +120,7 @@ Feature: register enterprise
120 Then I should see "Enterprise registration completed" 120 Then I should see "Enterprise registration completed"
121 And I am logged in as admin 121 And I am logged in as admin
122 And I go to the Control panel 122 And I go to the Control panel
123 - When I follow "Tasks" 123 + When I follow "Tasks" within ".control-panel"
124 Then I should see "Joao Silva wants to create enterprise My Enterprise." 124 Then I should see "Joao Silva wants to create enterprise My Enterprise."
125 And the first mail is to admin_user@example.com 125 And the first mail is to admin_user@example.com
126 And I choose "Reject" 126 And I choose "Reject"
features/step_definitions/noosfero_steps.rb
@@ -16,13 +16,13 @@ Given /^&quot;(.+)&quot; is (online|offline|busy) in chat$/ do |user, status| @@ -16,13 +16,13 @@ Given /^&quot;(.+)&quot; is (online|offline|busy) in chat$/ do |user, status|
16 User.find_by_login(user).update_attributes(:chat_status => status, :chat_status_at => DateTime.now) 16 User.find_by_login(user).update_attributes(:chat_status => status, :chat_status_at => DateTime.now)
17 end 17 end
18 18
19 -Given /^the following (community|communities|enterprises?)$/ do |kind,table| 19 +Given /^the following (community|communities|enterprises?|organizations?)$/ do |kind,table|
20 klass = kind.singularize.camelize.constantize 20 klass = kind.singularize.camelize.constantize
21 table.hashes.each do |row| 21 table.hashes.each do |row|
22 owner = row.delete("owner") 22 owner = row.delete("owner")
23 - community = klass.create!(row) 23 + organization = klass.create!(row)
24 if owner 24 if owner
25 - community.add_admin(Profile[owner]) 25 + organization.add_admin(Profile[owner])
26 end 26 end
27 end 27 end
28 end 28 end
@@ -210,6 +210,12 @@ Given /^&quot;(.+)&quot; is admin of &quot;(.+)&quot;$/ do |person, organization| @@ -210,6 +210,12 @@ Given /^&quot;(.+)&quot; is admin of &quot;(.+)&quot;$/ do |person, organization|
210 org.add_admin(user) 210 org.add_admin(user)
211 end 211 end
212 212
  213 +Then /^"(.+)" should be admin of "(.+)"$/ do |person, organization|
  214 + org = Organization.find_by_name(organization)
  215 + user = Person.find_by_name(person)
  216 + org.admins.should include(user)
  217 +end
  218 +
213 Given /^"([^\"]*)" has no articles$/ do |profile| 219 Given /^"([^\"]*)" has no articles$/ do |profile|
214 (Profile[profile] || Profile.find_by_name(profile)).articles.delete_all 220 (Profile[profile] || Profile.find_by_name(profile)).articles.delete_all
215 end 221 end
@@ -317,3 +323,9 @@ Given /^the following comments?$/ do |table| @@ -317,3 +323,9 @@ Given /^the following comments?$/ do |table|
317 comment.save! 323 comment.save!
318 end 324 end
319 end 325 end
  326 +
  327 +Given /^the community "(.+)" is closed$/ do |community|
  328 + community = Community.find_by_name(community)
  329 + community.closed = true
  330 + community.save
  331 +end
features/support/paths.rb
@@ -36,6 +36,12 @@ module NavigationHelpers @@ -36,6 +36,12 @@ module NavigationHelpers
36 when /^the profile$/ 36 when /^the profile$/
37 '/profile/%s' % User.find_by_id(session[:user]).login 37 '/profile/%s' % User.find_by_id(session[:user]).login
38 38
  39 + when /^(.*)'s join page/
  40 + '/profile/%s/join' % Profile.find_by_name($1).identifier
  41 +
  42 + when /^(.*)'s leave page/
  43 + '/profile/%s/leave' % Profile.find_by_name($1).identifier
  44 +
39 when /^login page$/ 45 when /^login page$/
40 '/account/login' 46 '/account/login'
41 47
public/javascripts/add-and-join.js
@@ -23,8 +23,8 @@ jQuery(function($) { @@ -23,8 +23,8 @@ jQuery(function($) {
23 }); 23 });
24 clicked.css("cursor",""); 24 clicked.css("cursor","");
25 $(".small-loading").remove(); 25 $(".small-loading").remove();
26 - display_notice(data);  
27 - }); 26 + display_notice(data.message);
  27 + }, "json");
28 return false; 28 return false;
29 }) 29 })
30 30
@@ -33,15 +33,24 @@ jQuery(function($) { @@ -33,15 +33,24 @@ jQuery(function($) {
33 url = clicked.attr("href"); 33 url = clicked.attr("href");
34 loading_for_button(this); 34 loading_for_button(this);
35 $.post(url, function(data){ 35 $.post(url, function(data){
36 - clicked.fadeOut(function(){  
37 - clicked.css("display","none");  
38 - clicked.parent().parent().find(".join-community").fadeIn();  
39 - clicked.parent().parent().find(".join-community").css("display", "");  
40 - });  
41 - clicked.css("cursor","");  
42 - $(".small-loading").remove();  
43 - display_notice(data);  
44 - }); 36 + if(data.redirect_to){
  37 + document.location.href = data.redirect_to;
  38 + }
  39 + else if(data.reload){
  40 + document.location.reload(true);
  41 + }
  42 + else{
  43 + clicked.fadeOut(function(){
  44 + clicked.css("display","none");
  45 + clicked.parent().parent().find(".join-community").fadeIn();
  46 + clicked.parent().parent().find(".join-community").css("display", "");
  47 + });
  48 + clicked.css("cursor","");
  49 + $(".small-loading").remove();
  50 +
  51 + display_notice(data.message);
  52 + }
  53 + }, "json");
45 return false; 54 return false;
46 }) 55 })
47 56
public/stylesheets/application.css
@@ -1566,7 +1566,7 @@ a.comment-picture { @@ -1566,7 +1566,7 @@ a.comment-picture {
1566 a.button, a.button:visited, 1566 a.button, a.button:visited,
1567 body.noosfero a.button, body.noosfero a.button:visited, 1567 body.noosfero a.button, body.noosfero a.button:visited,
1568 input.button { 1568 input.button {
1569 - margin: 0px 2px; 1569 + margin: 0px 2px 0px 0px;
1570 background-repeat: no-repeat; 1570 background-repeat: no-repeat;
1571 background-position: 50% 50%; 1571 background-position: 50% 50%;
1572 padding: 3px 0px 3px 20px; 1572 padding: 3px 0px 3px 20px;
@@ -4094,6 +4094,15 @@ h1#agenda-title { @@ -4094,6 +4094,15 @@ h1#agenda-title {
4094 width: 100%; 4094 width: 100%;
4095 } 4095 }
4096 4096
  4097 +#last-admin-message {
  4098 + background-color: #CCC;
  4099 + color: #000;
  4100 + font-size: 14px;
  4101 + padding: 20px 15px;
  4102 + -moz-border-radius:10px;
  4103 + -webkit-border-radius:10px;
  4104 +}
  4105 +
4097 /* ==> public/stylesheets/controller_search.css <== */ 4106 /* ==> public/stylesheets/controller_search.css <== */
4098 /* @import url(pagination.css); ALREADY INCLUDED ABOVE */ 4107 /* @import url(pagination.css); ALREADY INCLUDED ABOVE */
4099 4108
test/functional/content_viewer_controller_test.rb
@@ -308,14 +308,16 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase @@ -308,14 +308,16 @@ class ContentViewerControllerTest &lt; Test::Unit::TestCase
308 end 308 end
309 309
310 should 'not show private content to members' do 310 should 'not show private content to members' do
311 - community = Community.create!(:name => 'testcomm')  
312 - Folder.create!(:name => 'test', :profile => community, :published => false)  
313 - community.add_member(profile) 311 + community = fast_create(Community)
  312 + admin = fast_create(Person)
  313 + community.add_member(admin)
314 314
  315 + folder = fast_create(Folder, :profile_id => community.id, :published => false)
  316 + community.add_member(profile)
315 login_as(profile.identifier) 317 login_as(profile.identifier)
316 318
317 @request.stubs(:ssl?).returns(true) 319 @request.stubs(:ssl?).returns(true)
318 - get :view_page, :profile => community.identifier, :page => [ 'test' ] 320 + get :view_page, :profile => community.identifier, :page => [ folder.path ]
319 321
320 assert_template 'access_denied.rhtml' 322 assert_template 'access_denied.rhtml'
321 end 323 end
test/functional/memberships_controller_test.rb
@@ -95,11 +95,11 @@ class MembershipsControllerTest &lt; Test::Unit::TestCase @@ -95,11 +95,11 @@ class MembershipsControllerTest &lt; Test::Unit::TestCase
95 assert_no_tag :tag => 'li', :content => /Description:/ 95 assert_no_tag :tag => 'li', :content => /Description:/
96 end 96 end
97 97
98 - should 'show link to leave from community' do 98 + should 'show link to leave from community with reload' do
99 community = Community.create!(:name => 'my test community', :description => 'description test') 99 community = Community.create!(:name => 'my test community', :description => 'description test')
100 community.add_member(profile) 100 community.add_member(profile)
101 get :index, :profile => profile.identifier 101 get :index, :profile => profile.identifier
102 - assert_tag :tag => 'a', :attributes => { :href => "/profile/#{community.identifier}/leave" }, :content => 'Leave' 102 + assert_tag :tag => 'a', :attributes => { :href => "/profile/#{community.identifier}/leave?reload=true" }, :content => 'Leave'
103 end 103 end
104 104
105 should 'current user is added as admin after create new community' do 105 should 'current user is added as admin after create new community' do
@@ -127,7 +127,9 @@ class MembershipsControllerTest &lt; Test::Unit::TestCase @@ -127,7 +127,9 @@ class MembershipsControllerTest &lt; Test::Unit::TestCase
127 end 127 end
128 128
129 should 'not display destroy link to normal members' do 129 should 'not display destroy link to normal members' do
130 - community = Community.create!(:name => 'A community to destroy') 130 + community = fast_create(Community)
  131 + admin = fast_create(Person)
  132 + community.add_member(admin)
131 133
132 person = Person['testuser'] 134 person = Person['testuser']
133 community.add_member(person) 135 community.add_member(person)
test/functional/profile_controller_test.rb
@@ -383,14 +383,28 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -383,14 +383,28 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
383 assert profile.memberships.include?(community), 'profile should be actually added to the community' 383 assert profile.memberships.include?(community), 'profile should be actually added to the community'
384 end 384 end
385 385
386 - should 'create task when join to closed organization' do  
387 - community = Community.create!(:name => 'my test community', :closed => true)  
388 - login_as @profile.identifier 386 + should 'create task when join to closed organization with members' do
  387 + community = fast_create(Community)
  388 + community.update_attribute(:closed, true)
  389 + admin = fast_create(Person)
  390 + community.add_member(admin)
  391 +
  392 + login_as profile.identifier
389 assert_difference AddMember, :count do 393 assert_difference AddMember, :count do
390 post :join, :profile => community.identifier 394 post :join, :profile => community.identifier
391 end 395 end
392 end 396 end
393 397
  398 + should 'not create task when join to closed and empty organization' do
  399 + community = fast_create(Community)
  400 + community.update_attribute(:closed, true)
  401 +
  402 + login_as profile.identifier
  403 + assert_no_difference AddMember, :count do
  404 + post :join, :profile => community.identifier
  405 + end
  406 + end
  407 +
394 should 'require login to join community' do 408 should 'require login to join community' do
395 community = Community.create!(:name => 'my test community', :closed => true) 409 community = Community.create!(:name => 'my test community', :closed => true)
396 get :join, :profile => community.identifier 410 get :join, :profile => community.identifier
@@ -399,7 +413,10 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -399,7 +413,10 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
399 end 413 end
400 414
401 should 'actually leave profile' do 415 should 'actually leave profile' do
402 - community = Community.create!(:name => 'my test community') 416 + community = fast_create(Community)
  417 + admin = fast_create(Person)
  418 + community.add_member(admin)
  419 +
403 community.add_member(profile) 420 community.add_member(profile)
404 assert_includes profile.memberships, community 421 assert_includes profile.memberships, community
405 422
@@ -417,6 +434,21 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -417,6 +434,21 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
417 assert_redirected_to :controller => 'account', :action => 'login' 434 assert_redirected_to :controller => 'account', :action => 'login'
418 end 435 end
419 436
  437 + should 'not leave if is last admin' do
  438 + community = fast_create(Community)
  439 +
  440 + community.add_admin(profile)
  441 + assert_includes profile.memberships, community
  442 +
  443 + login_as(profile.identifier)
  444 + post :leave, :profile => community.identifier
  445 +
  446 + profile.reload
  447 + assert_response :success
  448 + assert_match(/last_admin/, @response.body)
  449 + assert_includes profile.memberships, community
  450 + end
  451 +
420 should 'store location before login when request join via get not logged' do 452 should 'store location before login when request join via get not logged' do
421 community = Community.create!(:name => 'my test community') 453 community = Community.create!(:name => 'my test community')
422 454
test/functional/profile_members_controller_test.rb
@@ -236,22 +236,42 @@ class ProfileMembersControllerTest &lt; Test::Unit::TestCase @@ -236,22 +236,42 @@ class ProfileMembersControllerTest &lt; Test::Unit::TestCase
236 should 'find users' do 236 should 'find users' do
237 ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent') 237 ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent')
238 user = create_user_full('test_user').person 238 user = create_user_full('test_user').person
239 - u = create_user_with_permission('ent_user', 'manage_memberships', ent) 239 + person = create_user_with_permission('ent_user', 'manage_memberships', ent)
240 login_as :ent_user 240 login_as :ent_user
241 241
242 - get :find_users, :profile => ent.identifier, :query => 'test*' 242 + get :find_users, :profile => ent.identifier, :query => 'test*', :scope => 'all_users'
243 243
244 assert_includes assigns(:users_found), user 244 assert_includes assigns(:users_found), user
245 end 245 end
246 246
247 - should 'not appear add button for member in add members page' do 247 + should 'not display members when finding users in all_users scope' do
248 ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent') 248 ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent')
249 - p = create_user_with_permission('test_user', 'manage_memberships', ent)  
250 - login_as :test_user 249 + user = create_user_full('test_user').person
  250 +
  251 + person = create_user_with_permission('ent_user', 'manage_memberships', ent)
  252 + login_as :ent_user
  253 +
  254 + get :find_users, :profile => ent.identifier, :query => '*user', :scope => 'all_users'
  255 +
  256 + assert_tag :tag => 'a', :content => /#{user.name}/
  257 + assert_no_tag :tag => 'a', :content => /#{person.name}/
  258 + end
251 259
252 - get :find_users, :profile => ent.identifier, :query => 'test*' 260 + should 'not display admins when finding users in new_admins scope' do
  261 + ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent')
  262 +
  263 + person = create_user('admin_user').person
  264 + ent.add_admin(person)
  265 +
  266 + user = create_user_full('test_user').person
  267 + ent.add_member(user).finish
253 268
254 - assert_tag :tag => 'tr', :attributes => {:id => 'tr-test_user', :style => 'display:none'} 269 + login_as :admin_user
  270 +
  271 + get :find_users, :profile => ent.identifier, :query => '*user', :scope => 'new_admins'
  272 +
  273 + assert_tag :tag => 'a', :content => /#{user.name}/
  274 + assert_no_tag :tag => 'a', :content => /#{person.name}/
255 end 275 end
256 276
257 should 'return users with <query> as a prefix' do 277 should 'return users with <query> as a prefix' do
@@ -259,10 +279,10 @@ class ProfileMembersControllerTest &lt; Test::Unit::TestCase @@ -259,10 +279,10 @@ class ProfileMembersControllerTest &lt; Test::Unit::TestCase
259 daniela = create_user_full('daniela').person 279 daniela = create_user_full('daniela').person
260 280
261 ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent') 281 ent = fast_create(Enterprise, :name => 'Test Ent', :identifier => 'test_ent')
262 - p = create_user_with_permission('test_user', 'manage_memberships', ent) 282 + person = create_user_with_permission('test_user', 'manage_memberships', ent)
263 login_as :test_user 283 login_as :test_user
264 284
265 - get :find_users, :profile => ent.identifier, :query => 'daniel' 285 + get :find_users, :profile => ent.identifier, :query => 'daniel', :scope => 'all_users'
266 286
267 assert_includes assigns(:users_found), daniel 287 assert_includes assigns(:users_found), daniel
268 assert_includes assigns(:users_found), daniela 288 assert_includes assigns(:users_found), daniela
@@ -307,4 +327,32 @@ class ProfileMembersControllerTest &lt; Test::Unit::TestCase @@ -307,4 +327,32 @@ class ProfileMembersControllerTest &lt; Test::Unit::TestCase
307 assert_equal Profile['profile_admin_user'], assigns(:mailing).person 327 assert_equal Profile['profile_admin_user'], assigns(:mailing).person
308 end 328 end
309 329
  330 + should 'set a community member as admin' do
  331 + community = fast_create(Community)
  332 + admin = create_user_with_permission('admin_user', 'manage_memberships', community)
  333 + member = create_user('test_member').person
  334 + community.add_member(member)
  335 +
  336 + assert_not_includes community.admins, member
  337 +
  338 + login_as :admin_user
  339 + get :add_admin, :profile => community.identifier, :id => member.identifier
  340 +
  341 + assert_includes community.admins, member
  342 + end
  343 +
  344 + should 'remove a community admin' do
  345 + community = fast_create(Community)
  346 + admin = create_user_with_permission('admin_user', 'manage_memberships', community)
  347 + member = create_user('test_member').person
  348 + community.add_admin(member)
  349 +
  350 + assert_includes community.admins, member
  351 +
  352 + login_as :admin_user
  353 + get :remove_admin, :profile => community.identifier, :id => member.identifier
  354 +
  355 + assert_not_includes community.admins, member
  356 + end
  357 +
310 end 358 end
test/unit/application_helper_test.rb
@@ -96,11 +96,20 @@ class ApplicationHelperTest &lt; Test::Unit::TestCase @@ -96,11 +96,20 @@ class ApplicationHelperTest &lt; Test::Unit::TestCase
96 assert_equal 'black', role_color('none', Environment.default.id) 96 assert_equal 'black', role_color('none', Environment.default.id)
97 end 97 end
98 98
99 - should 'rolename for' do 99 + should 'rolename for first organization member' do
100 person = create_user('usertest').person 100 person = create_user('usertest').person
101 community = fast_create(Community, :name => 'new community', :identifier => 'new-community', :environment_id => Environment.default.id) 101 community = fast_create(Community, :name => 'new community', :identifier => 'new-community', :environment_id => Environment.default.id)
102 community.add_member(person) 102 community.add_member(person)
103 - assert_equal 'Profile Member', rolename_for(person, community) 103 + assert_equal 'Profile Administrator', rolename_for(person, community)
  104 + end
  105 +
  106 + should 'rolename for a member' do
  107 + member1 = create_user('usertest1').person
  108 + member2 = create_user('usertest2').person
  109 + community = fast_create(Community, :name => 'new community', :identifier => 'new-community', :environment_id => Environment.default.id)
  110 + community.add_member(member1)
  111 + community.add_member(member2)
  112 + assert_equal 'Profile Member', rolename_for(member2, community)
104 end 113 end
105 114
106 should 'get theme from environment by default' do 115 should 'get theme from environment by default' do
test/unit/community_test.rb
@@ -3,7 +3,7 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39; @@ -3,7 +3,7 @@ require File.dirname(__FILE__) + &#39;/../test_helper&#39;
3 class CommunityTest < Test::Unit::TestCase 3 class CommunityTest < Test::Unit::TestCase
4 4
5 def setup 5 def setup
6 - @person = create_user('testuser').person 6 + @person = fast_create(Person)
7 end 7 end
8 8
9 attr_reader :person 9 attr_reader :person
@@ -183,10 +183,33 @@ class CommunityTest &lt; Test::Unit::TestCase @@ -183,10 +183,33 @@ class CommunityTest &lt; Test::Unit::TestCase
183 end 183 end
184 end 184 end
185 185
  186 + should 'set as member without task if organization is closed and has no members' do
  187 + community = fast_create(Community)
  188 + community.closed = true
  189 + community.save
  190 +
  191 + assert_no_difference AddMember, :count do
  192 + community.add_member(person)
  193 + end
  194 + assert person.is_member_of?(community)
  195 + end
  196 +
  197 + should 'set as member without task if organization is not closed and has no members' do
  198 + community = fast_create(Community)
  199 +
  200 + assert_no_difference AddMember, :count do
  201 + community.add_member(person)
  202 + end
  203 + assert person.is_member_of?(community)
  204 + end
  205 +
186 should 'not create new request membership if it already exists' do 206 should 'not create new request membership if it already exists' do
187 community = fast_create(Community) 207 community = fast_create(Community)
188 community.closed = true 208 community.closed = true
189 community.save 209 community.save
  210 +
  211 + community.add_member(fast_create(Person))
  212 +
190 assert_difference AddMember, :count do 213 assert_difference AddMember, :count do
191 community.add_member(person) 214 community.add_member(person)
192 end 215 end
test/unit/enterprise_test.rb
@@ -102,14 +102,24 @@ class EnterpriseTest &lt; Test::Unit::TestCase @@ -102,14 +102,24 @@ class EnterpriseTest &lt; Test::Unit::TestCase
102 assert_not_includes result, ent2 102 assert_not_includes result, ent2
103 end 103 end
104 104
  105 + should 'allow to add new members if has no members' do
  106 + enterprise = fast_create(Enterprise)
  107 +
  108 + person = fast_create(Person)
  109 + enterprise.add_member(person)
  110 +
  111 + assert person.is_member_of?(enterprise)
  112 + end
  113 +
105 should 'not allow to add new members' do 114 should 'not allow to add new members' do
106 - o = fast_create(Enterprise, :name => 'my test profile', :identifier => 'mytestprofile')  
107 - p = create_user('mytestuser').person 115 + enterprise = fast_create(Enterprise)
  116 + member = fast_create(Person)
  117 + enterprise.add_member(member)
108 118
109 - o.add_member(p)  
110 - o.reload 119 + person = fast_create(Person)
  120 + enterprise.add_member(person)
111 121
112 - assert_not_includes o.members, p 122 + assert_equal false, person.is_member_of?(enterprise)
113 end 123 end
114 124
115 should 'allow to remove members' do 125 should 'allow to remove members' do
test/unit/person_test.rb
@@ -394,12 +394,16 @@ class PersonTest &lt; Test::Unit::TestCase @@ -394,12 +394,16 @@ class PersonTest &lt; Test::Unit::TestCase
394 end 394 end
395 395
396 should 'not allow simple member to view group pending tasks' do 396 should 'not allow simple member to view group pending tasks' do
397 - c = fast_create(Community)  
398 - c.tasks << Task.new  
399 - p = create_user('user_without_tasks').person  
400 - c.add_member(p) 397 + community = fast_create(Community)
  398 + member = fast_create(Person)
  399 + community.add_member(member)
  400 +
  401 + community.tasks << Task.new
401 402
402 - assert_not_includes Person.with_pending_tasks, p 403 + person = fast_create(Person)
  404 + community.add_member(person)
  405 +
  406 + assert_not_includes Person.with_pending_tasks, person
403 end 407 end
404 408
405 should 'person has organization pending tasks' do 409 should 'person has organization pending tasks' do
@@ -1116,4 +1120,29 @@ class PersonTest &lt; Test::Unit::TestCase @@ -1116,4 +1120,29 @@ class PersonTest &lt; Test::Unit::TestCase
1116 assert person.receives_scrap_notification? 1120 assert person.receives_scrap_notification?
1117 end 1121 end
1118 1122
  1123 + should 'check if person is the only admin' do
  1124 + person = fast_create(Person)
  1125 + organization = fast_create(Organization)
  1126 + organization.add_admin(person)
  1127 +
  1128 + assert person.is_last_admin?(organization)
  1129 + end
  1130 +
  1131 + should 'check if person is the last admin leaving the community' do
  1132 + person = fast_create(Person)
  1133 + organization = fast_create(Organization)
  1134 + organization.add_admin(person)
  1135 +
  1136 + assert person.is_last_admin_leaving?(organization, [])
  1137 + assert !person.is_last_admin_leaving?(organization, [Role.find_by_key('profile_admin')])
  1138 + end
  1139 +
  1140 + should 'return unique members of a community' do
  1141 + person = fast_create(Person)
  1142 + community = fast_create(Community)
  1143 + community.add_member(person)
  1144 +
  1145 + assert_equal [person], Person.members_of(community)
  1146 + assert_equal 1, Person.members_of(community).count
  1147 + end
1119 end 1148 end
test/unit/profile_test.rb
@@ -1406,7 +1406,12 @@ class ProfileTest &lt; Test::Unit::TestCase @@ -1406,7 +1406,12 @@ class ProfileTest &lt; Test::Unit::TestCase
1406 1406
1407 should 'provide URL to leave' do 1407 should 'provide URL to leave' do
1408 profile = build(Profile, :identifier => 'testprofile') 1408 profile = build(Profile, :identifier => 'testprofile')
1409 - assert_equal({ :profile => 'testprofile', :controller => 'profile', :action => 'leave'}, profile.leave_url) 1409 + assert_equal({ :profile => 'testprofile', :controller => 'profile', :action => 'leave', :reload => false}, profile.leave_url)
  1410 + end
  1411 +
  1412 + should 'provide URL to leave with reload' do
  1413 + profile = build(Profile, :identifier => 'testprofile')
  1414 + assert_equal({ :profile => 'testprofile', :controller => 'profile', :action => 'leave', :reload => true}, profile.leave_url(true))
1410 end 1415 end
1411 1416
1412 should 'provide URL to join' do 1417 should 'provide URL to join' do
@@ -1743,26 +1748,25 @@ class ProfileTest &lt; Test::Unit::TestCase @@ -1743,26 +1748,25 @@ class ProfileTest &lt; Test::Unit::TestCase
1743 end 1748 end
1744 1749
1745 should "return one member on label if the profile has one member" do 1750 should "return one member on label if the profile has one member" do
1746 - p = fast_create(Person)  
1747 - c = fast_create(Community)  
1748 - c.add_member(p)  
1749 - assert_equal 1, c.members.count  
1750 - assert_equal "one member", c.more_popular_label 1751 + person = fast_create(Person)
  1752 + community = fast_create(Community)
  1753 + community.add_member(person)
  1754 +
  1755 + assert_equal "one member", community.more_popular_label
1751 end 1756 end
1752 1757
1753 should "return the number of members on label if the profile has more than one member" do 1758 should "return the number of members on label if the profile has more than one member" do
1754 - p1 = fast_create(Person)  
1755 - p2 = fast_create(Person)  
1756 - c = fast_create(Community)  
1757 - c.add_member(p1)  
1758 - c.add_member(p2)  
1759 - assert_equal 2, c.members.count  
1760 - assert_equal "2 members", c.more_popular_label 1759 + person1 = fast_create(Person)
  1760 + person2 = fast_create(Person)
  1761 + community = fast_create(Community)
1761 1762
1762 - p3 = fast_create(Person)  
1763 - c.add_member(p3)  
1764 - assert_equal 3, c.members.count  
1765 - assert_equal "3 members", c.more_popular_label 1763 + community.add_member(person1)
  1764 + community.add_member(person2)
  1765 + assert_equal "2 members", community.more_popular_label
  1766 +
  1767 + person3 = fast_create(Person)
  1768 + community.add_member(person3)
  1769 + assert_equal "3 members", community.more_popular_label
1766 end 1770 end
1767 1771
1768 should 'provide list of galleries' do 1772 should 'provide list of galleries' do