diff --git a/.gitignore b/.gitignore index 5373e77e89..1e18239793 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ test/rails_app/tmp pkg/* *.gem .vscode +spec/rails_app/tmp diff --git a/lib/devise_ldap_authenticatable/ldap/connection.rb b/lib/devise_ldap_authenticatable/ldap/connection.rb index faefa574cc..0f715f9152 100644 --- a/lib/devise_ldap_authenticatable/ldap/connection.rb +++ b/lib/devise_ldap_authenticatable/ldap/connection.rb @@ -140,7 +140,7 @@ def in_required_groups? for group in @required_groups if group.is_a?(Array) - return false unless in_group?(group[1], group[0]) + return false unless group[1..-1].select(&:present?).any? { |g| in_group?(g, group[0]) } else return false unless in_group?(group) end diff --git a/lib/generators/devise_ldap_authenticatable/templates/ldap.yml b/lib/generators/devise_ldap_authenticatable/templates/ldap.yml index 6afa181677..aa4878e03e 100644 --- a/lib/generators/devise_ldap_authenticatable/templates/ldap.yml +++ b/lib/generators/devise_ldap_authenticatable/templates/ldap.yml @@ -13,6 +13,8 @@ authorizations: &AUTHORIZATIONS - cn=users,ou=groups,dc=test,dc=com # If an array is given, the first element will be the attribute to check against, the second the group name - ["moreMembers", "cn=users,ou=groups,dc=test,dc=com"] + # If multiple group names are given, verification will be satisfied if at least one of them matches the check + - ["moreMembers", "cn=mods,ou=groups,dc=test,dc=com", "cn=admins,ou=groups,dc=test,dc=com"] ## Requires config.ldap_check_attributes in devise.rb to be true ## Can have multiple attributes and values, must match all to be authorized require_attribute: diff --git a/spec/rails_app/app/assets/config/manifest.js b/spec/rails_app/app/assets/config/manifest.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spec/unit/connection_spec.rb b/spec/unit/connection_spec.rb index 7715f2a736..3a18134060 100644 --- a/spec/unit/connection_spec.rb +++ b/spec/unit/connection_spec.rb @@ -70,6 +70,82 @@ class TestOpResult end end + describe '#in_required_groups?' do + before do + conn = double(Net::LDAP).as_null_object + allow(Net::LDAP).to receive(:new).and_return(conn) + end + + let(:check_group_membership) { true } + let(:required_groups) { %w[group1 group2] } + + let(:connection) do + Devise::LDAP::Connection.new.tap do |c| + allow(c).to receive(:dn).and_return('any dn') + c.instance_variable_set(:@required_groups, required_groups) + c.instance_variable_set(:@check_group_membership, check_group_membership) + end + end + + context 'required_groups is given as array of strings' do + it 'returns true if member of all the listed group' do + allow(connection).to receive(:in_group?).with('group1').and_return(true) + allow(connection).to receive(:in_group?).with('group2').and_return(false) + expect(connection.in_required_groups?).to be(false) + + allow(connection).to receive(:in_group?).with('group1').and_return(true) + allow(connection).to receive(:in_group?).with('group2').and_return(true) + expect(connection.in_required_groups?).to be(true) + end + end + + context 'required_groups is given as array of arrays' do + let(:required_groups) do + [ + %w[member group1 group2] + ] + end + + it 'returns true if member of any required group' do + allow(connection).to receive(:in_group?).with('group1', 'member').and_return(false) + allow(connection).to receive(:in_group?).with('group2', 'member').and_return(true) + expect(connection.in_required_groups?).to be(true) + + allow(connection).to receive(:in_group?).with('group1', 'member').and_return(true) + allow(connection).to receive(:in_group?).with('group2', 'member').and_return(false) + expect(connection.in_required_groups?).to be(true) + + allow(connection).to receive(:in_group?).with('group1', 'member').and_return(false) + allow(connection).to receive(:in_group?).with('group2', 'member').and_return(false) + expect(connection.in_required_groups?).to be(false) + end + end + + context 'with check_group_membership false' do + let(:check_group_membership) { false } + + it 'returns always true' do + expect(connection.in_required_groups?).to be(true) + end + end + + context 'with nil required_groups' do + let(:required_groups) { nil } + + it 'returns always false' do + expect(connection.in_required_groups?).to be(false) + end + end + + context 'with no required_groups' do + let(:required_groups) { [] } + + it 'returns always true' do + expect(connection.in_required_groups?).to be(true) + end + end + end + describe '#authorized?' do let(:conn) { double(Net::LDAP).as_null_object } let(:error) { }