ldap-filter 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ldap-filter.gemspec
4
+ gemspec
@@ -0,0 +1,34 @@
1
+ # ldap-filter
2
+
3
+ While working on a Rails application that leaned heavily on my school's LDAP server, I started off writing inflexible methods like:
4
+
5
+ def uid_filter(uid)
6
+ "(uid=#{uid})"
7
+ end
8
+
9
+ def uid_or_email_filter(uid, email)
10
+ "(|(#{uid_filter(uid)})(#{email_filter(email)}))"
11
+ end
12
+
13
+ And decided it would be easier to do:
14
+
15
+ filter = LDAP::Filter::Base.new :uid, 'mrhalp' # (uid=mrhalp)
16
+ if search[:email] # mrhalp@email.org
17
+ email = LDAP::Filter::Base.new :mail, search[:email]
18
+ filter = filter | email
19
+ end
20
+ MyLDAPLibrary.search filter.to_s # (|(email=mrhalp@email.org)(uid=mrhalp))
21
+
22
+ You also don't have to worry about all those nested parentheses.
23
+
24
+ ## Install
25
+
26
+ gem install ldap-filter
27
+
28
+ With Bundler:
29
+
30
+ gem 'ldap-filter'
31
+
32
+ ## Usage
33
+
34
+ More to come soon.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "ldap/filter/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "ldap-filter"
7
+ s.version = LDAP::Filter::VERSION
8
+ s.authors = ["Eduardo Gutierrez"]
9
+ s.email = ["edd_d@mit.edu"]
10
+ s.homepage = "https://github.com/ecbypi/ldap-filter"
11
+ s.summary = %q{DSL for building LDAP filters}
12
+ s.description = %q{DSL for dynamically building complex LDAP filters without concern for closing parentheses}
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ # specify any dependencies here; for example:
20
+ s.add_development_dependency "rspec"
21
+ end
@@ -0,0 +1 @@
1
+ require 'ldap/filter'
@@ -0,0 +1,5 @@
1
+ require "ldap/filter/version"
2
+ require 'ldap/filter/base'
3
+ require 'ldap/filter/compound'
4
+ require 'ldap/filter/and_filter'
5
+ require 'ldap/filter/or_filter'
@@ -0,0 +1,10 @@
1
+ module LDAP
2
+ module Filter
3
+ class AndFilter < Compound
4
+
5
+ def initialize *args
6
+ super '&', *args
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,43 @@
1
+ module LDAP
2
+ module Filter
3
+ class Base
4
+ attr_accessor :key, :value
5
+
6
+ def initialize key, value, inverse=false
7
+ @key = key
8
+ @value = value.to_s
9
+ @not = inverse
10
+ end
11
+
12
+ def to_s
13
+ filter = '('
14
+ filter << '!' if @not
15
+ filter << condition
16
+ filter << ')'
17
+ end
18
+
19
+ def !
20
+ @not = !@not
21
+ self
22
+ end
23
+
24
+ def << value
25
+ OrFilter.new @key, @value, value
26
+ end
27
+
28
+ def | filter
29
+ OrFilter.new [self, filter]
30
+ end
31
+
32
+ def & filter
33
+ AndFilter.new [self, filter]
34
+ end
35
+
36
+ private
37
+
38
+ def condition
39
+ [@key, '=', @value].join
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,64 @@
1
+ module LDAP
2
+ module Filter
3
+ class Compound
4
+
5
+ attr_reader :children, :operator
6
+
7
+ def initialize operator, key_or_mappings, *values
8
+ @children = case key_or_mappings
9
+ when Symbol then populate_from_values key_or_mappings, values
10
+ when Array then grep key_or_mappings
11
+ when Hash then populate_from_hash key_or_mappings
12
+ end
13
+ @operator = operator unless @operator
14
+ end
15
+
16
+ def to_s
17
+ filter = '('
18
+ filter << @operator.to_s
19
+ filter << @children.map(&:to_s).join
20
+ filter << ')'
21
+ end
22
+
23
+ def << filter
24
+ raise ArgumentError, 'invalid representation of a filter' unless valid_filter?(filter)
25
+ @children << filter
26
+ end
27
+
28
+ def | filter
29
+ OrFilter.new [self, filter]
30
+ end
31
+
32
+ def & filter
33
+ AndFilter.new [self, filter]
34
+ end
35
+
36
+ private
37
+
38
+ def valid_filter? filter
39
+ filter.kind_of?(Base) ||
40
+ filter.kind_of?(Compound)
41
+ end
42
+
43
+ def grep filters
44
+ filters.select { |filter| valid_filter? filter }
45
+ end
46
+
47
+ def populate_from_hash mappings
48
+ raise ArgumentError, 'compound filters require more than one key' if mappings.keys.size < 2
49
+ mappings.map do |key, values|
50
+ case values
51
+ when Array then Compound.new('|', key, *values)
52
+ else Base.new(key, values)
53
+ end
54
+ end
55
+ end
56
+
57
+ def populate_from_values key, values
58
+ raise ArgumentError, 'need more than one value for compound filter on the same key' if values.size < 2
59
+ @operator = '|' # Cannot &'d values on the same key
60
+ values.map { |value| Base.new(key, value) }
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,10 @@
1
+ module LDAP
2
+ module Filter
3
+ class OrFilter < Compound
4
+
5
+ def initialize *args
6
+ super '|', *args
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ module LDAP
2
+ module Filter
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ require 'ldap-filter'
2
+
3
+ module LDAP
4
+ module Filter
5
+ describe AndFilter do
6
+
7
+ it "subclases LDAP::Filter::Compound, defaulting the operator to :&" do
8
+ filter = AndFilter.new(givenName: 'John', sn: 'Smith')
9
+ filter.operator.to_s.should eq '&'
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,51 @@
1
+ require 'ldap-filter'
2
+
3
+ module LDAP
4
+ module Filter
5
+
6
+ describe Base do
7
+ let(:filter) { Base.new(:givenName, 'John') }
8
+
9
+ describe "#to_s" do
10
+ it "puts together the pieces and returns usable filter" do
11
+ filter.to_s.should eq '(givenName=John)'
12
+ end
13
+ end
14
+
15
+ describe "#!" do
16
+ it "inverts the filter" do
17
+ !filter
18
+ filter.to_s.should eq '(!givenName=John)'
19
+ end
20
+ end
21
+
22
+ describe "compound methods" do
23
+ let(:other) { Base.new(:sn, 'Smith') }
24
+
25
+ describe "#<<" do
26
+ it "creates an OrFilter object under the same key" do
27
+ compound = filter << 'Smith'
28
+ compound.should be_a OrFilter
29
+ compound.to_s.should eq '(|(givenName=John)(givenName=Smith))'
30
+ end
31
+ end
32
+
33
+ describe "#|" do
34
+ it "builds an OrFilter of itself and the argument filter" do
35
+ compound = filter | other
36
+ compound.should be_a OrFilter
37
+ compound.to_s.should eq '(|(givenName=John)(sn=Smith))'
38
+ end
39
+ end
40
+
41
+ describe "#&" do
42
+ it "builds an AndFilter of itself and the argument filter" do
43
+ compound = filter & other
44
+ compound.should be_a AndFilter
45
+ compound.to_s.should eq '(&(givenName=John)(sn=Smith))'
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,106 @@
1
+ require 'ldap-filter'
2
+
3
+ module LDAP
4
+ module Filter
5
+
6
+ describe Compound do
7
+ let(:operator) { '&' } # AndOperator
8
+
9
+ describe "#to_s" do
10
+ it "builds all children filters and combines them with the operator" do
11
+ filter = Compound.new(operator, { givenName: 'John', sn: ['Smith', 'Smithers']})
12
+ filter.to_s.should eq '(&(givenName=John)(|(sn=Smith)(sn=Smithers)))'
13
+ end
14
+ end
15
+
16
+ describe "can be built from a hash" do
17
+ it "with key value pairs for base filters" do
18
+ attributes = {
19
+ givenName: 'John',
20
+ sn: 'Smith'
21
+ }
22
+ filter = Compound.new(operator, attributes)
23
+ filter.children.size.should eq 2
24
+ filter.children.first.should be_instance_of LDAP::Filter::Base
25
+ end
26
+
27
+ it "with key values pairs to create nested compound filters" do
28
+ attributes = {
29
+ givenName: ['John', 'Mary', 'Tyler'],
30
+ sn: 'Smith'
31
+ }
32
+ filter = Compound.new(operator, attributes)
33
+ filter.children.size.should eq 2
34
+ filter.children.first.should be_a LDAP::Filter::Compound
35
+ filter.children.first.children.size.should eq 3
36
+ end
37
+
38
+ it "so long as more than one key is supplied" do
39
+ expect { Compound.new('|', { givenName: 'John' }) }.to raise_error ArgumentError
40
+ end
41
+ end
42
+
43
+ describe "can be built from an array of string values" do
44
+ it "can be built using a key and an array of values" do
45
+ filter = Compound.new(operator, :givenName, 'Mary', 'John', 'Tyler')
46
+ filter.operator.should eq '|'
47
+ filter.children.size.should eq 3
48
+ end
49
+
50
+ it "so long as there is more than one value provided" do
51
+ expect { Compound.new('|', :givenName, 'Mary') }.to raise_error ArgumentError
52
+ end
53
+ end
54
+
55
+ describe "when built from other filter objects" do
56
+ let(:given_name) { Base.new(:givenName, 'John') }
57
+ let(:surname) { Base.new(:sn, 'Smith') }
58
+
59
+ it "is done using an array of filter objects" do
60
+ filter = Compound.new(operator, [given_name, surname])
61
+ filter.children.size.should eq 2
62
+ filter.children.first.should eq given_name
63
+ filter.children.last.should eq surname
64
+ end
65
+
66
+ it "takes out non-filter objects when built with an array of filters" do
67
+ filter = Compound.new(operator, [given_name, surname, 'invalid'])
68
+ filter.children.size.should eq 2
69
+ end
70
+ end
71
+
72
+ describe "compound methods" do
73
+ let(:compound) { Compound.new '|', { givenName: 'John', sn: 'Smith' } }
74
+ let(:base) { Base.new :mail, 'smith@email.org' }
75
+
76
+ describe "#<<" do
77
+ it "adds a filter to it's children" do
78
+ expect { compound << base }.to change { compound.children.size }.by 1
79
+ end
80
+
81
+ it "only accepts filter objects" do
82
+ expect { compound << 'smith@email.org' }.to raise_error ArgumentError
83
+ end
84
+ end
85
+
86
+ describe "#|" do
87
+ it "creates a new OrFilter" do
88
+ new_filter = compound | base
89
+ new_filter.children.should include(compound)
90
+ new_filter.children.should include(base)
91
+ new_filter.operator.should eq '|'
92
+ end
93
+ end
94
+
95
+ describe "#&" do
96
+ it "creates a new AndFilter" do
97
+ new_filter = compound & base
98
+ new_filter.children.should include(compound)
99
+ new_filter.children.should include(base)
100
+ new_filter.operator.should eq '&'
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,13 @@
1
+ require 'ldap-filter'
2
+
3
+ module LDAP
4
+ module Filter
5
+ describe OrFilter do
6
+
7
+ it "subclases LDAP::Filter::Compound, defaulting the operator to :&" do
8
+ filter = OrFilter.new(givenName: 'John', sn: 'Smith')
9
+ filter.operator.to_s.should eq '|'
10
+ end
11
+ end
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ldap-filter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Eduardo Gutierrez
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-28 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70129611592680 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70129611592680
25
+ description: DSL for dynamically building complex LDAP filters without concern for
26
+ closing parentheses
27
+ email:
28
+ - edd_d@mit.edu
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - .gitignore
34
+ - .rspec
35
+ - Gemfile
36
+ - README.md
37
+ - Rakefile
38
+ - ldap-filter.gemspec
39
+ - lib/ldap-filter.rb
40
+ - lib/ldap/filter.rb
41
+ - lib/ldap/filter/and_filter.rb
42
+ - lib/ldap/filter/base.rb
43
+ - lib/ldap/filter/compound.rb
44
+ - lib/ldap/filter/or_filter.rb
45
+ - lib/ldap/filter/version.rb
46
+ - spec/filter/and_filter_spec.rb
47
+ - spec/filter/base_spec.rb
48
+ - spec/filter/compound_spec.rb
49
+ - spec/filter/or_filter_spec.rb
50
+ homepage: https://github.com/ecbypi/ldap-filter
51
+ licenses: []
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project:
70
+ rubygems_version: 1.8.10
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: DSL for building LDAP filters
74
+ test_files:
75
+ - spec/filter/and_filter_spec.rb
76
+ - spec/filter/base_spec.rb
77
+ - spec/filter/compound_spec.rb
78
+ - spec/filter/or_filter_spec.rb