Commit 095aeddafecc715694f6f5522294bff8e5e6f398
Exists in
master
and in
29 other branches
Merge branch 'stoa-invitation' into stoa-profile-info
Conflicts: plugins/stoa/lib/stoa_plugin.rb plugins/stoa/public/style.css
Showing
15 changed files
with
215 additions
and
21 deletions
Show diff stats
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 < Noosfero::Plugin | @@ -20,6 +20,7 @@ class StoaPlugin < 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 < Noosfero::Plugin | @@ -28,8 +29,10 @@ class StoaPlugin < 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 < Noosfero::Plugin | @@ -43,4 +46,21 @@ class StoaPlugin < 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 |
1.97 KB
3.66 KB
plugins/stoa/public/javascripts/signup_complement.js
@@ -23,14 +23,22 @@ jQuery("#usp_id_field").observe_field(1, function(){ | @@ -23,14 +23,22 @@ jQuery("#usp_id_field").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 < ActionController::TestCase | @@ -38,4 +38,9 @@ class AccountControllerTest < 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 |
@@ -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__) + '/../../../../test/test_helper' | @@ -2,16 +2,64 @@ require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
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 < ActiveSupport::TestCase | @@ -8,6 +8,7 @@ class StoaPlugin::UspUserTest < 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 < ActionController::TestCase | @@ -57,4 +57,24 @@ class FriendsControllerTest < 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 < ActiveSupport::TestCase | @@ -1187,17 +1187,18 @@ class EnvironmentTest < 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 |