Commit b4c6fe75d04829c418398e305d62c8b1d87c93ed

Authored by Joenio Costa
Committed by Antonio Terceiro
1 parent cfccb6db

Invite friends to join community

- invite friends refactored

(ActionItem1275)
app/controllers/my_profile/friends_controller.rb
1   -require "contacts"
2   -
3 1 class FriendsController < MyProfileController
4 2  
5 3 protect 'manage_friends', :profile
... ... @@ -30,83 +28,6 @@ class FriendsController &lt; MyProfileController
30 28 end
31 29 end
32 30  
33   - def invite
34   - @wizard = params[:wizard].blank? ? false : params[:wizard]
35   - @step = 3
36   - if request.post? && params[:import]
37   - begin
38   - case params[:import_from]
39   - when "gmail"
40   - @friends = Contacts::Gmail.new(params[:login], params[:password]).contacts
41   - when "yahoo"
42   - @friends = Contacts::Yahoo.new(params[:login], params[:password]).contacts
43   - when "hotmail"
44   - @friends = Contacts::Hotmail.new(params[:login], params[:password]).contacts
45   - else
46   - @friends = []
47   - end
48   - @friends.map! {|friend| friend + ["#{friend[0]} <#{friend[1]}>"]}
49   - rescue
50   - @login = params[:login]
51   - flash.now[:notice] = __('There was an error while looking for your contact list. Did you enter correct login and password?')
52   - end
53   -
54   - elsif request.post? && params[:confirmation]
55   - friends_to_invite = []
56   - friends_to_invite += (params[:manual_import_addresses].is_a?(Array) ? params[:manual_import_addresses] : params[:manual_import_addresses].split("\r\n")) if params[:manual_import_addresses]
57   - friends_to_invite += (params[:webmail_import_addresses].is_a?(Array) ? params[:webmail_import_addresses] : params[:webmail_import_addresses].split("\r\n")) if params[:webmail_import_addresses]
58   -
59   - if !params[:message].match(/<url>/)
60   - flash.now[:notice] = __('&lt;url&gt; is needed in invitation message.')
61   - elsif !friends_to_invite.empty?
62   - friends_to_invite.each do |friend_to_invite|
63   - next if friend_to_invite == __("Firstname Lastname <friend@email.com>")
64   -
65   - friend_to_invite.strip!
66   - if match = friend_to_invite.match(/(.*)<(.*)>/) and match[2].match(Noosfero::Constants::EMAIL_FORMAT)
67   - friend_name = match[1].strip
68   - friend_email = match[2]
69   - elsif match = friend_to_invite.strip.match(Noosfero::Constants::EMAIL_FORMAT)
70   - friend_name = ""
71   - friend_email = match[0]
72   - else
73   - next
74   - end
75   -
76   - friend = User.find_by_email(friend_email)
77   - if friend.nil?
78   - InviteFriend.create(:person => profile, :friend_name => friend_name, :friend_email => friend_email, :message => params[:message])
79   - elsif !friend.person.is_a_friend?(profile)
80   - InviteFriend.create(:person => profile, :friend => friend.person)
81   - end
82   - end
83   -
84   - flash[:notice] = __('Your invitations have been sent.')
85   - if @wizard
86   - redirect_to :action => 'invite', :wizard => true
87   - return
88   - else
89   - redirect_to :action => 'index'
90   - end
91   - else
92   - flash.now[:notice] = __('Please enter a valid email address.')
93   - end
94   -
95   - @friends = params[:webmail_friends] ? params[:webmail_friends].map {|e| YAML.load(e)} : []
96   - @manual_import_addresses = params[:manual_import_addresses] || ""
97   - @webmail_import_addresses = params[:webmail_import_addresses] || []
98   - end
99   -
100   - @import_from = params[:import_from] || "manual"
101   - @message = params[:message] || environment.message_for_friend_invitation
102   - if @wizard
103   - if !params[:import]
104   - @friends = []
105   - end
106   - render :layout => 'wizard'
107   - end
108   - end
109   -
110 31 protected
111 32  
112 33 class << self
... ... @@ -117,4 +38,5 @@ class FriendsController &lt; MyProfileController
117 38 def per_page
118 39 self.class.per_page
119 40 end
  41 +
120 42 end
... ...
app/controllers/public/invite_controller.rb 0 → 100644
... ... @@ -0,0 +1,50 @@
  1 +class InviteController < PublicController
  2 +
  3 + needs_profile
  4 + before_filter :login_required
  5 + before_filter :check_permissions_to_invite, :only => 'friends'
  6 +
  7 + def friends
  8 + step = params[:step]
  9 + if request.post?
  10 + if step == '1'
  11 + begin
  12 + @contacts = Invitation.get_contacts(params[:import_from], params[:login], params[:password])
  13 + rescue
  14 + @login = params[:login]
  15 + flash.now[:notice] = _('There was an error while looking for your contact list. Did you enter correct login and password?')
  16 + end
  17 + elsif step == '2'
  18 + manual_import_addresses = params[:manual_import_addresses]
  19 + webmail_import_addresses = params[:webmail_import_addresses]
  20 + contacts_to_invite = Invitation.join_contacts(manual_import_addresses, webmail_import_addresses)
  21 + if !params[:mail_template].match(/<url>/)
  22 + flash.now[:notice] = _('&lt;url&gt; is needed in invitation mail.')
  23 + elsif !contacts_to_invite.empty?
  24 + Invitation.invite(current_user.person, contacts_to_invite, params[:mail_template], profile)
  25 + flash[:notice] = _('Your invitations have been sent.')
  26 + redirect_back_or_default :controller => 'profile'
  27 + else
  28 + flash.now[:notice] = _('Please enter a valid email address.')
  29 + end
  30 + @contacts = params[:webmail_friends] ? params[:webmail_friends].map {|e| YAML.load(e)} : []
  31 + @manual_import_addresses = manual_import_addresses || ""
  32 + @webmail_import_addresses = webmail_import_addresses || []
  33 + end
  34 + else
  35 + store_location(request.referer)
  36 + end
  37 + @import_from = params[:import_from] || "manual"
  38 + @mail_template = params[:mail_template] || environment.invitation_mail_template(profile)
  39 + end
  40 +
  41 + protected
  42 +
  43 + def check_permissions_to_invite
  44 + if profile.person? and !current_user.person.has_permission?(:manage_friends, profile) or
  45 + profile.community? and !current_user.person.has_permission?(:invite_members, profile)
  46 + render_access_denied
  47 + end
  48 + end
  49 +
  50 +end
... ...
app/helpers/invite_helper.rb 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +module InviteHelper
  2 +end
... ...
app/models/environment.rb
... ... @@ -385,21 +385,30 @@ class Environment &lt; ActiveRecord::Base
385 385 signup_fields
386 386 end
387 387  
388   - # Default message send to friend when user use invite a friend feature
  388 + def invitation_mail_template(profile)
  389 + if profile.person?
  390 + message_for_friend_invitation
  391 + else
  392 + message_for_member_invitation
  393 + end
  394 + end
  395 +
389 396 def message_for_friend_invitation
390   - self.settings['message_for_friend_invitation'] || [
391   - _('Hello <friend>,'),
392   - _('<user> is inviting you to participate on %{environment}.') % { :environment => self.name },
393   - _('To accept the invitation, please follow this link:') + "\n" + '<url>',
394   - "--\n#{self.name}",
395   - ''
396   - ].join("\n\n")
  397 + self.settings['message_for_friend_invitation'] || InviteFriend.mail_template
397 398 end
398 399  
399 400 def message_for_friend_invitation=(value)
400 401 self.settings['message_for_friend_invitation'] = value
401 402 end
402 403  
  404 + def message_for_member_invitation
  405 + self.settings['message_for_member_invitation'] || InviteMember.mail_template
  406 + end
  407 +
  408 + def message_for_member_invitation=(value)
  409 + self.settings['message_for_member_invitation'] = value
  410 + end
  411 +
403 412 def custom_enterprise_fields
404 413 self.settings[:custom_enterprise_fields].nil? ? {} : self.settings[:custom_enterprise_fields]
405 414 end
... ...
app/models/invitation.rb 0 → 100644
... ... @@ -0,0 +1,113 @@
  1 +class Invitation < Task
  2 +
  3 + acts_as_having_settings :field => :data
  4 + settings_items :message, :friend_name, :friend_email
  5 +
  6 + validates_presence_of :requestor_id
  7 +
  8 + validates_presence_of :target_id, :if => Proc.new{|invite| invite.friend_email.blank?}
  9 +
  10 + validates_presence_of :friend_email, :if => Proc.new{|invite| invite.target_id.blank?}
  11 + validates_format_of :friend_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => Proc.new{|invite| invite.target_id.blank?}
  12 +
  13 + validates_presence_of :message, :if => Proc.new{|invite| invite.target_id.blank?}
  14 + validates_format_of :message, :with => /<url>/, :if => Proc.new{|invite| invite.target_id.blank?}
  15 +
  16 + alias :person :requestor
  17 + alias :person= :requestor=
  18 +
  19 + alias :friend :target
  20 + alias :friend= :target=
  21 +
  22 + after_create do |task|
  23 + TaskMailer.deliver_invitation_notification(task) unless task.friend
  24 + end
  25 +
  26 + def validate
  27 + super
  28 + email = friend ? friend.user.email : friend_email
  29 + if person && email && person.user.email == email
  30 + self.errors.add_to_base(_("You can't invite youself"))
  31 + end
  32 + end
  33 +
  34 + # Returns <tt>false</tt>. Adding friends by itself does not trigger e-mail
  35 + # sending.
  36 + def sends_email?
  37 + false
  38 + end
  39 +
  40 + def self.invite(person, contacts_to_invite, message, profile)
  41 + contacts_to_invite.each do |contact_to_invite|
  42 + next if contact_to_invite == _("Firstname Lastname <friend@email.com>")
  43 +
  44 + contact_to_invite.strip!
  45 + if match = contact_to_invite.match(/(.*)<(.*)>/) and match[2].match(Noosfero::Constants::EMAIL_FORMAT)
  46 + friend_name = match[1].strip
  47 + friend_email = match[2]
  48 + elsif match = contact_to_invite.strip.match(Noosfero::Constants::EMAIL_FORMAT)
  49 + friend_name = ""
  50 + friend_email = match[0]
  51 + else
  52 + next
  53 + end
  54 +
  55 + user = User.find_by_email(friend_email)
  56 +
  57 + task_args = if user.nil?
  58 + {:person => person, :friend_name => friend_name, :friend_email => friend_email, :message => message}
  59 + elsif !user.person.is_a_friend?(person)
  60 + {:person => person, :target => user.person}
  61 + end
  62 +
  63 + if profile.person?
  64 + InviteFriend.create(task_args)
  65 + elsif profile.community?
  66 + InviteMember.create(task_args.merge(:community_id => profile.id))
  67 + else
  68 + raise NotImplementedError, 'Don\'t know how to invite people to a %s' % profile.class.to_s
  69 + end
  70 + end
  71 + end
  72 +
  73 + def self.get_contacts(source, login, password)
  74 + contacts = []
  75 + case source
  76 + when "gmail"
  77 + contacts = Contacts::Gmail.new(login, password).contacts
  78 + when "yahoo"
  79 + contacts = Contacts::Yahoo.new(login, password).contacts
  80 + when "hotmail"
  81 + contacts = Contacts::Hotmail.new(login, password).contacts
  82 + when "manual"
  83 + #do nothing
  84 + else
  85 + raise NotImplementedError, 'Unknown source to get contacts'
  86 + end
  87 + contacts.map { |contact| contact + ["#{contact[0]} <#{contact[1]}>"] }
  88 + end
  89 +
  90 + def self.join_contacts(manual_import_addresses, webmail_import_addresses)
  91 + contacts = []
  92 + if manual_import_addresses
  93 + contacts += manual_import_addresses.is_a?(Array) ? manual_import_addresses : manual_import_addresses.split
  94 + end
  95 + if webmail_import_addresses
  96 + contacts += webmail_import_addresses.is_a?(Array) ? webmail_import_addresses : webmail_import_addresses.split
  97 + end
  98 + contacts
  99 + end
  100 +
  101 + def expanded_message
  102 + msg = message
  103 + msg = msg.gsub /<user>/, person.name
  104 + msg = msg.gsub /<friend>/, friend_name.blank? ? friend_email : friend_name
  105 + msg = msg.gsub /<environment>/, person.environment.name
  106 + msg
  107 + end
  108 +
  109 + def mail_template
  110 + raise 'You should implement mail_template in a subclass'
  111 + end
  112 +
  113 +end
... ...
app/models/invite_friend.rb
1   -class InviteFriend < Task
  1 +class InviteFriend < Invitation
2 2  
3   - acts_as_having_settings :group_for_person, :group_for_friend, :message, :friend_name, :friend_email, :field => :data
4   -
5   - validates_presence_of :requestor_id
6   -
7   - validates_presence_of :target_id, :if => Proc.new{|invite| invite.friend_email.blank? }
8   -
9   - validates_presence_of :friend_email, :if => Proc.new{|invite| invite.target_id.blank? }
10   - validates_format_of :friend_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => Proc.new{|invite| invite.target_id.blank? }
11   -
12   - validates_presence_of :message, :if => Proc.new{|invite| invite.target_id.blank? }
13   - validates_format_of :message, :with => /<url>/, :if => Proc.new{|invite| invite.target_id.blank? }
14   -
15   - alias :person :requestor
16   - alias :person= :requestor=
17   -
18   - alias :friend :target
19   - alias :friend= :target=
20   -
21   - after_create do |task|
22   - TaskMailer.deliver_invitation_notification(task) unless task.friend
23   - end
24   -
25   - def validate
26   - super
27   - friendemail = friend ? friend.user.email : friend_email
28   - if person && friendemail && person.user.email == friendemail
29   - self.errors.add_to_base(_("You can't invite youself"))
30   - end
31   - end
  3 + settings_items :group_for_person, :group_for_friend
32 4  
33 5 def perform
34   - requestor.add_friend(target, group_for_person)
35   - target.add_friend(requestor, group_for_friend)
36   - end
37   -
38   - # Returns <tt>false</tt>. Adding friends by itself does not trigger e-mail
39   - # sending.
40   - def sends_email?
41   - false
  6 + person.add_friend(friend, group_for_person)
  7 + friend.add_friend(person, group_for_friend)
42 8 end
43 9  
44 10 def description
45   - _('%s wants to be your friend.') % [requestor.name]
  11 + _('%s wants to be your friend.') % [person.name]
46 12 end
47 13  
48 14 def permission
49 15 :manage_friends
50 16 end
  17 +
  18 + # Default message send to friend when user use invite a friend feature
  19 + def self.mail_template
  20 + [ _('Hello <friend>,'),
  21 + _('<user> is inviting you to participate on <environment>.'),
  22 + _('To accept the invitation, please follow this link:'),
  23 + '<url>',
  24 + "--\n<environment>",
  25 + ].join("\n\n")
  26 + end
  27 +
51 28 end
... ...
app/models/invite_member.rb 0 → 100644
... ... @@ -0,0 +1,36 @@
  1 +class InviteMember < Invitation
  2 +
  3 + settings_items :community_id, :type => :integer
  4 + validates_presence_of :community_id
  5 +
  6 + def community
  7 + Community.find(community_id)
  8 + end
  9 +
  10 + def community=(newcommunity)
  11 + community_id = newcommunity.id
  12 + end
  13 +
  14 + def perform
  15 + community.add_member(friend)
  16 + end
  17 +
  18 + def description
  19 + _('%s invites you to join the community %s.') % [person.name, community.name]
  20 + end
  21 +
  22 + def expanded_message
  23 + super.gsub /<community>/, community.name
  24 + end
  25 +
  26 + # Default message send to friend when user use invite a friend feature
  27 + def self.mail_template
  28 + [ _('Hello <friend>,'),
  29 + _('<user> is inviting you to participate of <community> on <environment>.'),
  30 + _('To accept the invitation, please follow this link:'),
  31 + '<url>',
  32 + "--\n<environment>",
  33 + ].join("\n\n")
  34 + end
  35 +
  36 +end
... ...
app/models/profile.rb
... ... @@ -43,6 +43,7 @@ class Profile &lt; ActiveRecord::Base
43 43 'edit_appearance' => N_('Edit appearance'),
44 44 'view_private_content' => N_('View private content'),
45 45 'publish_content' => N_('Publish content'),
  46 + 'invite_members' => N_('Invite members'),
46 47 }
47 48  
48 49 acts_as_accessible
... ...
app/models/task_mailer.rb
... ... @@ -27,10 +27,8 @@ class TaskMailer &lt; ActionMailer::Base
27 27 end
28 28  
29 29 def invitation_notification(task)
30   - msg = task.message
31   - msg = msg.gsub(/<user>/, task.requestor.name)
32   - msg = msg.gsub(/<friend>/, task.friend_name.blank? ? task.friend_email : task.friend_name)
33   - msg = msg.gsub(/<url>/, generate_environment_url(task, :controller => 'account', :action => 'signup', :invitation_code => task.code))
  30 + msg = task.expanded_message
  31 + msg = msg.gsub /<url>/, generate_environment_url(task, :controller => 'account', :action => 'signup', :invitation_code => task.code)
34 32  
35 33 recipients task.friend_email
36 34  
... ...
app/views/friends/index.rhtml
... ... @@ -14,7 +14,7 @@
14 14 <% button_bar do %>
15 15 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %>
16 16 <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %>
17   - <%= button(:search, _('Invite people from my e-mail contacts'), :action => 'invite') %>
  17 + <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'friends') %>
18 18 <% end %>
19 19 <% end %>
20 20  
... ... @@ -45,7 +45,7 @@
45 45 <% button_bar do %>
46 46 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %>
47 47 <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %>
48   - <%= button(:search, _('Invite people from my e-mail contacts'), :action => 'invite') %>
  48 + <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'friends') %>
49 49 <% end %>
50 50 <% end %>
51 51  
... ...
app/views/friends/invite.rhtml
... ... @@ -1,107 +0,0 @@
1   -<% if @wizard %>
2   - <%= render :partial => 'account/wizard_steps'%>
3   -<% end %>
4   -
5   -<h1><%= __('Invite your friends') %></h1>
6   -
7   -<% unless @friends %>
8   -
9   - <% if !@wizard %>
10   - <h2><%= __('Step 1 of 1: Select address book') %></h2>
11   - <% end %>
12   -
13   - <% form_tag do %>
14   - <%= hidden_field_tag(:import, 1) %>
15   -
16   - <%= hidden_field_tag(:wizard, @wizard) %>
17   -
18   - <%= [
19   - radio_button_tag(:import_from, "manual", @import_from == "manual", :onclick => 'hide_invite_friend_login_password()') + content_tag('label', __('Manually (empty field)'), :for => "import_from_manual"),
20   - radio_button_tag(:import_from, "gmail", @import_from == "gmail", :onclick => 'show_invite_friend_login_password()') + content_tag('label', 'Gmail', :for => 'import_from_gmail'),
21   - radio_button_tag(:import_from, "yahoo", @import_from == "yahoo", :onclick => 'show_invite_friend_login_password()') + content_tag('label', 'Yahoo', :for => "import_from_yahoo"),
22   - radio_button_tag(:import_from, "hotmail", @import_from == "hotmail", :onclick => 'show_invite_friend_login_password()') + content_tag('label', 'Hotmail', :for => "import_from_hotmail")
23   - ].join("\n<br/>\n") %>
24   -
25   - <script type="text/javascript">
26   - function hide_invite_friend_login_password() {
27   - $('invite-friends-login-password').hide();
28   - }
29   - function show_invite_friend_login_password() {
30   - $('invite-friends-login-password').show();
31   - $('login').focus();
32   - }
33   - </script>
34   - <div id='invite-friends-login-password' <%= "style='display: none;'" if (@import_from == 'manual') %>>
35   - <%= labelled_form_field(__("Username") + ":", text_field_tag(:login, @login)) %>
36   - <%= labelled_form_field(__("Password") + ":", password_field_tag(:password)) %>
37   - </div>
38   -
39   - <% button_bar do %>
40   - <%= submit_button(:forward, __("Next")) %>
41   - <% end %>
42   - <p><%= __("We won't store your password or contact anyone without your permission.")%></p>
43   -
44   - <% end %>
45   -
46   -<% else %>
47   -
48   - <% if !@wizard %>
49   - <h2><%= __('Step 2 of 2: Selecting Friends') %></h2>
50   - <% end %>
51   - <p>
52   - <%= __('Indicate which friends you want to invite.') %>
53   - </p>
54   -
55   - <% if @wizard && @import_from == 'manual' %>
56   - <div>
57   - <%= __('Import now your contacts from %s, %s or %s') % [link_to_import('GMail', :import_from => 'gmail'), link_to_import('Yahoo', :import_from => 'yahoo'), link_to_import('Hotmail', :import_from => 'hotmail')] %>
58   - </div>
59   - <div>
60   - <%= _('or') %>
61   - </div>
62   - <% end %>
63   -
64   - <% form_tag do %>
65   - <%= hidden_field_tag(:confirmation, 1) %>
66   - <%= hidden_field_tag(:import_from, @import_from) %>
67   - <%= hidden_field_tag(:wizard, @wizard) %>
68   -
69   - <div>
70   - <%= __('Enter one e-mail address per line:') %>
71   - <%= text_area_tag(:manual_import_addresses, (@manual_import_addresses || ''), :cols => 72, :rows => 5) %>
72   - </div>
73   - <% if @import_from != 'manual' %>
74   - <div>
75   - <%= link_to_function __('Check all'), "$$('input.friend_to_invite').each(function(checkbox) { checkbox.checked = true; });" %>
76   - <%= link_to_function __('Uncheck all'), "$$('input.friend_to_invite').each(function(checkbox) { checkbox.checked = false; });" %>
77   - <% friend_pos = 0 %>
78   - <div id='friends-list'>
79   - <% @friends.each do |friend| %>
80   - <% friend_pos += 1 %>
81   - <p>
82   - <%= hidden_field_tag("webmail_friends[]", friend.to_yaml) %>
83   - <%= check_box_tag("webmail_import_addresses[]", friend[2], (!@webmail_import_addresses || @webmail_import_addresses.include?(friend[2])), :id => "friends_to_invite_#{friend_pos}", :class => "friend_to_invite" ) %><label for="<%= "friends_to_invite_#{friend_pos}" %>"><%= "#{friend[0]} (#{friend[1]})" %></label>
84   - </p>
85   - <% end %>
86   - </div>
87   - </div>
88   - <% end -%>
89   -
90   - <br/>
91   -
92   - <%= link_to_function(_('Personalize invitation message'), nil) do |page|
93   - page['invitation-message'].show
94   - end %>
95   -
96   - <div id='invitation-message' style='display:none'>
97   - <%= h __("Now enter an invitation message. You must keep the <url> code in your invitation message. When your friends receive the invitation e-mail, <url> will be replaced by a link that they need to click to activate their account. <user> and <friend> codes will be replaced by your name and friend name, but they are optional.") %>
98   - <%= labelled_form_field(__('Invitation message:'), text_area_tag(:message, @message, :cols => 72, :rows => 8)) %>
99   - </div>
100   -
101   - <% button_bar do %>
102   - <%= submit_button(:ok, __("Invite my friends!")) %>
103   - <% end %>
104   - <% end %>
105   -
106   -<% end %>
107   -
app/views/invite/friends.rhtml 0 → 100644
... ... @@ -0,0 +1,93 @@
  1 +<% if profile.person? %>
  2 + <h1><%= _('Invite your friends') %></h1>
  3 +<% else %>
  4 + <h1><%= _('Invite your friends to join %s') % profile.name %></h1>
  5 +<% end %>
  6 +
  7 +<% unless @contacts %>
  8 +
  9 + <h2><%= _('Step 1 of 2: Select address book') %></h2>
  10 +
  11 + <% form_tag do %>
  12 + <%= hidden_field_tag(:step, 1) %>
  13 +
  14 + <%= [
  15 + radio_button_tag(:import_from, "manual", @import_from == "manual", :onclick => 'hide_invite_friend_login_password()') + content_tag('label', _('Manually (empty field)'), :for => "import_from_manual"),
  16 + radio_button_tag(:import_from, "gmail", @import_from == "gmail", :onclick => 'show_invite_friend_login_password()') + content_tag('label', 'Gmail', :for => 'import_from_gmail'),
  17 + radio_button_tag(:import_from, "yahoo", @import_from == "yahoo", :onclick => 'show_invite_friend_login_password()') + content_tag('label', 'Yahoo', :for => "import_from_yahoo"),
  18 + radio_button_tag(:import_from, "hotmail", @import_from == "hotmail", :onclick => 'show_invite_friend_login_password()') + content_tag('label', 'Hotmail', :for => "import_from_hotmail")
  19 + ].join("\n<br/>\n") %>
  20 +
  21 + <script type="text/javascript">
  22 + function hide_invite_friend_login_password() {
  23 + $('invite-friends-login-password').hide();
  24 + }
  25 + function show_invite_friend_login_password() {
  26 + $('invite-friends-login-password').show();
  27 + $('login').focus();
  28 + }
  29 + </script>
  30 + <div id='invite-friends-login-password' <%= "style='display: none;'" if (@import_from == 'manual') %>>
  31 + <%= labelled_form_field(_("Username") + ":", text_field_tag(:login, @login)) %>
  32 + <%= labelled_form_field(_("Password") + ":", password_field_tag(:password)) %>
  33 + </div>
  34 +
  35 + <% button_bar do %>
  36 + <%= submit_button(:forward, _("Next")) %>
  37 + <% end %>
  38 + <p><%= _("We won't store your password or contact anyone without your permission.") %></p>
  39 + <% end %>
  40 +
  41 +<% else %>
  42 +
  43 + <h2><%= _('Step 2 of 2: Selecting Friends') %></h2>
  44 + <p>
  45 + <%= _('Indicate which friends you want to invite.') %>
  46 + </p>
  47 +
  48 + <% form_tag do %>
  49 + <%= hidden_field_tag(:step, 2) %>
  50 + <%= hidden_field_tag(:import_from, @import_from) %>
  51 +
  52 + <div>
  53 + <%= labelled_form_field(_('Enter one e-mail address per line:'), text_area_tag(:manual_import_addresses, (@manual_import_addresses || ''), :cols => 72, :rows => 5)) %>
  54 + </div>
  55 + <% if @import_from != 'manual' %>
  56 + <div>
  57 + <%= link_to_function _('Check all'), "$$('input.contact_to_invite').each(function(checkbox) { checkbox.checked = true; });" %>
  58 + <%= link_to_function _('Uncheck all'), "$$('input.contact_to_invite').each(function(checkbox) { checkbox.checked = false; });" %>
  59 + <% friend_pos = 0 %>
  60 + <div id='contacts-list'>
  61 + <% @contacts.each do |contact| %>
  62 + <% friend_pos += 1 %>
  63 + <p>
  64 + <%= hidden_field_tag("webmail_friends[]", contact.to_yaml) %>
  65 + <%= check_box_tag("webmail_import_addresses[]", contact[2],
  66 + (!@webmail_import_addresses || @webmail_import_addresses.include?(contact[2])),
  67 + :id => "contacts_to_invite_#{friend_pos}",
  68 + :class => "contact_to_invite" )
  69 + %>
  70 + <label for="<%= "contacts_to_invite_#{friend_pos}" %>"><%= "#{contact[0]} (#{contact[1]})" %></label>
  71 + </p>
  72 + <% end %>
  73 + </div>
  74 + </div>
  75 + <% end -%>
  76 +
  77 + <br/>
  78 +
  79 + <%= link_to_function(_('Personalize invitation mail'), nil) do |page|
  80 + page['invitation-mail_template'].show
  81 + end %>
  82 +
  83 + <div id='invitation-mail_template' style='display:none'>
  84 + <%= h _("Now enter an invitation message. You must keep the <url> code in your invitation mail_template. When your friends receive the invitation e-mail, <url> will be replaced by a link that they need to click to activate their account. <user> and <friend> codes will be replaced by your name and friend name, but they are optional.") %>
  85 + <%= labelled_form_field(_('Invitation mail_template:'), text_area_tag(:mail_template, @mail_template, :cols => 72, :rows => 8)) %>
  86 + </div>
  87 +
  88 + <% button_bar do %>
  89 + <%= submit_button(:ok, _("Invite my friends!")) %>
  90 + <% end %>
  91 + <% end %>
  92 +
  93 +<% end %>
... ...
app/views/profile/friends.rhtml
... ... @@ -16,11 +16,11 @@
16 16 <% end %>
17 17  
18 18 <% button_bar do %>
  19 + <%= button :back, _('Go back'), { :controller => 'profile' }, :help => _('Back to the page where you come from.') %>
19 20 <% if user == profile %>
20 21 <%= button :edit, _('Manage my friends'), :controller => 'friends', :action => 'index', :profile => profile.identifier %>
  22 + <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'friends') %>
21 23 <% end %>
22   - <%= button :back, _('Go back'), { :controller => 'profile' },
23   - :help => _('Back to the page where you come from.') %>
24 24 <% end %>
25 25  
26 26 </div><!-- fim class="common-profile-list-block" -->
... ...
app/views/profile/members.rhtml
... ... @@ -10,9 +10,10 @@
10 10 </ul>
11 11  
12 12 <% button_bar do %>
13   - <%= button :back, _('Go back'), { :controller => 'profile' },
14   - :help => _('Back to the page where you come from.') %>
  13 + <%= button :back, _('Go back'), { :controller => 'profile' }, :help => _('Back to the page where you come from.') %>
  14 + <% if profile.community? and user and user.has_permission?(:invite_members, profile) %>
  15 + <%= button :search, _('Invite your friends to join %s') % profile.name, :controller => 'invite', :action => 'friends' %>
  16 + <% end %>
15 17 <% end %>
16 18  
17 19 </div><!-- fim class="common-profile-list-block" -->
18   -
... ...
app/views/profile_members/index.rhtml
... ... @@ -5,4 +5,7 @@
5 5 <% button_bar do %>
6 6 <%= button :back, _('Back'), :controller => 'profile_editor' %>
7 7 <%= button :add, _('Add members'), :action => 'add_members' if profile.enterprise? %>
  8 + <% if profile.community? and user.has_permission?(:invite_members, profile) %>
  9 + <%= button :search, _('Invite your friends to join %s') % profile.name, :controller => 'invite', :action => 'friends' %>
  10 + <% end %>
8 11 <% end %>
... ...
config/routes.rb
... ... @@ -58,13 +58,16 @@ ActionController::Routing::Routes.draw do |map|
58 58 map.events 'profile/:profile/events/:year/:month', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :profile => /#{Noosfero.identifier_format}/
59 59 map.events 'profile/:profile/events', :controller => 'events', :action => 'events', :profile => /#{Noosfero.identifier_format}/
60 60  
61   - # public profile information
62   - map.profile 'profile/:profile/:action/:id', :controller => 'profile', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format}/
63   -
64 61 # catalog
65 62 map.catalog 'catalog/:profile', :controller => 'catalog', :action => 'index', :profile => /#{Noosfero.identifier_format}/
66 63 map.product 'catalog/:profile/:id', :controller => 'catalog', :action => 'show', :profile => /#{Noosfero.identifier_format}/
67 64  
  65 + # invite
  66 + map.invite 'profile/:profile/invite/:action', :controller => 'invite', :profile => /#{Noosfero.identifier_format}/
  67 +
  68 + # public profile information
  69 + map.profile 'profile/:profile/:action/:id', :controller => 'profile', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format}/
  70 +
68 71 # contact
69 72 map.contact 'contact/:profile/:action/:id', :controller => 'contact', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format}/
70 73  
... ...
db/migrate/082_add_invite_members_permission_to_admins.rb 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +class AddInviteMembersPermissionToAdmins < ActiveRecord::Migration
  2 + def self.up
  3 + Environment.all.each{ |env|
  4 + admin = Profile::Roles.admin(env.id)
  5 + admin.permissions += ['invite_members']
  6 + admin.save!
  7 + }
  8 + end
  9 +
  10 + def self.down
  11 + Environment.all.each{ |env|
  12 + admin = Profile::Roles.admin(env.id)
  13 + admin.permissions -= ['invite_members']
  14 + admin.save!
  15 + }
  16 + end
  17 +end
... ...
db/schema.rb
... ... @@ -9,7 +9,7 @@
9 9 #
10 10 # It's strongly recommended to check this file into your version control system.
11 11  
12   -ActiveRecord::Schema.define(:version => 81) do
  12 +ActiveRecord::Schema.define(:version => 82) do
13 13  
14 14 create_table "article_versions", :force => true do |t|
15 15 t.integer "article_id"
... ...
features/invitation.feature 0 → 100644
... ... @@ -0,0 +1,85 @@
  1 +Feature: invitation
  2 + As a noosfero visitor
  3 + I want to invite my friends to Noosfero
  4 +
  5 + Background:
  6 + Given the following users
  7 + | login |
  8 + | josesilva |
  9 + | josesantos |
  10 + And the following communities
  11 + | owner | identifier | name |
  12 + | josesilva | 26-bsslines | 26 Bsslines |
  13 + And the following enterprises
  14 + | owner | identifier | name |
  15 + | josesilva | beatles-for-sale | Beatles For Sale |
  16 + And I am logged in as "josesilva"
  17 +
  18 + Scenario: see link to invite friends
  19 + When I am on /profile/josesilva/friends
  20 + Then I should see "Invite people from my e-mail contacts" link
  21 +
  22 + Scenario: see link to invite friends in myprofile
  23 + When I am on /myprofile/josesilva/friends
  24 + Then I should see "Invite people from my e-mail contacts" link
  25 +
  26 + Scenario: go to invitation screen when follow link to invite friends
  27 + Given I am on /myprofile/josesilva/friends
  28 + When I follow "Invite people from my e-mail contacts"
  29 + Then I am on /profile/josesilva/invite/friends
  30 +
  31 + Scenario: see title when invite friends
  32 + When I am on /profile/josesilva/invite/friends
  33 + Then I should see "Invite your friends"
  34 +
  35 + # why not work?
  36 + Scenario: back to manage friends after invite friends
  37 + Given I am on /myprofile/josesilva/friends
  38 + And I follow "Invite people from my e-mail contacts"
  39 + And I press "Next"
  40 + And I fill in "manual_import_addresses" with "misfits@devil.doll"
  41 + And I fill in "mail_template" with "Follow this link <url>"
  42 + When I press "Invite my friends!"
  43 + Then I should be on /myprofile/josesilva/friends
  44 +
  45 + Scenario: see link to invite members to community
  46 + When I am on /profile/26-bsslines/members
  47 + Then I should see "Invite your friends to join 26 Bsslines" link
  48 +
  49 + Scenario: not see link to invite members to community if has no rights
  50 + Given I am not logged in
  51 + And I am logged in as "josesantos"
  52 + When I am on /profile/26-bsslines/members
  53 + Then I should not see "Invite your friends to join 26 Bsslines" link
  54 +
  55 + Scenario: go to invitation screen when follow link to invite members
  56 + Given I am on /profile/26-bsslines/members
  57 + When I follow "Invite your friends to join 26 Bsslines"
  58 + Then I am on /profile/26-bsslines/invite/friends
  59 +
  60 + Scenario: see title when invite members
  61 + When I am on /profile/26-bsslines/invite/friends
  62 + Then I should see "Invite your friends to join 26 Bsslines"
  63 +
  64 + Scenario: not see link to invite members to enterprise
  65 + When I am on /profile/beatles-for-sale/members
  66 + Then I should not see "Invite your friends to join Beatles For Sale" link
  67 +
  68 + Scenario: deny access if user has no right to invite members
  69 + Given I am not logged in
  70 + And I am logged in as "josesantos"
  71 + When I am on /profile/26-bsslines/invite/friends
  72 + Then I should see "Access denied"
  73 +
  74 + Scenario: not see link to invite members to enterprise in manage members
  75 + Given I am on /myprofile/beatles-for-sale/profile_members
  76 + Then I should not see "Invite your friends to join Beatles For Sale" link
  77 +
  78 + Scenario: back to manage members after invite friends
  79 + Given I am on /myprofile/26-bsslines/profile_members
  80 + And I follow "Invite your friends to join 26 Bsslines"
  81 + And I press "Next"
  82 + And I fill in "manual_import_addresses" with "misfits@devil.doll"
  83 + And I fill in "mail_template" with "Follow this link <url>"
  84 + When I press "Invite my friends!"
  85 + Then I should be on /myprofile/26-bsslines/profile_members
... ...
public/stylesheets/controller_friends.css
... ... @@ -12,13 +12,6 @@
12 12 padding-top: 20px;
13 13 }
14 14  
15   -#friends-list {
16   - overflow: auto;
17   - height: 300px;
18   - border: 1px solid #999;
19   - margin: 5px 0px;
20   -}
21   -
22 15 #pagination-friends .pagination span {
23 16 display: inline;
24 17 }
... ...
public/stylesheets/controller_invite.css 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +#contacts-list {
  2 + overflow: auto;
  3 + height: 300px;
  4 + border: 1px solid #999;
  5 + margin: 5px 0px;
  6 +}
... ...
test/fixtures/roles.yml
... ... @@ -40,6 +40,8 @@ profile_admin:
40 40 name: 'Profile Administrator'
41 41 system: true
42 42 permissions:
  43 + - invite_members
  44 + - manage_memberships
43 45 - edit_profile_design
44 46 - edit_profile
45 47 - moderate_comments
... ...
test/functional/friends_controller_test.rb
... ... @@ -75,93 +75,4 @@ class FriendsControllerTest &lt; Test::Unit::TestCase
75 75 assert_tag :tag => 'a', :content => 'Find people', :attributes => { :href => '/assets/people' }
76 76 end
77 77  
78   - should 'display invitation page' do
79   - get :invite
80   - assert_response :success
81   - assert_template 'invite'
82   - end
83   -
84   - should 'actualy invite manually added addresses with name and e-mail' do
85   - assert_difference InviteFriend, :count, 1 do
86   - post :invite, :manual_import_addresses => "Test Name <test@test.com>", :import_from => "manual", :message => "click: <url>", :confirmation => 1
87   - assert_redirected_to :action => 'index'
88   - end
89   - end
90   -
91   - should 'actualy invite manually added addresses with name and e-mail on wizard' do
92   - assert_difference InviteFriend, :count, 1 do
93   - post :invite, :manual_import_addresses => "Test Name <test@test.com>", :import_from => "manual", :message => "click: <url>", :confirmation => 1, :wizard => true
94   - assert_redirected_to :action => 'invite', :wizard => true
95   - end
96   - end
97   -
98   - should 'actually invite manually added address with only e-mail' do
99   - assert_difference InviteFriend, :count, 1 do
100   - post :invite, :manual_import_addresses => "test@test.com", :import_from => "manual", :message => "click: <url>", :confirmation => 1
101   - assert_redirected_to :action => 'index'
102   - end
103   - end
104   -
105   - should 'actually invite manually added address with only e-mail on wizard' do
106   - assert_difference InviteFriend, :count, 1 do
107   - post :invite, :manual_import_addresses => "test@test.com", :import_from => "manual", :message => "click: <url>", :confirmation => 1, :wizard => true
108   - assert_redirected_to :action => 'invite', :wizard => true
109   - end
110   - end
111   -
112   - should 'actually invite manually added addresses with e-mail and other format' do
113   - assert_difference InviteFriend, :count, 1 do
114   - post :invite, :manual_import_addresses => "test@test.cz.com", :import_from => "manual", :message => "click: <url>", :confirmation => 1
115   - assert_redirected_to :action => 'index'
116   - end
117   - end
118   -
119   - should 'actually invite manually added addresses with e-mail and other format on wizard' do
120   - assert_difference InviteFriend, :count, 1 do
121   - post :invite, :manual_import_addresses => "test@test.cz.com", :import_from => "manual", :message => "click: <url>", :confirmation => 1, :wizard => true
122   - assert_redirected_to :action => 'invite', :wizard => true
123   - end
124   - end
125   -
126   - should 'actually invite manually added address with friend object' do
127   - assert_difference InviteFriend, :count, 1 do
128   - post :invite, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :message => "click: <url>", :confirmation => 1
129   - assert_redirected_to :action => 'index'
130   - end
131   - end
132   -
133   - should 'actually invite manually added address with friend object on wizard' do
134   - assert_difference InviteFriend, :count, 1 do
135   - post :invite, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :message => "click: <url>", :confirmation => 1, :wizard => true
136   - assert_redirected_to :action => 'invite', :wizard => true
137   - end
138   - end
139   -
140   - should 'actually invite more than one manually added addres' do
141   - assert_difference InviteFriend, :count, 2 do
142   - post :invite, :manual_import_addresses => "Some Friend <somefriend@email.com>\r\notherperson@bleble.net\r\n", :import_from => "manual", :message => "click: <url>", :confirmation => 1
143   - assert_redirected_to :action => 'index'
144   - end
145   - end
146   -
147   - should 'actually invite more than one manually added addres on wizard' do
148   - assert_difference InviteFriend, :count, 2 do
149   - post :invite, :manual_import_addresses => "Some Friend <somefriend@email.com>\r\notherperson@bleble.net\r\n", :import_from => "manual", :message => "click: <url>", :confirmation => 1, :wizard => true
150   - assert_redirected_to :action => 'invite', :wizard => true
151   - end
152   - end
153   -
154   - should 'not invite yourself' do
155   - assert_no_difference InviteFriend, :count do
156   - post :invite, :manual_import_addresses => "#{profile.name} <#{profile.user.email}>", :import_from => "manual", :message => "click: <url>", :confirmation => 1, :wizard => true
157   - end
158   - end
159   -
160   - should 'not create InviteFriend if is a friend' do
161   - friend = create_user('testfriend', :email => 'friend@noosfero.org')
162   - friend.person.add_friend(profile)
163   - assert_no_difference InviteFriend, :count do
164   - post :invite, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :message => "click: <url>", :confirmation => 1, :wizard => true
165   - end
166   - end
167 78 end
... ...
test/functional/invite_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,86 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class InviteControllerTest < ActionController::TestCase
  4 +
  5 + def setup
  6 + @profile = create_user('testuser').person
  7 + @friend = create_user('thefriend').person
  8 + @community = fast_create(Community)
  9 + login_as ('testuser')
  10 + end
  11 + attr_accessor :profile, :friend, :community
  12 +
  13 + should 'actually invite manually added address with friend object' do
  14 + assert_difference InviteFriend, :count, 1 do
  15 + post :friends, :profile => profile.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :step => 2
  16 + assert_redirected_to :controller => 'profile'
  17 + end
  18 + end
  19 +
  20 + should 'actually invite manually added address with only e-mail' do
  21 + assert_difference InviteFriend, :count, 1 do
  22 + post :friends, :profile => profile.identifier, :manual_import_addresses => "test@test.com", :import_from => "manual", :mail_template => "click: <url>", :step => 2
  23 + end
  24 + end
  25 +
  26 + should 'actually invite manually added addresses with e-mail and other format' do
  27 + assert_difference InviteFriend, :count, 1 do
  28 + post :friends, :profile => profile.identifier, :manual_import_addresses => "test@test.cz.com", :import_from => "manual", :mail_template => "click: <url>", :step => 2
  29 + end
  30 + end
  31 +
  32 + should 'actually invite more than one manually added address' do
  33 + assert_difference InviteFriend, :count, 2 do
  34 + post :friends, :profile => profile.identifier, :manual_import_addresses => "Some Friend <somefriend@email.com>\r\notherperson@bleble.net\r\n", :import_from => "manual", :mail_template => "click: <url>", :step => 2
  35 + end
  36 + end
  37 +
  38 + should 'actualy invite manually added addresses with name and e-mail' do
  39 + assert_difference InviteFriend, :count, 1 do
  40 + post :friends, :profile => profile.identifier, :manual_import_addresses => "Test Name <test@test.com>", :import_from => "manual", :mail_template => "click: <url>", :step => 2
  41 + end
  42 + end
  43 +
  44 + should 'not invite yourself' do
  45 + assert_no_difference InviteFriend, :count do
  46 + post :friends, :profile => profile.identifier, :manual_import_addresses => "#{profile.name} <#{profile.user.email}>", :import_from => "manual", :mail_template => "click: <url>", :step => 2
  47 + end
  48 + end
  49 +
  50 + should 'not invite if already a friend' do
  51 + friend = create_user('testfriend', :email => 'friend@noosfero.org')
  52 + friend.person.add_friend(profile)
  53 + assert_no_difference InviteFriend, :count do
  54 + post :friends, :profile => profile.identifier, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :mail_template => "click: <url>", :step => 2
  55 + end
  56 + end
  57 +
  58 + should 'display invitation page' do
  59 + get :friends, :profile => profile.identifier
  60 + assert_response :success
  61 + assert_tag :tag => 'h1', :content => 'Invite your friends'
  62 + end
  63 +
  64 + should 'get mail template to invite members' do
  65 + community.add_admin(profile)
  66 + get :friends, :profile => community.identifier
  67 + assert_equal InviteMember.mail_template, assigns(:mail_template)
  68 + end
  69 +
  70 + should 'get mail template to invite friends' do
  71 + community.add_admin(profile)
  72 + get :friends, :profile => profile.identifier
  73 + assert_equal InviteFriend.mail_template, assigns(:mail_template)
  74 + end
  75 +
  76 + should 'deny if user has no rights to invite members' do
  77 + get :friends, :profile => community.identifier
  78 + assert_response 403 # forbidden
  79 + end
  80 +
  81 + should 'deny access when trying to invite friends to another user' do
  82 + get :friends, :profile => friend.identifier
  83 + assert_response 403 # forbidden
  84 + end
  85 +
  86 +end
... ...
test/unit/environment_test.rb
... ... @@ -587,19 +587,32 @@ class EnvironmentTest &lt; Test::Unit::TestCase
587 587 assert_equal ['birth_date'], env.required_person_fields
588 588 end
589 589  
590   - should 'provide a default invitation message' do
591   - env = Environment.new
  590 + should 'provide a default invitation message for friend' do
  591 + env = Environment.default
592 592 message = [
593 593 'Hello <friend>,',
594   - "<user> is inviting you to participate on #{env.name}.",
595   - 'To accept the invitation, please follow this link:' + "\n" + '<url>',
596   - "--\n#{env.name}",
597   - ''
  594 + "<user> is inviting you to participate on <environment>.",
  595 + 'To accept the invitation, please follow this link:',
  596 + '<url>',
  597 + "--\n<environment>",
598 598 ].join("\n\n")
599 599  
600 600 assert_equal message, env.message_for_friend_invitation
601 601 end
602 602  
  603 + should 'provide a default invitation message for member' do
  604 + env = Environment.default
  605 + message = [
  606 + 'Hello <friend>,',
  607 + "<user> is inviting you to participate of <community> on <environment>.",
  608 + 'To accept the invitation, please follow this link:',
  609 + '<url>',
  610 + "--\n<environment>",
  611 + ].join("\n\n")
  612 +
  613 + assert_equal message, env.message_for_member_invitation
  614 + end
  615 +
603 616 should 'set custom_enterprises_fields' do
604 617 env = Environment.new
605 618 env.custom_enterprise_fields = {'contact_person' => {'required' => 'true', 'active' => 'true'},'contact_email'=> {'required' => 'true', 'active' => 'true'}}
... ... @@ -841,4 +854,18 @@ class EnvironmentTest &lt; Test::Unit::TestCase
841 854 assert_equal [], Environment.new.local_docs
842 855 end
843 856  
  857 + should 'provide right invitation mail template for friends' do
  858 + env = Environment.default
  859 + person = Person.new
  860 +
  861 + assert_equal env.message_for_friend_invitation, env.invitation_mail_template(person)
  862 + end
  863 +
  864 + should 'provide right invitation mail template for members' do
  865 + env = Environment.default
  866 + community = Community.new
  867 +
  868 + assert_equal env.message_for_member_invitation, env.invitation_mail_template(community)
  869 + end
  870 +
844 871 end
... ...
test/unit/invitation_test.rb 0 → 100644
... ... @@ -0,0 +1,62 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class InvitationTest < ActiveSupport::TestCase
  4 +
  5 + should 'expand message' do
  6 + invitation = Invitation.new(
  7 + :person => Person.new(:name => 'Sadam', :environment => Environment.new(:name => 'AnarquiaOi')),
  8 + :friend_name => 'Fernandinho',
  9 + :message => 'Hi <friend>, <user> is inviting you to <environment>!'
  10 + )
  11 + assert_equal 'Hi Fernandinho, Sadam is inviting you to AnarquiaOi!', invitation.expanded_message
  12 + end
  13 +
  14 + should 'require subclasses implement mail_template method' do
  15 + assert_raise RuntimeError do
  16 + Invitation.new.mail_template
  17 + end
  18 + end
  19 +
  20 + should 'join string contacts with array contacts' do
  21 + string_contacts = "sadam@garotos\nfernandinho@garotos\roi@garotos"
  22 + array_contacts = ['casiotone@gengivas.negras']
  23 +
  24 + assert_equal ['sadam@garotos', 'fernandinho@garotos', 'oi@garotos', 'casiotone@gengivas.negras'],
  25 + Invitation.join_contacts(string_contacts, array_contacts)
  26 + end
  27 +
  28 + should 'raises when try get contacts from unknown source' do
  29 + assert_raise NotImplementedError do
  30 + Invitation.get_contacts('ze', 'ze12', 'bli-mail')
  31 + end
  32 + end
  33 +
  34 + should 'not know how to invite members to non-community' do
  35 + person = fast_create(Person)
  36 + enterprise = fast_create(Enterprise)
  37 +
  38 + assert_raise NotImplementedError do
  39 + Invitation.invite(person, ['sadam@garotos.podres'], 'hello friend', enterprise)
  40 + end
  41 + end
  42 +
  43 + should 'create right task when invite friends' do
  44 + person = fast_create(Person)
  45 + person.user = User.new(:email => 'current_user@email.invalid')
  46 +
  47 + assert_difference InviteFriend, :count do
  48 + Invitation.invite(person, ['sadam@garotos.podres'], 'hello friend <url>', person)
  49 + end
  50 + end
  51 +
  52 + should 'create right task when invite members to community' do
  53 + person = fast_create(Person)
  54 + person.user = User.new(:email => 'current_user@email.invalid')
  55 + community = fast_create(Community)
  56 +
  57 + assert_difference InviteMember, :count do
  58 + Invitation.invite(person, ['sadam@garotos.podres'], 'hello friend <url>', community)
  59 + end
  60 + end
  61 +
  62 +end
... ...
test/unit/invite_member_test.rb 0 → 100644
... ... @@ -0,0 +1,112 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class InviteMemberTest < ActiveSupport::TestCase
  4 +
  5 + should 'be a task' do
  6 + ok { InviteMember.new.kind_of?(Task) }
  7 + end
  8 +
  9 + should 'actually add as member when confirmed' do
  10 + person = fast_create(Person)
  11 + friend = fast_create(Person)
  12 + friend.stubs(:user).returns(User.new(:email => 'garotos@podres.punk.oi'))
  13 + person.stubs(:user).returns(User.new(:email => 'suburbio-operario@podres.podres'))
  14 + community = fast_create(Community)
  15 +
  16 + assert_equal [], community.members
  17 +
  18 + task = InviteMember.create!(:person => person, :friend => friend, :community_id => community.id)
  19 + task.finish
  20 + community.reload
  21 +
  22 + ok('friend is member of community') { community.members.include?(friend) }
  23 + end
  24 +
  25 + should 'require community (person inviting other to be a member)' do
  26 + task = InviteMember.new
  27 + task.valid?
  28 +
  29 + ok('community is required') { task.errors.invalid?(:community_id) }
  30 + end
  31 +
  32 + should 'require friend email if no target given (person being invited)' do
  33 + task = InviteMember.new
  34 + task.valid?
  35 +
  36 + ok('friend_email is required') { task.errors.invalid?(:friend_email) }
  37 + end
  38 +
  39 + should 'dont require friend email if target given (person being invited)' do
  40 + task = InviteMember.new(:target => create_user('testuser2').person)
  41 + task.valid?
  42 +
  43 + ok('friend_email isnt required') { !task.errors.invalid?(:friend_email) }
  44 + end
  45 +
  46 + should 'require target (person being invited) if no friend email given' do
  47 + task = InviteMember.new
  48 + task.valid?
  49 +
  50 + ok('target is required') { task.errors.invalid?(:target_id) }
  51 + end
  52 +
  53 + should 'dont require target (person being invited) if friend email given' do
  54 + task = InviteMember.new(:friend_email => "test@test.com")
  55 + task.valid?
  56 +
  57 + ok('target isn required') { !task.errors.invalid?(:target_id) }
  58 + end
  59 +
  60 + should 'not send e-mails to requestor' do
  61 + p1 = create_user('testuser1').person
  62 + p2 = create_user('testuser2').person
  63 +
  64 + TaskMailer.expects(:deliver_task_finished).never
  65 + TaskMailer.expects(:deliver_task_created).never
  66 +
  67 + task = InviteMember.create!(:person => p1, :friend => p2, :community_id => fast_create(Community).id)
  68 + task.finish
  69 + end
  70 +
  71 + should 'send e-mails to friend if friend_email given' do
  72 + p1 = create_user('testuser1').person
  73 +
  74 + TaskMailer.expects(:deliver_invitation_notification).once
  75 +
  76 + task = InviteMember.create!(:person => p1, :friend_email => 'test@test.com', :message => '<url>', :community_id => fast_create(Community).id)
  77 + end
  78 +
  79 + should 'not send e-mails to friend if target given (person being invited)' do
  80 + p1 = create_user('testuser1').person
  81 + p2 = create_user('testuser2').person
  82 +
  83 + TaskMailer.expects(:deliver_invitation_notification).never
  84 +
  85 + task = InviteMember.create!(:person => p1, :friend => p2, :community_id => fast_create(Community).id)
  86 + end
  87 +
  88 + should 'provide proper description' do
  89 + p1 = create_user('testuser1').person
  90 + p2 = create_user('testuser2').person
  91 +
  92 + TaskMailer.expects(:deliver_task_finished).never
  93 + TaskMailer.expects(:deliver_task_created).never
  94 +
  95 + community = fast_create(Community)
  96 + task = InviteMember.create!(:person => p1, :friend => p2, :community_id => community.id)
  97 +
  98 + assert_equal "#{p1.name} invites you to join the community #{community.name}.", task.description
  99 + end
  100 +
  101 + should 'not invite yourself' do
  102 + p = create_user('testuser1').person
  103 +
  104 + task1 = InviteMember.new(:person => p, :friend => p, :message => 'click here: <url>')
  105 + assert !task1.save
  106 +
  107 + task2 = InviteMember.new(:person => p, :friend_name => 'Myself', :friend_email => p.user.email, :message => 'click here: <url>')
  108 + assert !task2.save
  109 + end
  110 +
  111 +end
  112 +
... ...
test/unit/task_mailer_test.rb
... ... @@ -124,6 +124,7 @@ class TaskMailerTest &lt; Test::Unit::TestCase
124 124 environment.expects(:name).returns('example').at_least_once
125 125  
126 126 task.expects(:requestor).returns(requestor).at_least_once
  127 + task.expects(:person).returns(requestor).at_least_once
127 128 requestor.expects(:environment).returns(environment).at_least_once
128 129  
129 130 mail = TaskMailer.create_invitation_notification(task)
... ...