Commit fd9a3c230f85b124d85f12ae8d4d7e57df7785e3
1 parent
4e225ec6
Exists in
master
and in
28 other branches
Sub-organizations plugin
Showing
18 changed files
with
687 additions
and
0 deletions
Show diff stats
plugins/sub_organizations/controllers/sub_organizations_plugin_myprofile_controller.rb
0 → 100644
@@ -0,0 +1,53 @@ | @@ -0,0 +1,53 @@ | ||
1 | +class SubOrganizationsPluginMyprofileController < MyProfileController | ||
2 | + append_view_path File.join(File.dirname(__FILE__) + '/../views') | ||
3 | + | ||
4 | + before_filter :organizations_only | ||
5 | + | ||
6 | + def index | ||
7 | + @children = SubOrganizationsPlugin::Relation.children(profile) | ||
8 | + @tokenized_children = prepare_to_token_input(@children) | ||
9 | + @pending_children = SubOrganizationsPlugin::ApprovePaternityRelation.pending_children(profile) | ||
10 | + if request.post? | ||
11 | + begin | ||
12 | + original = SubOrganizationsPlugin::Relation.children(profile) | ||
13 | + requested = Organization.find(params[:q].split(',')) | ||
14 | + added = requested - original | ||
15 | + removed = original - requested | ||
16 | + added.each do |organization| | ||
17 | + if current_person.has_permission?('perform_task',organization) | ||
18 | + SubOrganizationsPlugin::Relation.add_children(profile, organization) | ||
19 | + else | ||
20 | + SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => user, :temp_parent_type => profile.class.name, :temp_parent_id => profile.id, :target => organization) | ||
21 | + end | ||
22 | + end | ||
23 | + SubOrganizationsPlugin::Relation.remove_children(profile,removed) | ||
24 | + session[:notice] = _('Sub-organizations updated') | ||
25 | + rescue Exception => exception | ||
26 | + logger.error(exception.to_s) | ||
27 | + session[:notice] = _('Sub-organizations could not be updated') | ||
28 | + end | ||
29 | + redirect_to :action => :index | ||
30 | + end | ||
31 | + end | ||
32 | + | ||
33 | + def search_organization | ||
34 | + render :text => prepare_to_token_input(environment.organizations.find(:all, :conditions => | ||
35 | + ["(LOWER(name) LIKE ? OR LOWER(identifier) LIKE ?) | ||
36 | + AND (identifier NOT LIKE ?) AND (id != ?)", | ||
37 | + "%#{params[:q]}%", "%#{params[:q]}%", "%_template", profile.id]). | ||
38 | + select { |organization| | ||
39 | + SubOrganizationsPlugin::Relation.children(organization).blank? && | ||
40 | + !SubOrganizationsPlugin::ApprovePaternityRelation.pending_children(profile).include?(organization) | ||
41 | + }).to_json | ||
42 | + end | ||
43 | + | ||
44 | + private | ||
45 | + | ||
46 | + def organizations_only | ||
47 | + render_not_found if !profile.organization? | ||
48 | + end | ||
49 | + | ||
50 | + def prepare_to_token_input(array) | ||
51 | + array.map { |object| {:id => object.id, :name => object.name} } | ||
52 | + end | ||
53 | +end |
plugins/sub_organizations/db/migrate/20120530173629_create_relation.rb
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +class CreateRelation < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :sub_organizations_plugin_relations do |t| | ||
4 | + t.references :parent, :polymorphic => true | ||
5 | + t.references :child, :polymorphic => true | ||
6 | + end | ||
7 | + end | ||
8 | + | ||
9 | + def self.down | ||
10 | + drop_table :sub_organizations_plugin_relations | ||
11 | + end | ||
12 | +end |
plugins/sub_organizations/db/migrate/20120615202224_approve_paternity_relation.rb
0 → 100644
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +class ApprovePaternityRelation < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + create_table :sub_organizations_plugin_approve_paternity_relations do |t| | ||
4 | + t.references :task | ||
5 | + t.references :parent, :polymorphic => true | ||
6 | + t.references :child, :polymorphic => true | ||
7 | + end | ||
8 | + end | ||
9 | + | ||
10 | + def self.down | ||
11 | + drop_table :sub_organizations_plugin_approve_paternity_relations | ||
12 | + end | ||
13 | +end |
plugins/sub_organizations/lib/sub_organizations_plugin.rb
0 → 100644
@@ -0,0 +1,46 @@ | @@ -0,0 +1,46 @@ | ||
1 | +require_dependency 'sub_organizations_plugin/ext/organization' | ||
2 | +require_dependency 'sub_organizations_plugin/ext/create_enterprise' | ||
3 | + | ||
4 | +class SubOrganizationsPlugin < Noosfero::Plugin | ||
5 | + | ||
6 | + def self.plugin_name | ||
7 | + _("Sub-groups") | ||
8 | + end | ||
9 | + | ||
10 | + def self.plugin_description | ||
11 | + _("Adds the ability for groups to have sub-groups.") | ||
12 | + end | ||
13 | + | ||
14 | + def control_panel_buttons | ||
15 | + if context.profile.organization? && SubOrganizationsPlugin::Relation.parents(context.profile).blank? | ||
16 | + { :title => _('Manage sub-groups'), :icon => 'groups', :url => {:controller => 'sub_organizations_plugin_myprofile'} } | ||
17 | + end | ||
18 | + end | ||
19 | + | ||
20 | + def stylesheet? | ||
21 | + true | ||
22 | + end | ||
23 | + | ||
24 | + def organization_members(organization) | ||
25 | + children = SubOrganizationsPlugin::Relation.children(organization) | ||
26 | + Person.members_of(children) if children.present? | ||
27 | + end | ||
28 | + | ||
29 | + def has_permission?(person, permission, target) | ||
30 | + if !target.kind_of?(Environment) && target.organization? | ||
31 | + SubOrganizationsPlugin::Relation.parents(target).map do |parent| | ||
32 | + person.has_permission_without_plugins?(permission, parent) | ||
33 | + end.include?(true) | ||
34 | + end | ||
35 | + end | ||
36 | + | ||
37 | + def new_community_hidden_fields | ||
38 | + parent_to_be = context.params[:sub_organizations_plugin_parent_to_be] | ||
39 | + {'sub_organizations_plugin_parent_to_be' => parent_to_be} if parent_to_be.present? | ||
40 | + end | ||
41 | + | ||
42 | + def enterprise_registration_hidden_fields | ||
43 | + parent_to_be = context.params[:sub_organizations_plugin_parent_to_be] | ||
44 | + {'sub_organizations_plugin_parent_to_be' => parent_to_be} if parent_to_be.present? | ||
45 | + end | ||
46 | +end |
plugins/sub_organizations/lib/sub_organizations_plugin/approve_paternity.rb
0 → 100644
@@ -0,0 +1,57 @@ | @@ -0,0 +1,57 @@ | ||
1 | +class SubOrganizationsPlugin::ApprovePaternity < Task | ||
2 | + validates_presence_of :requestor, :target | ||
3 | + | ||
4 | + settings_items :temp_parent_id | ||
5 | + settings_items :temp_parent_type | ||
6 | + | ||
7 | + after_create do |task| | ||
8 | + r = SubOrganizationsPlugin::ApprovePaternityRelation.create!(:task => task, :parent => task.temp_parent, :child => task.target) | ||
9 | + end | ||
10 | + | ||
11 | + def temp_parent | ||
12 | + temp_parent_type.constantize.find(temp_parent_id) | ||
13 | + end | ||
14 | + | ||
15 | + def parent | ||
16 | + SubOrganizationsPlugin::ApprovePaternityRelation.parent(self) | ||
17 | + end | ||
18 | + | ||
19 | + def title | ||
20 | + _("Paternity request") | ||
21 | + end | ||
22 | + | ||
23 | + def linked_subject | ||
24 | + {:text => parent.name, :url => parent.url} | ||
25 | + end | ||
26 | + | ||
27 | + def information | ||
28 | + {:message => _('%{requestor} wants to add this organization as a sub-organization of %{linked_subject}.')} | ||
29 | + end | ||
30 | + | ||
31 | + def reject_details | ||
32 | + true | ||
33 | + end | ||
34 | + | ||
35 | + def icon | ||
36 | + {:type => :profile_image, :profile => parent, :url => parent.url} | ||
37 | + end | ||
38 | + | ||
39 | + def task_created_message | ||
40 | + ('%{requestor} wants to add your organization %{target} as a sub-organization of %{parent}.') % {:requestor => requestor.name, :target => target.name, :parent => temp_parent.name} | ||
41 | + end | ||
42 | + | ||
43 | + def task_finished_message | ||
44 | + ('%{target} accepted your request to add it as a sub-organization of %{parent}.') % {:target => target.name, :parent => parent.name} | ||
45 | + end | ||
46 | + | ||
47 | + def task_cancelled_message | ||
48 | + ('%{target} refused your request to add it as a sub-organization of %{parent}.') % {:target => target.name, :parent => parent.name} | ||
49 | + end | ||
50 | + | ||
51 | + protected | ||
52 | + | ||
53 | + def perform | ||
54 | + SubOrganizationsPlugin::Relation.add_children(parent, target) | ||
55 | + end | ||
56 | + | ||
57 | +end |
plugins/sub_organizations/lib/sub_organizations_plugin/approve_paternity_relation.rb
0 → 100644
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +class SubOrganizationsPlugin::ApprovePaternityRelation < Noosfero::Plugin::ActiveRecord | ||
2 | + belongs_to :task | ||
3 | + belongs_to :parent, :polymorphic => true | ||
4 | + belongs_to :child, :polymorphic => true | ||
5 | + | ||
6 | + validates_presence_of :task, :parent, :child | ||
7 | + | ||
8 | + class << self | ||
9 | + def parent(task) | ||
10 | + find_by_task_id(task.id).parent | ||
11 | + end | ||
12 | + | ||
13 | + def pending_children(parent) | ||
14 | + options = { | ||
15 | + :select => "distinct profiles.*", | ||
16 | + :joins => "inner join sub_organizations_plugin_approve_paternity_relations as relations on profiles.id=relations.child_id inner join tasks on relations.task_id=tasks.id", | ||
17 | + :conditions => ["relations.parent_id = ? AND tasks.status = 1", parent.id] | ||
18 | + } | ||
19 | + ActiveRecord::NamedScope::Scope.new(Organization, options) | ||
20 | + end | ||
21 | + end | ||
22 | + | ||
23 | +end |
plugins/sub_organizations/lib/sub_organizations_plugin/ext/create_enterprise.rb
0 → 100644
plugins/sub_organizations/lib/sub_organizations_plugin/ext/organization.rb
0 → 100644
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +require_dependency 'organization' | ||
2 | +class Organization | ||
3 | + settings_items :sub_organizations_plugin_parent_to_be | ||
4 | + | ||
5 | + after_create do |organization| | ||
6 | + if organization.sub_organizations_plugin_parent_to_be.present? | ||
7 | + parent = Organization.find(organization.sub_organizations_plugin_parent_to_be) | ||
8 | + SubOrganizationsPlugin::Relation.add_children(parent,organization) | ||
9 | + end | ||
10 | + end | ||
11 | + | ||
12 | + FIELDS << 'sub_organizations_plugin_parent_to_be' | ||
13 | +end |
plugins/sub_organizations/lib/sub_organizations_plugin/relation.rb
0 → 100644
@@ -0,0 +1,54 @@ | @@ -0,0 +1,54 @@ | ||
1 | +class SubOrganizationsPlugin::Relation < Noosfero::Plugin::ActiveRecord | ||
2 | + belongs_to :parent, :polymorphic => true | ||
3 | + belongs_to :child, :polymorphic => true | ||
4 | + | ||
5 | + validates_presence_of :parent, :child | ||
6 | + validate :no_self_reference | ||
7 | + validate :no_cyclical_reference, :if => 'parent.present? && child.present?' | ||
8 | + validate :no_multi_level, :if => 'parent.present? && child.present?' | ||
9 | + | ||
10 | + def no_self_reference | ||
11 | + errors.add(:child, _('self-reference is not allowed.')) if parent == child | ||
12 | + end | ||
13 | + | ||
14 | + def no_cyclical_reference | ||
15 | + if self.class.children(child).include?(parent) | ||
16 | + errors.add(:child, _('cyclical reference is not allowed.')) | ||
17 | + end | ||
18 | + end | ||
19 | + | ||
20 | + def no_multi_level | ||
21 | + if self.class.parents(parent).present? || self.class.children(child).present? | ||
22 | + errors.add(:child, _('multi-level paternity is not allowed.')) | ||
23 | + end | ||
24 | + end | ||
25 | + | ||
26 | + class << self | ||
27 | + def children(parent) | ||
28 | + options = { | ||
29 | + :select => "profiles.*", | ||
30 | + :joins => "inner join sub_organizations_plugin_relations as relations on profiles.id=relations.child_id", | ||
31 | + :conditions => ["relations.parent_id = ?", parent.id] | ||
32 | + } | ||
33 | + ActiveRecord::NamedScope::Scope.new(Organization, options) | ||
34 | + end | ||
35 | + | ||
36 | + def parents(child) | ||
37 | + options = { | ||
38 | + :select => "profiles.*", | ||
39 | + :joins => "inner join sub_organizations_plugin_relations as relations on profiles.id=relations.parent_id", | ||
40 | + :conditions => ["relations.child_id = ?", child.id] | ||
41 | + } | ||
42 | + ActiveRecord::NamedScope::Scope.new(Organization, options) | ||
43 | + end | ||
44 | + | ||
45 | + def add_children(parent, *children) | ||
46 | + children.each {|child| create!(:parent => parent, :child => child)} | ||
47 | + end | ||
48 | + | ||
49 | + def remove_children(parent, *children) | ||
50 | + children.flatten.each {|child| find_by_parent_id_and_child_id(parent.id, child.id).destroy} | ||
51 | + end | ||
52 | + end | ||
53 | + | ||
54 | +end |
plugins/sub_organizations/test/functional/sub_organizations_plugin_myprofile_controller_test.rb
0 → 100644
@@ -0,0 +1,89 @@ | @@ -0,0 +1,89 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
2 | +require File.dirname(__FILE__) + '/../../controllers/sub_organizations_plugin_myprofile_controller' | ||
3 | + | ||
4 | +# Re-raise errors caught by the controller. | ||
5 | +class SubOrganizationsPluginMyprofileController; def rescue_action(e) raise e end; end | ||
6 | + | ||
7 | +class SubOrganizationsPluginMyprofileControllerTest < ActionController::TestCase | ||
8 | + def setup | ||
9 | + @controller = SubOrganizationsPluginMyprofileController.new | ||
10 | + @request = ActionController::TestRequest.new | ||
11 | + @response = ActionController::TestResponse.new | ||
12 | + @organization = Organization.create!(:name => 'My Organization', :identifier => 'my-organization') | ||
13 | + @person = create_user('person').person | ||
14 | + @organization.add_admin(@person) | ||
15 | + login_as(@person.user.login) | ||
16 | + e = Environment.default | ||
17 | + e.enable_plugin('SubOrganizationsPlugin') | ||
18 | + e.save! | ||
19 | + end | ||
20 | + | ||
21 | + attr_accessor :person, :organization | ||
22 | + | ||
23 | + should 'search organizations' do | ||
24 | + # Should list if match name | ||
25 | + o1 = fast_create(Organization, :name => 'sample organization 1') | ||
26 | + # Should be case insensitive | ||
27 | + o2 = fast_create(Organization, :name => 'SaMpLe OrGaNiZaTiOn 2') | ||
28 | + # Should not list if don't match name | ||
29 | + o3 = fast_create(Organization, :name => 'blo') | ||
30 | + # Should not list if is has children | ||
31 | + child = fast_create(Organization) | ||
32 | + o4 = fast_create(Organization, :name => 'sample organization 4') | ||
33 | + SubOrganizationsPlugin::Relation.add_children(o4, child) | ||
34 | + # Should not list if is there is a task to add it | ||
35 | + o5 = fast_create(Organization, :name => 'sample enterprise 5') | ||
36 | + SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => person, :target => o5, :temp_parent_id => organization.id, :temp_parent_type => organization.class.name) | ||
37 | + # Should search by identifier | ||
38 | + o6 = fast_create(Organization, :name => 'Bla', :identifier => 'sample-enterprise-6') | ||
39 | + # Should not list itself | ||
40 | + organization.name = 'Sample Organization' | ||
41 | + organization.save! | ||
42 | + | ||
43 | + get :search_organization, :profile => organization.identifier, :q => 'sampl' | ||
44 | + | ||
45 | + assert_match /#{o1.name}/, @response.body | ||
46 | + assert_match /#{o2.name}/, @response.body | ||
47 | + assert_no_match /#{o3.name}/, @response.body | ||
48 | + assert_no_match /#{o4.name}/, @response.body | ||
49 | + assert_no_match /#{o5.name}/, @response.body | ||
50 | + assert_match /#{o6.name}/, @response.body | ||
51 | + assert_no_match /#{organization.name}/, @response.body | ||
52 | + end | ||
53 | + | ||
54 | + should 'update sub-organizations list' do | ||
55 | + org1 = fast_create(Organization) | ||
56 | + org2 = fast_create(Organization) | ||
57 | + org3 = fast_create(Organization) | ||
58 | + org4 = fast_create(Organization) | ||
59 | + SubOrganizationsPlugin::Relation.add_children(organization, org1, org2) | ||
60 | + | ||
61 | + post :index, :profile => organization.identifier, :q => [org2,org3,org4].map(&:id).join(',') | ||
62 | + | ||
63 | + children = SubOrganizationsPlugin::Relation.children(organization) | ||
64 | + assert_not_includes children, org1 | ||
65 | + assert_includes children, org2 | ||
66 | + assert_not_includes children, org3 | ||
67 | + assert_not_includes children, org4 | ||
68 | + | ||
69 | + SubOrganizationsPlugin::ApprovePaternity.all.map(&:finish) | ||
70 | + | ||
71 | + children = SubOrganizationsPlugin::Relation.children(organization) | ||
72 | + assert_not_includes children, org1 | ||
73 | + assert_includes children, org2 | ||
74 | + assert_includes children, org3 | ||
75 | + assert_includes children, org4 | ||
76 | + end | ||
77 | + | ||
78 | + should 'establish relation right away if the user can perform tasks on the sub-organization' do | ||
79 | + org1 = fast_create(Organization) | ||
80 | + org2 = fast_create(Organization) | ||
81 | + org2.add_admin(person) | ||
82 | + | ||
83 | + assert_difference SubOrganizationsPlugin::ApprovePaternity, :count, 1 do | ||
84 | + post :index, :profile => organization.identifier, :q => [org1,org2].map(&:id).join(',') | ||
85 | + end | ||
86 | + assert_includes SubOrganizationsPlugin::Relation.children(organization), org2 | ||
87 | + end | ||
88 | + | ||
89 | +end |
plugins/sub_organizations/test/unit/sub_organizations_plugin/approve_paternity_relation_test.rb
0 → 100644
@@ -0,0 +1,32 @@ | @@ -0,0 +1,32 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class SubOrganizationsPlugin::ApprovePaternityRelationTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @requestor = create_user('some-user').person | ||
7 | + end | ||
8 | + | ||
9 | + attr_reader :requestor | ||
10 | + | ||
11 | + should 'return parent' do | ||
12 | + org1 = fast_create(Organization) | ||
13 | + org2 = fast_create(Organization) | ||
14 | + task = SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => requestor, :target => org2, :temp_parent_id => org1.id, :temp_parent_type => org1.class.name) | ||
15 | + | ||
16 | + assert_equal SubOrganizationsPlugin::ApprovePaternityRelation.parent(task), org1 | ||
17 | + end | ||
18 | + | ||
19 | + should 'list pending children' do | ||
20 | + organization = fast_create(Organization) | ||
21 | + org1 = fast_create(Organization) | ||
22 | + org2 = fast_create(Organization) | ||
23 | + org3 = fast_create(Organization) | ||
24 | + | ||
25 | + SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => requestor, :target => org1, :temp_parent_id => organization.id, :temp_parent_type => organization.class.name) | ||
26 | + SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => requestor, :target => org2, :temp_parent_id => organization.id, :temp_parent_type => organization.class.name) | ||
27 | + | ||
28 | + assert_includes SubOrganizationsPlugin::ApprovePaternityRelation.pending_children(organization), org1 | ||
29 | + assert_includes SubOrganizationsPlugin::ApprovePaternityRelation.pending_children(organization), org2 | ||
30 | + assert_not_includes SubOrganizationsPlugin::ApprovePaternityRelation.pending_children(organization), org3 | ||
31 | + end | ||
32 | +end |
plugins/sub_organizations/test/unit/sub_organizations_plugin/approve_paternity_test.rb
0 → 100644
@@ -0,0 +1,29 @@ | @@ -0,0 +1,29 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class SubOrganizationsPlugin::ApprovePaternityTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @requestor = create_user('some-user').person | ||
7 | + end | ||
8 | + | ||
9 | + attr_reader :requestor | ||
10 | + | ||
11 | + should 'create relation after creation' do | ||
12 | + org1 = fast_create(Organization) | ||
13 | + org2 = fast_create(Organization) | ||
14 | + assert_difference SubOrganizationsPlugin::ApprovePaternityRelation, :count, 1 do | ||
15 | + SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => requestor, :temp_parent_id => org1.id, :temp_parent_type => org1.class.name, :target => org2) | ||
16 | + end | ||
17 | + end | ||
18 | + | ||
19 | + should 'add children to parent after approving' do | ||
20 | + org1 = fast_create(Organization) | ||
21 | + org2 = fast_create(Organization) | ||
22 | + | ||
23 | + task = SubOrganizationsPlugin::ApprovePaternity.create!(:requestor => requestor, :temp_parent_id => org1.id, :temp_parent_type => org1.class.name, :target => org2) | ||
24 | + assert_not_includes SubOrganizationsPlugin::Relation.children(org1), org2 | ||
25 | + | ||
26 | + task.finish | ||
27 | + assert_includes SubOrganizationsPlugin::Relation.children(org1), org2 | ||
28 | + end | ||
29 | +end |
plugins/sub_organizations/test/unit/sub_organizations_plugin/ext/create_enterprise_test.rb
0 → 100644
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../../test/test_helper' | ||
2 | + | ||
3 | +class CreateEnterpriseTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'inlude the parent field in create enterprise' do | ||
6 | + create_enterprise = CreateEnterprise.new | ||
7 | + assert_nothing_raised { create_enterprise.sub_organizations_plugin_parent_to_be = '999' } | ||
8 | + end | ||
9 | + | ||
10 | +end | ||
11 | + |
plugins/sub_organizations/test/unit/sub_organizations_plugin/ext/organization.rb
0 → 100644
@@ -0,0 +1,23 @@ | @@ -0,0 +1,23 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../../test/test_helper' | ||
2 | + | ||
3 | +class OrganizationTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'inlude the parent field in organization' do | ||
6 | + organization = Organization.new | ||
7 | + assert_nothing_raised { organization.sub_organizations_plugin_parent_to_be = '999' } | ||
8 | + end | ||
9 | + | ||
10 | + should 'include the parent field in the FIELDS constant' do | ||
11 | + assert_includes Organization::FIELDS, 'sub_organizations_plugin_parent_to_be' | ||
12 | + end | ||
13 | + | ||
14 | + should 'relate organization with parent if the attribute is set' do | ||
15 | + parent = fast_create(Organization) | ||
16 | + organization = Organization.new(:identifier => 'some-org',:name => 'Some Org', :sub_organizations_plugin_parent_to_be => parent.id) | ||
17 | + assert_not_includes SubOrganizationsPlugin::Relation.children(parent), organization | ||
18 | + | ||
19 | + organization.save! | ||
20 | + assert_includes SubOrganizationsPlugin::Relation.children(parent), organization | ||
21 | + end | ||
22 | + | ||
23 | +end |
plugins/sub_organizations/test/unit/sub_organizations_plugin/relation_test.rb
0 → 100644
@@ -0,0 +1,110 @@ | @@ -0,0 +1,110 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../../test/test_helper' | ||
2 | + | ||
3 | +class SubOrganizationsPlugin::RelationTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + should 'validates presence of child and parent' do | ||
6 | + org = fast_create(Organization) | ||
7 | + relation = SubOrganizationsPlugin::Relation.new | ||
8 | + | ||
9 | + relation.parent = org | ||
10 | + relation.valid? | ||
11 | + assert relation.errors.invalid?(:child) | ||
12 | + | ||
13 | + relation.parent = nil | ||
14 | + relation.child = org | ||
15 | + relation.valid? | ||
16 | + assert relation.errors.invalid?(:parent) | ||
17 | + end | ||
18 | + | ||
19 | + should 'relate two organizations' do | ||
20 | + org1 = fast_create(Organization) | ||
21 | + org2 = fast_create(Organization) | ||
22 | + relation = SubOrganizationsPlugin::Relation.create!(:parent => org1, :child => org2) | ||
23 | + | ||
24 | + assert_equal org1, relation.parent | ||
25 | + assert_equal org2, relation.child | ||
26 | + end | ||
27 | + | ||
28 | + should 'not allow self relation' do | ||
29 | + org = fast_create(Organization) | ||
30 | + relation = SubOrganizationsPlugin::Relation.new(:parent_id => org, :child_id => org) | ||
31 | + assert !relation.valid? | ||
32 | + assert relation.errors.invalid?(:child) | ||
33 | + end | ||
34 | + | ||
35 | + should 'be able to retrieve parents of an organization' do | ||
36 | + child = fast_create(Organization) | ||
37 | + parent1 = fast_create(Organization) | ||
38 | + parent2 = fast_create(Organization) | ||
39 | + SubOrganizationsPlugin::Relation.create!(:parent => parent1, :child => child) | ||
40 | + SubOrganizationsPlugin::Relation.create!(:parent => parent2, :child => child) | ||
41 | + | ||
42 | + assert_includes SubOrganizationsPlugin::Relation.parents(child), parent1 | ||
43 | + assert_includes SubOrganizationsPlugin::Relation.parents(child), parent2 | ||
44 | + end | ||
45 | + | ||
46 | + should 'be able to retrieve children of an organization' do | ||
47 | + parent = fast_create(Organization) | ||
48 | + child1 = fast_create(Organization) | ||
49 | + child2 = fast_create(Organization) | ||
50 | + SubOrganizationsPlugin::Relation.create!(:parent => parent, :child => child1) | ||
51 | + SubOrganizationsPlugin::Relation.create!(:parent => parent, :child => child2) | ||
52 | + | ||
53 | + assert_includes SubOrganizationsPlugin::Relation.children(parent), child1 | ||
54 | + assert_includes SubOrganizationsPlugin::Relation.children(parent), child2 | ||
55 | + end | ||
56 | + | ||
57 | + should 'not allow cyclical reference' do | ||
58 | + org1 = fast_create(Organization) | ||
59 | + org2 = fast_create(Organization) | ||
60 | + SubOrganizationsPlugin::Relation.create!(:parent => org1, :child => org2) | ||
61 | + relation = SubOrganizationsPlugin::Relation.new(:parent => org2, :child => org1) | ||
62 | + | ||
63 | + assert !relation.valid? | ||
64 | + assert relation.errors.invalid?(:child) | ||
65 | + end | ||
66 | + | ||
67 | + should 'not allow multi-level paternity' do | ||
68 | + org1 = fast_create(Organization) | ||
69 | + org2 = fast_create(Organization) | ||
70 | + org3 = fast_create(Organization) | ||
71 | + SubOrganizationsPlugin::Relation.create!(:parent => org1, :child => org2) | ||
72 | + r1 = SubOrganizationsPlugin::Relation.new(:parent => org2, :child => org3) | ||
73 | + r2 = SubOrganizationsPlugin::Relation.new(:parent => org3, :child => org1) | ||
74 | + | ||
75 | + assert !r1.valid? | ||
76 | + assert r1.errors.invalid?(:child) | ||
77 | + | ||
78 | + assert !r2.valid? | ||
79 | + assert r2.errors.invalid?(:child) | ||
80 | + end | ||
81 | + | ||
82 | + should 'add children' do | ||
83 | + org1 = fast_create(Organization) | ||
84 | + org2 = fast_create(Organization) | ||
85 | + org3 = fast_create(Organization) | ||
86 | + org4 = fast_create(Organization) | ||
87 | + | ||
88 | + SubOrganizationsPlugin::Relation.add_children(org1,org2) | ||
89 | + assert_includes SubOrganizationsPlugin::Relation.children(org1), org2 | ||
90 | + | ||
91 | + SubOrganizationsPlugin::Relation.add_children(org1,org3,org4) | ||
92 | + assert_includes SubOrganizationsPlugin::Relation.children(org1), org3 | ||
93 | + assert_includes SubOrganizationsPlugin::Relation.children(org1), org4 | ||
94 | + end | ||
95 | + | ||
96 | + should 'remove children' do | ||
97 | + org1 = fast_create(Organization) | ||
98 | + org2 = fast_create(Organization) | ||
99 | + org3 = fast_create(Organization) | ||
100 | + org4 = fast_create(Organization) | ||
101 | + SubOrganizationsPlugin::Relation.add_children(org1,org2,org3,org4) | ||
102 | + | ||
103 | + SubOrganizationsPlugin::Relation.remove_children(org1,org2) | ||
104 | + assert_not_includes SubOrganizationsPlugin::Relation.children(org1), org2 | ||
105 | + | ||
106 | + SubOrganizationsPlugin::Relation.remove_children(org1,org3,org4) | ||
107 | + assert_not_includes SubOrganizationsPlugin::Relation.children(org1), org3 | ||
108 | + assert_not_includes SubOrganizationsPlugin::Relation.children(org1), org4 | ||
109 | + end | ||
110 | +end |
plugins/sub_organizations/test/unit/sub_organizations_plugin_test.rb
0 → 100644
@@ -0,0 +1,83 @@ | @@ -0,0 +1,83 @@ | ||
1 | +require File.dirname(__FILE__) + '/../../../../test/test_helper' | ||
2 | + | ||
3 | +class SubOrganizationsTest < ActiveSupport::TestCase | ||
4 | + | ||
5 | + def setup | ||
6 | + @plugin = SubOrganizationsPlugin.new | ||
7 | + end | ||
8 | + | ||
9 | + attr_reader :plugin | ||
10 | + | ||
11 | + should 'include sub-organizations members in the parent organization' do | ||
12 | + org1 = fast_create(Organization) | ||
13 | + org2 = fast_create(Organization) | ||
14 | + org3 = fast_create(Organization) | ||
15 | + member1 = fast_create(Person) | ||
16 | + member2 = fast_create(Person) | ||
17 | + member3 = fast_create(Person) | ||
18 | + member4 = fast_create(Person) | ||
19 | + member5 = fast_create(Person) | ||
20 | + member6 = fast_create(Person) | ||
21 | + member7 = fast_create(Person) | ||
22 | + org1.add_member(member1) | ||
23 | + org2.add_member(member2) | ||
24 | + org2.add_member(member3) | ||
25 | + org3.add_member(member4) | ||
26 | + org3.add_member(member5) | ||
27 | + SubOrganizationsPlugin::Relation.create!(:parent => org1, :child => org2) | ||
28 | + SubOrganizationsPlugin::Relation.create!(:parent => org1, :child => org3) | ||
29 | + | ||
30 | + org1_members = plugin.organization_members(org1) | ||
31 | + | ||
32 | + assert_equal ActiveRecord::NamedScope::Scope, org1_members.class | ||
33 | + assert_not_includes org1_members, member1 | ||
34 | + assert_includes org1_members, member2 | ||
35 | + assert_includes org1_members, member3 | ||
36 | + assert_includes org1_members, member4 | ||
37 | + assert_includes org1_members, member5 | ||
38 | + assert_not_includes org1_members, member6 | ||
39 | + assert_not_includes org1_members, member7 | ||
40 | + | ||
41 | + org2_members = plugin.organization_members(org2) | ||
42 | + org3_members = plugin.organization_members(org3) | ||
43 | + | ||
44 | + assert org2_members.blank? | ||
45 | + assert org3_members.blank? | ||
46 | + end | ||
47 | + | ||
48 | + should 'grant permission that user has on parent organizations over children orgnaizations' do | ||
49 | + person = create_user('admin-user').person | ||
50 | + org1 = fast_create(Organization) | ||
51 | + org2 = fast_create(Organization) | ||
52 | + SubOrganizationsPlugin::Relation.add_children(org1,org2) | ||
53 | + person.stubs('has_permission_without_plugins?').with(:make_ice_cream, org1).returns(true) | ||
54 | + person.stubs('has_permission_without_plugins?').with(:make_ice_cream, org2).returns(false) | ||
55 | + | ||
56 | + assert plugin.has_permission?(person, :make_ice_cream, org2) | ||
57 | + end | ||
58 | + | ||
59 | + should 'not crash if receives an environment as target of has permission' do | ||
60 | + assert_nothing_raised do | ||
61 | + plugin.has_permission?(fast_create(Person), :make_ice_cream, fast_create(Environment)) | ||
62 | + end | ||
63 | + end | ||
64 | + | ||
65 | + should 'display control panel button only to organizations with no parent' do | ||
66 | + org1 = fast_create(Organization) | ||
67 | + org2 = fast_create(Organization) | ||
68 | + profile = fast_create(Profile) | ||
69 | + SubOrganizationsPlugin::Relation.add_children(org1,org2) | ||
70 | + context = mock() | ||
71 | + SubOrganizationsPlugin.any_instance.stubs(:context).returns(context) | ||
72 | + | ||
73 | + context.stubs(:profile).returns(org1) | ||
74 | + assert_not_nil plugin.control_panel_buttons | ||
75 | + | ||
76 | + context.stubs(:profile).returns(org2) | ||
77 | + assert_nil plugin.control_panel_buttons | ||
78 | + | ||
79 | + context.stubs(:profile).returns(profile) | ||
80 | + assert_nil plugin.control_panel_buttons | ||
81 | + end | ||
82 | +end | ||
83 | + |
plugins/sub_organizations/views/sub_organizations_plugin_myprofile/index.html.erb
0 → 100644
@@ -0,0 +1,31 @@ | @@ -0,0 +1,31 @@ | ||
1 | +<h1><%= _('Manage sub-groups') %></h1> | ||
2 | + | ||
3 | +<% if !@pending_children.blank? %> | ||
4 | + <%= _('Sub-groups awaiting approval:') %> | ||
5 | + <ul> | ||
6 | + <% @pending_children.each do |child| %> | ||
7 | + <li><%= link_to(child.name, child.url) %></li> | ||
8 | + <% end %> | ||
9 | + </ul> | ||
10 | +<% end %> | ||
11 | + | ||
12 | +<% form_tag do %> | ||
13 | + <% button_bar do %> | ||
14 | + <%= button(:add, __('Create a new sub-community'), :controller => 'memberships', :action => 'new_community', :profile => user.identifier, :sub_organizations_plugin_parent_to_be => profile.id) %> | ||
15 | + <%= button :add, __('Register a new sub-enterprise'), :controller => 'enterprise_registration', :sub_organizations_plugin_parent_to_be => profile.id if environment.enabled?('enterprise_registration') %> | ||
16 | + <% end %> | ||
17 | + | ||
18 | + <%= token_input_field_tag(:q, 'search-organization', {:action => 'search_organization'}, | ||
19 | + { :focus => true, | ||
20 | + :hint_text => _('Type in a search term for a group'), | ||
21 | + :pre_populate => @tokenized_children}) %> | ||
22 | + | ||
23 | + <% button_bar do %> | ||
24 | + <%= submit_button('save', _('Save'))%> | ||
25 | + <%= button('cancel', _('Cancel'), {:controller => 'profile_editor'})%> | ||
26 | + <% end %> | ||
27 | +<% end %> | ||
28 | + | ||
29 | +<br style='clear: both'/> | ||
30 | + | ||
31 | +<%= render :partial => 'shared/list_groups', :locals => {:profile => user, :groups => @children} %> |