Commit fd9a3c230f85b124d85f12ae8d4d7e57df7785e3

Authored by Rodrigo Souto
1 parent 4e225ec6

Sub-organizations plugin

plugins/sub_organizations/controllers/sub_organizations_plugin_myprofile_controller.rb 0 → 100644
... ... @@ -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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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
... ... @@ -0,0 +1,5 @@
  1 +require_dependency 'create_enterprise'
  2 +
  3 +class CreateEnterprise
  4 + settings_items :sub_organizations_plugin_parent_to_be
  5 +end
... ...
plugins/sub_organizations/lib/sub_organizations_plugin/ext/organization.rb 0 → 100644
... ... @@ -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 @@
  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/public/style.css 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +#content .token-input-list {
  2 + margin-bottom: 30px;
  3 +}
... ...
plugins/sub_organizations/test/functional/sub_organizations_plugin_myprofile_controller_test.rb 0 → 100644
... ... @@ -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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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 @@
  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} %>
... ...