ucb_groups 0.0.2
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.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +54 -0
- data/Rakefile +1 -0
- data/lib/ucb_groups/campus_group.rb +31 -0
- data/lib/ucb_groups/ldap_conn.rb +36 -0
- data/lib/ucb_groups/membership_filter.rb +50 -0
- data/lib/ucb_groups/membership_finder.rb +52 -0
- data/lib/ucb_groups/monkey_patches/net_ldap_filter.rb +38 -0
- data/lib/ucb_groups/person.rb +41 -0
- data/lib/ucb_groups/version.rb +3 -0
- data/lib/ucb_groups.rb +36 -0
- data/spec/integration/calmsgs_groups_spec.rb +127 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/ucb_groups/campus_group_spec.rb +25 -0
- data/spec/ucb_groups/membership_filter_spec.rb +54 -0
- data/spec/ucb_groups/membership_finder_spec.rb +52 -0
- data/spec/ucb_groups_spec.rb +4 -0
- data/ucb_groups.gemspec +29 -0
- metadata +169 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8a70a98622c14e05dc6d97321b88fa49814fe37c
|
4
|
+
data.tar.gz: f7a84e130fabac3db97c20f6927151eca557b66b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dbb318e65608a45bb2f15782012ab6e556592cc1102cc774198cff91402542ba9ecbc2cd87660b008b9007ae37021bc78d338050aa0679ac64d5f87f32888d4b
|
7
|
+
data.tar.gz: aa28f08ef4abddf05884c02a979acbf67e4312f57b19a0e65a6a42549edceba8c9ebc1d45808606f26f95c5f36fbef4dee11cb149170b5516698c23997a936f9
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 sahglie
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# UcbGroups
|
2
|
+
|
3
|
+
Finds users that belong to a given ucb group
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'ucb_groups'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install ucb_groups
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
First, authenticate:
|
22
|
+
```
|
23
|
+
UcbGroups::LdapConn.authenticate(<username>, <password>)
|
24
|
+
```
|
25
|
+
|
26
|
+
Then...
|
27
|
+
|
28
|
+
Get list of groups in namespace:
|
29
|
+
```
|
30
|
+
UcbGroups::CampusGroup.find(<namespace>)
|
31
|
+
=> [CampusGroup, CampusGroup, ...]
|
32
|
+
```
|
33
|
+
|
34
|
+
Find people in one or more groups:
|
35
|
+
```
|
36
|
+
finder = UcbGroups::MembershipFinder.new(<namespace>)
|
37
|
+
people = finder.find(:groups => [grp1, grp2])
|
38
|
+
=> [Person, Person, Person, ...]
|
39
|
+
```
|
40
|
+
|
41
|
+
Find people in groups and filter by org:
|
42
|
+
```
|
43
|
+
finder = UcbGroups::MembershipFinder.new(<namespace>)
|
44
|
+
people = finder.find(:groups => [grp1, grp2], :orgs => [:JKASD])
|
45
|
+
=> [Person, Person, Person, ...]
|
46
|
+
```
|
47
|
+
|
48
|
+
## Contributing
|
49
|
+
|
50
|
+
1. Fork it
|
51
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
52
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
53
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
54
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module UcbGroups
|
2
|
+
class CampusGroup
|
3
|
+
attr_accessor :dn, :description, :namespace, :name
|
4
|
+
|
5
|
+
def initialize(ldap_entry)
|
6
|
+
@dn = ldap_entry[:dn].first.to_s
|
7
|
+
@description = ldap_entry[:description].first.to_s
|
8
|
+
@namespace, @name = parse_dn
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.find(namespace)
|
12
|
+
args = {
|
13
|
+
:base => "ou=campus groups,dc=berkeley,dc=edu",
|
14
|
+
:filter => build_filter(namespace),
|
15
|
+
:attributes => %w(dn description name),
|
16
|
+
}
|
17
|
+
LdapConn.conn.search(args).map { |entry| CampusGroup.new(entry) }
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# example dn: "cn=edu:berkeley:app:calmessages:faculty,ou=campus groups,dc=berkeley,dc=edu"
|
23
|
+
def parse_dn
|
24
|
+
dn.split(/:|,/)[3..4].map(&:to_s)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.build_filter(namespace)
|
28
|
+
"(&(objectclass=*)(cn=edu:berkeley:app:#{namespace}*))"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module UcbGroups
|
2
|
+
class LdapConn
|
3
|
+
def self.conn
|
4
|
+
net_ldap = ::Net::LDAP.new(auth_info)
|
5
|
+
net_ldap.bind || raise(BindFailedException)
|
6
|
+
net_ldap
|
7
|
+
rescue ::Net::LDAP::LdapError
|
8
|
+
raise(LdapBindFailedException)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.authenticate(username, password)
|
12
|
+
@username = username
|
13
|
+
@password = password
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.authenticate_from_config(config_file)
|
17
|
+
conf = YAML.load_file(config_file)
|
18
|
+
@username, @password = conf['username'], conf['password']
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def self.auth_info
|
24
|
+
@auth_info ||= {
|
25
|
+
host: "ldap.berkeley.edu",
|
26
|
+
auth: {
|
27
|
+
method: :simple,
|
28
|
+
username: @username,
|
29
|
+
password: @password,
|
30
|
+
},
|
31
|
+
port: 636,
|
32
|
+
encryption: { method: :simple_tls }
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module UcbGroups
|
2
|
+
class MembershipFilter
|
3
|
+
attr_accessor :namespace, :groups, :orgs
|
4
|
+
|
5
|
+
def initialize(namespace, groups, orgs)
|
6
|
+
@namespace = namespace
|
7
|
+
@groups = groups
|
8
|
+
@orgs = orgs
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
@filter ||= begin
|
13
|
+
if groups.empty?
|
14
|
+
objectclass_filter & orgs_filter
|
15
|
+
elsif orgs.empty?
|
16
|
+
objectclass_filter & groups_filter
|
17
|
+
else
|
18
|
+
objectclass_filter & (groups_filter & orgs_filter)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
@filter.to_rfc2254
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def objectclass_filter
|
27
|
+
Net::LDAP::Filter.eq("objectclass", "person")
|
28
|
+
end
|
29
|
+
|
30
|
+
def groups_filter
|
31
|
+
groups.map { |group| group_filter(group) }
|
32
|
+
.reduce { |accum, filter| accum.send("|", filter) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def group_filter(group)
|
36
|
+
Net::LDAP::Filter.
|
37
|
+
eq("ismemberof",
|
38
|
+
"cn=edu:berkeley:app:#{self.namespace}:#{group},ou=campus groups,dc=berkeley,dc=edu")
|
39
|
+
end
|
40
|
+
|
41
|
+
def orgs_filter
|
42
|
+
@orgs.map { |org| org_filter(org) }
|
43
|
+
.reduce { |accum, filter| accum.send("|", filter) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def org_filter(org)
|
47
|
+
Net::LDAP::Filter.eq("berkeleyedudeptunithierarchystring", "*#{org}*")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module UcbGroups
|
2
|
+
class MembershipFinder
|
3
|
+
attr_accessor :namespace, :groups, :orgs
|
4
|
+
|
5
|
+
def initialize(namespace)
|
6
|
+
@namespace = namespace
|
7
|
+
end
|
8
|
+
|
9
|
+
def find(*options)
|
10
|
+
@groups, @orgs = parse_options(options)
|
11
|
+
|
12
|
+
return [] if @groups.empty? && @orgs.empty?
|
13
|
+
|
14
|
+
ensure_valid_options
|
15
|
+
|
16
|
+
args = {
|
17
|
+
base: "ou=people,dc=berkeley,dc=edu",
|
18
|
+
filter: membership_filter,
|
19
|
+
attributes: Person.ldap_attributes
|
20
|
+
}
|
21
|
+
|
22
|
+
LdapConn.conn.search(args).map { |entry| Person.new(entry) }
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def parse_options(options)
|
28
|
+
options = options.first || {}
|
29
|
+
groups = options.fetch(:groups, []).map(&:to_s)
|
30
|
+
orgs = options.fetch(:orgs, []).map(&:to_s)
|
31
|
+
|
32
|
+
[groups, orgs]
|
33
|
+
end
|
34
|
+
|
35
|
+
def ensure_valid_options
|
36
|
+
groups.each do |group|
|
37
|
+
unless namespace_groups.include?(group.to_s)
|
38
|
+
raise(InvalidCampusGroupError.new(group))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def membership_filter
|
44
|
+
MembershipFilter.new(namespace, groups, orgs).to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
def namespace_groups
|
48
|
+
@namespace_groups ||= CampusGroup.find(namespace).map(&:name)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Pull request with this patch has been submitted via github. As soon
|
2
|
+
# as this patch is merged into ruby-net-ldap master branch we can remove
|
3
|
+
# this monkey patch
|
4
|
+
|
5
|
+
Net::LDAP::Filter::FilterParser.class_eval do
|
6
|
+
def parse_filter_branch(scanner)
|
7
|
+
scanner.scan(/\s*/)
|
8
|
+
if token = scanner.scan(/[-\w:.]*[\w]/)
|
9
|
+
scanner.scan(/\s*/)
|
10
|
+
if op = scanner.scan(/<=|>=|!=|:=|=/)
|
11
|
+
scanner.scan(/\s*/)
|
12
|
+
#if value = scanner.scan(/(?:[-\w*.+@=,#\$%&!'\s]|\\[a-fA-F\d]{2})+/)
|
13
|
+
|
14
|
+
# Our patch allows ':' as a valid character.
|
15
|
+
if value = scanner.scan(/(?:[-\w*.+@=,:#\$%&!'\s]|\\[a-fA-F\d]{2})+/)
|
16
|
+
# 20100313 AZ: Assumes that "(uid=george*)" is the same as
|
17
|
+
# "(uid=george* )". The standard doesn't specify, but I can find
|
18
|
+
# no examples that suggest otherwise.
|
19
|
+
value.strip!
|
20
|
+
|
21
|
+
case op
|
22
|
+
when "="
|
23
|
+
Net::LDAP::Filter.eq(token, value)
|
24
|
+
when "!="
|
25
|
+
Net::LDAP::Filter.ne(token, value)
|
26
|
+
when "<="
|
27
|
+
Net::LDAP::Filter.le(token, value)
|
28
|
+
when ">="
|
29
|
+
Net::LDAP::Filter.ge(token, value)
|
30
|
+
when ":="
|
31
|
+
Net::LDAP::Filter.ex(token, value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module UcbGroups
|
2
|
+
class Person
|
3
|
+
include Comparable
|
4
|
+
|
5
|
+
ATTRIBUTE_MAPPINGS = {
|
6
|
+
:uid => :uid,
|
7
|
+
:first_name => :givenname,
|
8
|
+
:last_name => :sn,
|
9
|
+
:email => :mail,
|
10
|
+
:orgs => :berkeleyEduPrimaryDeptUnitHierarchyString
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
attr_accessor *ATTRIBUTE_MAPPINGS.keys
|
14
|
+
|
15
|
+
def initialize(ldap_entry)
|
16
|
+
ATTRIBUTE_MAPPINGS.each do |attr, val|
|
17
|
+
self.send("#{attr}=", ldap_entry[val].first.to_s) if ldap_entry[val]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def full_name
|
22
|
+
[first_name, last_name].join(" ")
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.ldap_attributes
|
26
|
+
@ldap_attributes ||= ATTRIBUTE_MAPPINGS.values.map(&:to_s)
|
27
|
+
end
|
28
|
+
|
29
|
+
def eql?(other_person)
|
30
|
+
self.hash == other_person.hash
|
31
|
+
end
|
32
|
+
|
33
|
+
def hash
|
34
|
+
self.uid.to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
def <=>(other_person)
|
38
|
+
self.hash <=> other_person.hash
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/ucb_groups.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'net-ldap'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
require "ucb_groups/version"
|
7
|
+
require "ucb_groups/person"
|
8
|
+
require "ucb_groups/ldap_conn"
|
9
|
+
require "ucb_groups/campus_group"
|
10
|
+
require "ucb_groups/membership_filter"
|
11
|
+
require "ucb_groups/membership_finder"
|
12
|
+
require "ucb_groups/monkey_patches/net_ldap_filter"
|
13
|
+
|
14
|
+
|
15
|
+
module UcbGroups
|
16
|
+
LdapBindFailedException = Class.new(StandardError)
|
17
|
+
|
18
|
+
class InvalidCampusGroupError < StandardError
|
19
|
+
def initialize(group)
|
20
|
+
super(group)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class InvalidFinderOptions < StandardError
|
25
|
+
def initialize
|
26
|
+
super("You must provide at least one group or one org")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
if __FILE__ == $PROGRAM_NAME
|
33
|
+
finder = UcbGroups::MembershipFinder.new("calmessages")
|
34
|
+
people = finder.find(:groups => ["it-staff"], :orgs => ["JKASD"])
|
35
|
+
pp people
|
36
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
require_relative "../spec_helper"
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
#groups = UcbGroups::CampusGroup.find(:calmessages)
|
6
|
+
#pp groups.map(&:name).sort
|
7
|
+
|
8
|
+
|
9
|
+
def assert_matching_group(group)
|
10
|
+
@finder ||= UcbGroups::MembershipFinder.new(:calmessages)
|
11
|
+
grouper_uids = @finder.find(:groups => [group]).map(&:uid).sort
|
12
|
+
calmsgs_uids = calmsgs_group_uids(group)
|
13
|
+
|
14
|
+
#if calmsgs_uids.length != grouper_uids.length
|
15
|
+
puts "calmsgs: #{calmsgs_uids.length}, grouper: #{grouper_uids.length}"
|
16
|
+
puts "Only In Calmsgs: #{calmsgs_uids - grouper_uids}\nOnly in Grouper: #{grouper_uids - calmsgs_uids}"
|
17
|
+
grouper_uids.length.should eql(calmsgs_uids.length)
|
18
|
+
#end
|
19
|
+
|
20
|
+
calmsgs_uids.should eql(grouper_uids)
|
21
|
+
end
|
22
|
+
|
23
|
+
def calmsgs_group_uids(group)
|
24
|
+
uids = RestClient.get("localhost:3000/api/groups/#{group}.json")
|
25
|
+
JSON.parse(uids).map(&:to_s).sort
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
describe "Calmsgs Groups Compatibility" do
|
30
|
+
it "academic-senate-faculty" do
|
31
|
+
# fails but close enough
|
32
|
+
assert_matching_group("academic-senate-faculty")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "deans" do
|
36
|
+
# fails but close enough
|
37
|
+
assert_matching_group("deans")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "dept-admin" do
|
41
|
+
# fails because ldap does not keep emptititlecode around for expired people and caldap does (close enough)
|
42
|
+
assert_matching_group("dept-admin")
|
43
|
+
end
|
44
|
+
|
45
|
+
it "dept-chairs" do
|
46
|
+
# fails but close enough
|
47
|
+
assert_matching_group("dept-chairs")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "directors" do
|
51
|
+
assert_matching_group("directors")
|
52
|
+
end
|
53
|
+
|
54
|
+
it "emeriti" do
|
55
|
+
assert_matching_group("emeriti")
|
56
|
+
end
|
57
|
+
|
58
|
+
it "faculty" do
|
59
|
+
# fails because calmsgs is grabbing people that it shouldn't. In many instances calmsgs
|
60
|
+
# is grabbing staff that have no academic affiliation (close enough)
|
61
|
+
assert_matching_group("faculty")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "it-staff" do
|
65
|
+
# fails because calmsgs it grabbing retired or expired it-staff (close enough)
|
66
|
+
assert_matching_group("it-staff")
|
67
|
+
end
|
68
|
+
|
69
|
+
it "staff" do
|
70
|
+
# fails but close enough
|
71
|
+
assert_matching_group("staff")
|
72
|
+
end
|
73
|
+
|
74
|
+
it "students" do
|
75
|
+
# fails but close enough
|
76
|
+
assert_matching_group("students")
|
77
|
+
end
|
78
|
+
|
79
|
+
it "managers" do
|
80
|
+
assert_matching_group("managers") # fails but close enough
|
81
|
+
end
|
82
|
+
|
83
|
+
it "supervisors" do
|
84
|
+
assert_matching_group("supervisors") # fails but close enough
|
85
|
+
end
|
86
|
+
|
87
|
+
it "affiliates" do
|
88
|
+
assert_matching_group("affiliates") # fails
|
89
|
+
end
|
90
|
+
|
91
|
+
it "ucop" do
|
92
|
+
# fails but close enough
|
93
|
+
assert_matching_group("ucop")
|
94
|
+
end
|
95
|
+
|
96
|
+
it "graduate-students" do
|
97
|
+
# no calmsgs group
|
98
|
+
# assert_matching_group("graduate-students")
|
99
|
+
end
|
100
|
+
|
101
|
+
it "advisors" do
|
102
|
+
# no calmsgs group
|
103
|
+
# assert_matching_group("advisors")
|
104
|
+
end
|
105
|
+
|
106
|
+
it "gsis" do
|
107
|
+
# no calmsgs group
|
108
|
+
# assert_matching_group("gsis")
|
109
|
+
end
|
110
|
+
|
111
|
+
it "gsrs" do
|
112
|
+
# no calmsgs group
|
113
|
+
# assert_matching_group("gsrs")
|
114
|
+
end
|
115
|
+
|
116
|
+
it "instructors" do
|
117
|
+
# no calmsgs group
|
118
|
+
#assert_matching_group("instructors")
|
119
|
+
end
|
120
|
+
|
121
|
+
it "undergrad-students" do
|
122
|
+
# no calmsgs group
|
123
|
+
# assert_matching_group("undergrad-students")
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative "../spec_helper"
|
2
|
+
|
3
|
+
|
4
|
+
describe "CampusGroup" do
|
5
|
+
let(:entry) do
|
6
|
+
{
|
7
|
+
:dn => ["cn=edu:berkeley:app:calmessages:faculty,ou=campus groups,dc=berkeley,dc=edu"],
|
8
|
+
:description => ["Instructors"]
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
it "Finds Campus Groups" do
|
13
|
+
groups = UcbGroups::CampusGroup.find(:calmessages)
|
14
|
+
groups.should_not be_empty
|
15
|
+
end
|
16
|
+
|
17
|
+
it "initializes an entry" do
|
18
|
+
group = UcbGroups::CampusGroup.new(entry)
|
19
|
+
|
20
|
+
group.dn.should eql(entry[:dn].first)
|
21
|
+
group.description.should eql(entry[:description].first)
|
22
|
+
group.namespace.should eql("calmessages")
|
23
|
+
group.name.should eql("faculty")
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative "../spec_helper"
|
2
|
+
|
3
|
+
|
4
|
+
describe "MembershipFilter" do
|
5
|
+
let(:finder) { UcbGroups::MembershipFilter.new(namespace, groups, orgs) }
|
6
|
+
|
7
|
+
it "creates groups filter" do
|
8
|
+
filter = UcbGroups::MembershipFilter.new(:calmessages, [:deans], []).to_s
|
9
|
+
filter_str = "(&(objectclass=person)" +
|
10
|
+
"(ismemberof=cn=edu:berkeley:app:calmessages:deans,ou=campus groups,dc=berkeley,dc=edu))"
|
11
|
+
filter.should eql(filter_str)
|
12
|
+
|
13
|
+
filter = UcbGroups::MembershipFilter.new(:calmessages, [:deans, :instructors], []).to_s
|
14
|
+
filter_str = "(&(objectclass=person)" +
|
15
|
+
"(|(ismemberof=cn=edu:berkeley:app:calmessages:deans,ou=campus groups,dc=berkeley,dc=edu)" +
|
16
|
+
"(ismemberof=cn=edu:berkeley:app:calmessages:instructors,ou=campus groups,dc=berkeley,dc=edu)))"
|
17
|
+
filter.should eql(filter_str)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "creates orgs filter" do
|
21
|
+
filter = UcbGroups::MembershipFilter.new(:calmessages, [], ["JKASD"]).to_s
|
22
|
+
filter_str = "(&(objectclass=person)" +
|
23
|
+
"(berkeleyedudeptunithierarchystring=*JKASD*))"
|
24
|
+
filter.should eql(filter_str)
|
25
|
+
|
26
|
+
filter = UcbGroups::MembershipFilter.new(:calmessages, [], ["JKASD", "JJCNS"]).to_s
|
27
|
+
filter_str = "(&(objectclass=person)" +
|
28
|
+
"(|(berkeleyedudeptunithierarchystring=*JKASD*)" +
|
29
|
+
"(berkeleyedudeptunithierarchystring=*JJCNS*)))"
|
30
|
+
filter.should eql(filter_str)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "creates groups and orgs filter" do
|
34
|
+
filter = UcbGroups::MembershipFilter.new(:calmessages, [:deans], ["JKASD"]).to_s
|
35
|
+
filter_str = "(&(objectclass=person)" +
|
36
|
+
"(&(ismemberof=cn=edu:berkeley:app:calmessages:deans,ou=campus groups,dc=berkeley,dc=edu)" +
|
37
|
+
"(berkeleyedudeptunithierarchystring=*JKASD*)))"
|
38
|
+
filter.should eql(filter_str)
|
39
|
+
|
40
|
+
filter = UcbGroups::MembershipFilter.new(:calmessages, [:deans, :instructors], ["JKASD"]).to_s
|
41
|
+
filter_str = "(&(objectclass=person)" +
|
42
|
+
"(&(|(ismemberof=cn=edu:berkeley:app:calmessages:deans,ou=campus groups,dc=berkeley,dc=edu)" +
|
43
|
+
"(ismemberof=cn=edu:berkeley:app:calmessages:instructors,ou=campus groups,dc=berkeley,dc=edu))" +
|
44
|
+
"(berkeleyedudeptunithierarchystring=*JKASD*)))"
|
45
|
+
filter.should eql(filter_str)
|
46
|
+
|
47
|
+
filter = UcbGroups::MembershipFilter.new(:calmessages, [:deans, :instructors], ["JKASD", "JJCNS"]).to_s
|
48
|
+
filter_str = "(&(objectclass=person)" +
|
49
|
+
"(&(|(ismemberof=cn=edu:berkeley:app:calmessages:deans,ou=campus groups,dc=berkeley,dc=edu)" +
|
50
|
+
"(ismemberof=cn=edu:berkeley:app:calmessages:instructors,ou=campus groups,dc=berkeley,dc=edu))" +
|
51
|
+
"(|(berkeleyedudeptunithierarchystring=*JKASD*)(berkeleyedudeptunithierarchystring=*JJCNS*))))"
|
52
|
+
filter.should eql(filter_str)
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative "../spec_helper"
|
2
|
+
|
3
|
+
|
4
|
+
describe "MembershipFinder" do
|
5
|
+
let(:finder) { UcbGroups::MembershipFinder.new(:calmessages) }
|
6
|
+
|
7
|
+
context "find options" do
|
8
|
+
it "recognizes if groups are invalid" do
|
9
|
+
err = UcbGroups::InvalidCampusGroupError
|
10
|
+
expect { finder.find(:groups => [:invalid_group]) }.to raise_error(err)
|
11
|
+
expect { finder.find(:groups => [:deans, :invalid_group]) }.to raise_error(err)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "returns no results if :group and :orgs are both empty" do
|
15
|
+
finder.find(:groups => [], :orgs => []).should be_empty
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "Finding by group" do
|
20
|
+
it "finds users in a single group" do
|
21
|
+
finder.find(:groups => [:deans]).should_not be_empty
|
22
|
+
end
|
23
|
+
|
24
|
+
it "finds users in a multiple groups" do
|
25
|
+
finder.find(:groups => [:deans, :instructors]).should_not be_empty
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "Finding by org" do
|
30
|
+
it "finds users beneath a single org" do
|
31
|
+
finder.find(:orgs => [:JKASD]).should_not be_empty
|
32
|
+
end
|
33
|
+
|
34
|
+
it "finds users beneath any of the provided orgs" do
|
35
|
+
jkasd_people = finder.find(:orgs => [:JKASD])
|
36
|
+
jkasd_jjcns_people = finder.find(:orgs => [:JKASD, :JJCNS])
|
37
|
+
|
38
|
+
(jkasd_people.length < jkasd_jjcns_people.length).should be_true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "Finding by group and org" do
|
43
|
+
it "finds users in a single group and org" do
|
44
|
+
campus_it_staff = finder.find(:groups => ["it-staff"])
|
45
|
+
ist_it_staff = finder.find(:groups => ["it-staff"], :orgs => [:VRIST])
|
46
|
+
|
47
|
+
campus_it_staff.should_not be_empty
|
48
|
+
ist_it_staff.should_not be_empty
|
49
|
+
(ist_it_staff.length < campus_it_staff.length).should be_true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/ucb_groups.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ucb_groups/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ucb_groups"
|
8
|
+
spec.version = UcbGroups::VERSION
|
9
|
+
spec.authors = ["sahglie"]
|
10
|
+
spec.email = ["sahglie@gmail.com"]
|
11
|
+
spec.description = %q{Finds users that belong to a given ucb group}
|
12
|
+
spec.summary = %q{Finds users that belong to a given ucb group}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec", "~> 2.7"
|
24
|
+
spec.add_development_dependency "rest-client"
|
25
|
+
spec.add_development_dependency "json"
|
26
|
+
|
27
|
+
spec.add_runtime_dependency "ucb_ldap", "2.0.0.pre5"
|
28
|
+
spec.add_runtime_dependency "net-ldap", "0.2.2"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ucb_groups
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- sahglie
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-09-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.7'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rest-client
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: json
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: ucb_ldap
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 2.0.0.pre5
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 2.0.0.pre5
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: net-ldap
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.2.2
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.2.2
|
111
|
+
description: Finds users that belong to a given ucb group
|
112
|
+
email:
|
113
|
+
- sahglie@gmail.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- .gitignore
|
119
|
+
- Gemfile
|
120
|
+
- LICENSE.txt
|
121
|
+
- README.md
|
122
|
+
- Rakefile
|
123
|
+
- lib/ucb_groups.rb
|
124
|
+
- lib/ucb_groups/campus_group.rb
|
125
|
+
- lib/ucb_groups/ldap_conn.rb
|
126
|
+
- lib/ucb_groups/membership_filter.rb
|
127
|
+
- lib/ucb_groups/membership_finder.rb
|
128
|
+
- lib/ucb_groups/monkey_patches/net_ldap_filter.rb
|
129
|
+
- lib/ucb_groups/person.rb
|
130
|
+
- lib/ucb_groups/version.rb
|
131
|
+
- spec/integration/calmsgs_groups_spec.rb
|
132
|
+
- spec/spec_helper.rb
|
133
|
+
- spec/ucb_groups/campus_group_spec.rb
|
134
|
+
- spec/ucb_groups/membership_filter_spec.rb
|
135
|
+
- spec/ucb_groups/membership_finder_spec.rb
|
136
|
+
- spec/ucb_groups_spec.rb
|
137
|
+
- ucb_groups.gemspec
|
138
|
+
homepage: ''
|
139
|
+
licenses:
|
140
|
+
- MIT
|
141
|
+
metadata: {}
|
142
|
+
post_install_message:
|
143
|
+
rdoc_options: []
|
144
|
+
require_paths:
|
145
|
+
- lib
|
146
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - '>='
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - '>='
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
requirements: []
|
157
|
+
rubyforge_project:
|
158
|
+
rubygems_version: 2.0.3
|
159
|
+
signing_key:
|
160
|
+
specification_version: 4
|
161
|
+
summary: Finds users that belong to a given ucb group
|
162
|
+
test_files:
|
163
|
+
- spec/integration/calmsgs_groups_spec.rb
|
164
|
+
- spec/spec_helper.rb
|
165
|
+
- spec/ucb_groups/campus_group_spec.rb
|
166
|
+
- spec/ucb_groups/membership_filter_spec.rb
|
167
|
+
- spec/ucb_groups/membership_finder_spec.rb
|
168
|
+
- spec/ucb_groups_spec.rb
|
169
|
+
has_rdoc:
|