Commit 095aeddafecc715694f6f5522294bff8e5e6f398

Authored by Rodrigo Souto
2 parents 0b4c072d 197473bb

Merge branch 'stoa-invitation' into stoa-profile-info

Conflicts:
	plugins/stoa/lib/stoa_plugin.rb
	plugins/stoa/public/style.css
app/models/environment.rb
@@ -258,7 +258,7 @@ class Environment < ActiveRecord::Base @@ -258,7 +258,7 @@ class Environment < ActiveRecord::Base
258 end 258 end
259 259
260 def enable_plugin(plugin) 260 def enable_plugin(plugin)
261 - self.enabled_plugins += [plugin] 261 + self.enabled_plugins += [plugin.to_s]
262 self.enabled_plugins.uniq! 262 self.enabled_plugins.uniq!
263 self.save! 263 self.save!
264 end 264 end
@@ -269,7 +269,7 @@ class Environment < ActiveRecord::Base @@ -269,7 +269,7 @@ class Environment < ActiveRecord::Base
269 end 269 end
270 270
271 def disable_plugin(plugin) 271 def disable_plugin(plugin)
272 - self.enabled_plugins.delete(plugin) 272 + self.enabled_plugins.delete(plugin.to_s)
273 self.save! 273 self.save!
274 end 274 end
275 275
@@ -278,6 +278,10 @@ class Environment < ActiveRecord::Base @@ -278,6 +278,10 @@ class Environment < ActiveRecord::Base
278 self.settings["#{feature}_enabled".to_sym] == true 278 self.settings["#{feature}_enabled".to_sym] == true
279 end 279 end
280 280
  281 + def plugin_enabled?(plugin)
  282 + enabled_plugins.include?(plugin.to_s)
  283 + end
  284 +
281 # enables the features identified by <tt>features</tt>, which is expected to 285 # enables the features identified by <tt>features</tt>, which is expected to
282 # be an Enumarable object containing the identifiers of the desired features. 286 # be an Enumarable object containing the identifiers of the desired features.
283 # Passing <tt>nil</tt> is the same as passing an empty Array. 287 # Passing <tt>nil</tt> is the same as passing an empty Array.
app/views/friends/index.rhtml
@@ -14,7 +14,9 @@ @@ -14,7 +14,9 @@
14 <% button_bar do %> 14 <% button_bar do %>
15 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> 15 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %>
16 <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> 16 <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %>
17 - <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'select_address_book') %> 17 + <% if !@plugins.dispatch(:remove_invite_friends_button).include?(true) %>
  18 + <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'select_address_book') %>
  19 + <% end %>
18 <% end %> 20 <% end %>
19 <% end %> 21 <% end %>
20 22
@@ -43,7 +45,9 @@ @@ -43,7 +45,9 @@
43 <% button_bar do %> 45 <% button_bar do %>
44 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %> 46 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor') %>
45 <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> 47 <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %>
46 - <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'select_address_book') %> 48 + <% if !@plugins.dispatch(:remove_invite_friends_button).include?(true) %>
  49 + <%= button(:search, _('Invite people from my e-mail contacts'), :controller => 'invite', :action => 'select_address_book') %>
  50 + <% end %>
47 <% end %> 51 <% end %>
48 <% end %> 52 <% end %>
49 53
lib/noosfero/plugin.rb
@@ -244,4 +244,10 @@ class Noosfero::Plugin @@ -244,4 +244,10 @@ class Noosfero::Plugin
244 nil 244 nil
245 end 245 end
246 246
  247 + # -> Removes the invite friend button from the friends controller
  248 + # returns = boolean
  249 + def remove_invite_friends_button
  250 + nil
  251 + end
  252 +
247 end 253 end
plugins/stoa/lib/ext/person.rb
1 require_dependency 'person' 1 require_dependency 'person'
2 2
3 class Person 3 class Person
4 - validates_uniqueness_of :usp_id 4 + validates_uniqueness_of :usp_id, :allow_nil => true
  5 + settings_items :invitation_code
  6 + validate :usp_id_or_invitation, :if => lambda { |person| person.environment && person.environment.plugin_enabled?(StoaPlugin)}
  7 +
  8 + def usp_id_or_invitation
  9 + if usp_id.blank? && (invitation_code.blank? || !invitation_task)
  10 + errors.add(:usp_id, "can't register without usp_id or invitation")
  11 + end
  12 + end
  13 +
  14 + def invitation_task
  15 + Task.pending.find(:first, :conditions => {:code => invitation_code}) ||
  16 + Task.finished.find(:first, :conditions => {:code => invitation_code, :target_id => id})
  17 + end
5 end 18 end
plugins/stoa/lib/stoa_plugin.rb
@@ -20,6 +20,7 @@ class StoaPlugin &lt; Noosfero::Plugin @@ -20,6 +20,7 @@ class StoaPlugin &lt; Noosfero::Plugin
20 def signup_extra_contents 20 def signup_extra_contents
21 lambda { 21 lambda {
22 required(labelled_form_field(_('USP number'), text_field_tag('profile_data[usp_id]', '', :id => 'usp_id_field'))) + 22 required(labelled_form_field(_('USP number'), text_field_tag('profile_data[usp_id]', '', :id => 'usp_id_field'))) +
  23 + content_tag(:small, _('The usp id grants you special powers in the network. Don\'t forget to fill it in if you have one.'), :id => 'usp-id-balloon') +
23 content_tag('div', required(labelled_form_field(_('Birth date (yyyy-mm-dd)'), text_field_tag('birth_date', ''))), :id => 'signup-birth-date', :style => 'display: none') + 24 content_tag('div', required(labelled_form_field(_('Birth date (yyyy-mm-dd)'), text_field_tag('birth_date', ''))), :id => 'signup-birth-date', :style => 'display: none') +
24 content_tag('div', required(labelled_form_field(_('CPF'), text_field_tag('cpf', ''))), :id => 'signup-cpf', :style => 'display:none') + 25 content_tag('div', required(labelled_form_field(_('CPF'), text_field_tag('cpf', ''))), :id => 'signup-cpf', :style => 'display:none') +
25 javascript_include_tag('../plugins/stoa/javascripts/jquery.observe_field', '../plugins/stoa/javascripts/signup_complement') 26 javascript_include_tag('../plugins/stoa/javascripts/jquery.observe_field', '../plugins/stoa/javascripts/signup_complement')
@@ -28,8 +29,10 @@ class StoaPlugin &lt; Noosfero::Plugin @@ -28,8 +29,10 @@ class StoaPlugin &lt; Noosfero::Plugin
28 29
29 def account_controller_filters 30 def account_controller_filters
30 block = lambda do 31 block = lambda do
  32 + params[:profile_data] ||= {}
  33 + params[:profile_data][:invitation_code] = params[:invitation_code]
31 if request.post? 34 if request.post?
32 - if !StoaPlugin::UspUser.matches?(params[:profile_data][:usp_id], params[:confirmation_field], params[params[:confirmation_field]]) 35 + if !params[:invitation_code] && !StoaPlugin::UspUser.matches?(params[:profile_data][:usp_id], params[:confirmation_field], params[params[:confirmation_field]])
33 @person = Person.new 36 @person = Person.new
34 @person.errors.add(:usp_id, _(' validation failed')) 37 @person.errors.add(:usp_id, _(' validation failed'))
35 render :action => :signup 38 render :action => :signup
@@ -43,4 +46,21 @@ class StoaPlugin &lt; Noosfero::Plugin @@ -43,4 +46,21 @@ class StoaPlugin &lt; Noosfero::Plugin
43 :block => block }] 46 :block => block }]
44 end 47 end
45 48
  49 + def invite_controller_filters
  50 + [{ :type => 'before_filter',
  51 + :method_name => 'check_usp_id_existence',
  52 + :block => lambda {render_access_denied if profile.usp_id.blank?} }]
  53 + end
  54 +
  55 + def control_panel_buttons
  56 + { :title => _('Invite friends'),
  57 + :icon => 'invite-friends',
  58 + :url => {:controller => 'invite',
  59 + :action => 'select_address_book'} } if !context.profile.usp_id.blank?
  60 + end
  61 +
  62 + def remove_invite_friends_button
  63 + true
  64 + end
  65 +
46 end 66 end
plugins/stoa/public/images/control-panel/invite-friends.gif 0 → 100644

1.97 KB

plugins/stoa/public/images/control-panel/invite-friends.png 0 → 100644

3.66 KB

plugins/stoa/public/javascripts/signup_complement.js
@@ -23,14 +23,22 @@ jQuery(&quot;#usp_id_field&quot;).observe_field(1, function(){ @@ -23,14 +23,22 @@ jQuery(&quot;#usp_id_field&quot;).observe_field(1, function(){
23 }); 23 });
24 } 24 }
25 else { 25 else {
26 - jQuery('#signup-form .submit').attr('disabled', true); 26 + jQuery(me).removeClass('checking');
  27 + if(me.value) {
  28 + jQuery('#signup-form .submit').attr('disabled', true);
  29 + jQuery(me).addClass('invalid');
  30 + }
  31 + else {
  32 + jQuery('#signup-form .submit').attr('disabled', false);
  33 + jQuery(me).removeClass('invalid');
  34 + jQuery(me).removeClass('validated');
  35 + }
27 jQuery('#signup-birth-date').hide(); 36 jQuery('#signup-birth-date').hide();
28 jQuery('#signup-cpf').hide(); 37 jQuery('#signup-cpf').hide();
29 - jQuery(me).removeClass('checking').addClass('invalid');  
30 } 38 }
31 if(data.error) displayValidationUspIdError(data.error); 39 if(data.error) displayValidationUspIdError(data.error);
32 } 40 }
33 -); 41 + );
34 }); 42 });
35 43
36 function displayValidationUspIdError(error){ 44 function displayValidationUspIdError(error){
@@ -39,3 +47,8 @@ function displayValidationUspIdError(error){ @@ -39,3 +47,8 @@ function displayValidationUspIdError(error){
39 width: "70%" }); 47 width: "70%" });
40 } 48 }
41 49
  50 +jQuery('#usp_id_field').focus(function() {
  51 + jQuery('#usp-id-balloon').fadeIn('slow');
  52 +});
  53 +
  54 +jQuery('#usp_id_field').blur(function() { jQuery('#usp-id-balloon').fadeOut('slow'); });
plugins/stoa/public/style.css
@@ -10,3 +10,22 @@ @@ -10,3 +10,22 @@
10 cursor: default; 10 cursor: default;
11 } 11 }
12 12
  13 +.controller-profile_editor a.control-panel-invite-friends {background-image: url(../../plugins/stoa/images/control-panel/invite-friends.png)}
  14 +.controller-profile_editor .msie6 a.control-panel-invite-friends {background-image: url(../../plugins/stoa/images/control-panel/invite-friends.gif)}
  15 +
  16 +#signup-form small#usp-id-balloon {
  17 + display: none;
  18 + width: 142px;
  19 + height: 69px;
  20 + color: #FFFFFF;
  21 + font-weight: bold;
  22 + font-size: 11px;
  23 + padding: 5px 10px 45px 10px;
  24 + margin: 0;
  25 + line-height: 1.5em;
  26 + background: transparent url(/images/orange-balloon.png) bottom center no-repeat;
  27 + position: absolute;
  28 + z-index: 2;
  29 + right: 20px;
  30 + bottom: 110px;
  31 +}
plugins/stoa/test/functional/account_controller_test.rb
@@ -38,4 +38,9 @@ class AccountControllerTest &lt; ActionController::TestCase @@ -38,4 +38,9 @@ class AccountControllerTest &lt; ActionController::TestCase
38 assert_nil assigns(:person).errors[:usp_id] 38 assert_nil assigns(:person).errors[:usp_id]
39 end 39 end
40 40
  41 + should 'inlude invitation_code param in the person\'s attributes' do
  42 + get :signup, :invitation_code => 12345678
  43 + assert assigns(:person).invitation_code == '12345678'
  44 + end
  45 +
41 end 46 end
plugins/stoa/test/functional/invite_controller_test.rb 0 → 100644
@@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +require File.dirname(__FILE__) + '/../../../../app/controllers/public/invite_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class InviteController; def rescue_action(e) raise e end; end
  6 +
  7 +class InviteControllerTest < ActionController::TestCase
  8 +
  9 + def setup
  10 + @controller = InviteController.new
  11 + @request = ActionController::TestRequest.new
  12 + @response = ActionController::TestResponse.new
  13 + environment = Environment.default
  14 + environment.enabled_plugins = ['StoaPlugin']
  15 + environment.save!
  16 + end
  17 +
  18 + should 'not enable access to invitation if the user has not an usp_id' do
  19 + Task.create!(:code => 12345678)
  20 + person_without_usp_id = User.create!(:login => 'user-without', :email => 'user-without@example.com', :password => 'test', :password_confirmation => 'test', :person_data => {:invitation_code => 12345678}).person
  21 +
  22 + login_as(person_without_usp_id.identifier)
  23 + get :select_address_book, :profile => person_without_usp_id.identifier
  24 + assert_response 403
  25 + get :select_friends, :profile => person_without_usp_id.identifier
  26 + assert_response 403
  27 + end
  28 +
  29 + should 'enable access to invitation if the user has an usp_id' do
  30 + person_with_usp_id = User.create!(:login => 'user-with', :email => 'user-with@example.com', :password => 'test', :password_confirmation => 'test', :person_data => {:usp_id => 12345678}).person
  31 +
  32 + login_as(person_with_usp_id.identifier)
  33 + get :select_address_book, :profile => person_with_usp_id.identifier
  34 + assert_response 200
  35 + get :select_friends, :profile => person_with_usp_id.identifier, :contact_list => ContactList.create.id
  36 + assert_response 200
  37 + end
  38 +
  39 +end
  40 +
plugins/stoa/test/unit/person.rb
@@ -2,16 +2,64 @@ require File.dirname(__FILE__) + &#39;/../../../../test/test_helper&#39; @@ -2,16 +2,64 @@ require File.dirname(__FILE__) + &#39;/../../../../test/test_helper&#39;
2 2
3 class StoaPlugin::Person < ActiveSupport::TestCase 3 class StoaPlugin::Person < ActiveSupport::TestCase
4 4
  5 + def setup
  6 + @environment = Environment.default
  7 + @environment.enable_plugin(StoaPlugin)
  8 + end
  9 +
  10 + attr_reader :environment
  11 +
5 should 'validates uniqueness of usp_id' do 12 should 'validates uniqueness of usp_id' do
6 - usp_id = 12345678  
7 - person = create_user('some-person').person  
8 - person.usp_id = usp_id  
9 - person.save!  
10 - another_person = Person.new(:name => "Another person", :identifier => 'another-person', :usp_id => usp_id) 13 + usp_id = 87654321
  14 + fast_create(Person, :usp_id => usp_id)
  15 + another_person = Person.new(:usp_id => usp_id)
  16 + another_person.valid?
11 17
12 - assert !another_person.valid?  
13 assert another_person.errors.invalid?(:usp_id) 18 assert another_person.errors.invalid?(:usp_id)
14 end 19 end
15 20
  21 + should 'allow nil usp_id only if person has an invitation_code' do
  22 + person = Person.new(:environment => environment)
  23 + person.valid?
  24 + assert person.errors.invalid?(:usp_id)
  25 +
  26 + Task.create!(:code => 12345678)
  27 + person.invitation_code = 12345678
  28 + person.valid?
  29 +
  30 + assert !person.errors.invalid?(:usp_id)
  31 + end
  32 +
  33 + should 'allow multiple nil usp_id' do
  34 + fast_create(Person)
  35 + Task.create!(:code => 87654321)
  36 + person = Person.new(:invitation_code => 87654321)
  37 + person.valid?
  38 +
  39 + assert !person.errors.invalid?(:usp_id)
  40 + end
  41 +
  42 + should 'not allow person to be saved with a finished invitation that is not his own' do
  43 + t = Task.create!(:code => 87654321, :target_id => 1)
  44 + t.finish
  45 + person = Person.new(:environment => environment, :invitation_code => 87654321)
  46 + person.valid?
  47 +
  48 + assert person.errors.invalid?(:usp_id)
  49 + end
  50 +
  51 + should 'allow person to be saved with a finished invitation if it is his own' do
  52 + t = Task.create!(:code => 87654321)
  53 + user = User.new(:login => 'some-person', :email => 'some-person@example.com', :password => 'test', :password_confirmation => 'test', :person_data => {:environment => environment, :invitation_code => 87654321})
  54 + user.save!
  55 + person = user.person
  56 + t.target_id = person.id
  57 + t.finish
  58 +
  59 + person.valid?
  60 + assert !person.errors.invalid?(:usp_id)
  61 + end
  62 +
  63 +
16 end 64 end
17 65
plugins/stoa/test/unit/usp_user.rb
@@ -8,6 +8,7 @@ class StoaPlugin::UspUserTest &lt; ActiveSupport::TestCase @@ -8,6 +8,7 @@ class StoaPlugin::UspUserTest &lt; ActiveSupport::TestCase
8 @db = Tempfile.new('stoa-test') 8 @db = Tempfile.new('stoa-test')
9 configs = ActiveRecord::Base.configurations['stoa'] = {:adapter => 'sqlite3', :database => @db.path} 9 configs = ActiveRecord::Base.configurations['stoa'] = {:adapter => 'sqlite3', :database => @db.path}
10 ActiveRecord::Base.establish_connection(:stoa) 10 ActiveRecord::Base.establish_connection(:stoa)
  11 + ActiveRecord::Schema.verbose = false
11 ActiveRecord::Schema.create_table "pessoa" do |t| 12 ActiveRecord::Schema.create_table "pessoa" do |t|
12 t.integer "codpes" 13 t.integer "codpes"
13 t.text "numcpf" 14 t.text "numcpf"
test/functional/friends_controller_test.rb
@@ -57,4 +57,24 @@ class FriendsControllerTest &lt; ActionController::TestCase @@ -57,4 +57,24 @@ class FriendsControllerTest &lt; ActionController::TestCase
57 assert_tag :tag => 'a', :content => 'Find people', :attributes => { :href => '/assets/people' } 57 assert_tag :tag => 'a', :content => 'Find people', :attributes => { :href => '/assets/people' }
58 end 58 end
59 59
  60 + should 'not display invite friends button if any plugin tells not to' do
  61 + class Plugin1 < Noosfero::Plugin
  62 + def remove_invite_friends_button
  63 + true
  64 + end
  65 + end
  66 + class Plugin2 < Noosfero::Plugin
  67 + def remove_invite_friends_button
  68 + false
  69 + end
  70 + end
  71 +
  72 + e = profile.environment
  73 + e.enable_plugin(Plugin1.name)
  74 + e.enable_plugin(Plugin2.name)
  75 +
  76 + get :index, :profile => 'testuser'
  77 + assert_no_tag :tag => 'a', :attributes => { :href => "/profile/testuser/invite/friends" }
  78 + end
  79 +
60 end 80 end
test/unit/environment_test.rb
@@ -1187,17 +1187,18 @@ class EnvironmentTest &lt; ActiveSupport::TestCase @@ -1187,17 +1187,18 @@ class EnvironmentTest &lt; ActiveSupport::TestCase
1187 assert !environment.errors.invalid?(:reports_lower_bound) 1187 assert !environment.errors.invalid?(:reports_lower_bound)
1188 end 1188 end
1189 1189
1190 - should 'be able to enable or disable a plugin' do 1190 + should 'be able to enable or disable a plugin with the class or class name' do
  1191 + class Plugin
  1192 + end
1191 environment = Environment.default 1193 environment = Environment.default
1192 - plugin = 'Plugin'  
1193 1194
1194 - environment.enable_plugin(plugin) 1195 + environment.enable_plugin(Plugin)
1195 environment.reload 1196 environment.reload
1196 - assert_includes environment.enabled_plugins, plugin 1197 + assert environment.plugin_enabled?(Plugin.to_s)
1197 1198
1198 - environment.disable_plugin(plugin) 1199 + environment.disable_plugin(Plugin.to_s)
1199 environment.reload 1200 environment.reload
1200 - assert_not_includes environment.enabled_plugins, plugin 1201 + assert !environment.plugin_enabled?(Plugin)
1201 end 1202 end
1202 1203
1203 should 'have production costs' do 1204 should 'have production costs' do