ucb_ldap 1.3.0
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.
- data/CHANGELOG +127 -0
- data/Manifest +25 -0
- data/README +80 -0
- data/Rakefile +22 -0
- data/TODO +2 -0
- data/init.rb +1 -0
- data/lib/person/adv_con_person.rb +0 -0
- data/lib/person/affiliation_methods.rb +212 -0
- data/lib/person/generic_attributes.rb +68 -0
- data/lib/ucb_ldap.rb +177 -0
- data/lib/ucb_ldap_address.rb +106 -0
- data/lib/ucb_ldap_affiliation.rb +84 -0
- data/lib/ucb_ldap_entry.rb +398 -0
- data/lib/ucb_ldap_exceptions.rb +27 -0
- data/lib/ucb_ldap_namespace.rb +42 -0
- data/lib/ucb_ldap_org.rb +369 -0
- data/lib/ucb_ldap_person.rb +135 -0
- data/lib/ucb_ldap_person_job_appointment.rb +79 -0
- data/lib/ucb_ldap_schema.rb +115 -0
- data/lib/ucb_ldap_schema_attribute.rb +153 -0
- data/lib/ucb_ldap_service.rb +109 -0
- data/lib/ucb_ldap_student_term.rb +101 -0
- data/lib/ucb_simple_ldap_entry.rb +201 -0
- data/schema/schema.yml +2954 -0
- data/ucb_ldap.gemspec +40 -0
- data/version.yml +1 -0
- metadata +124 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
|
2
|
+
module UCB
|
3
|
+
module LDAP
|
4
|
+
# = UCB::LDAP::JobAppointment
|
5
|
+
#
|
6
|
+
# This class models a person's job appointment instance in the UCB LDAP directory.
|
7
|
+
#
|
8
|
+
# appts = JobAppontment.find_by_uid("1234") #=> [#<UCB::LDAP::JobAppointment: ...>, ...]
|
9
|
+
#
|
10
|
+
# JobAppointments are usually loaded through a Person instance:
|
11
|
+
#
|
12
|
+
# p = Person.find_by_uid("1234") #=> #<UCB::LDAP::Person: ...>
|
13
|
+
# appts = p.job_appointments #=> [#<UCB::LDAP::JobAppointment: ...>, ...]
|
14
|
+
#
|
15
|
+
# == Note on Binds
|
16
|
+
#
|
17
|
+
# You must have a privileged bind and pass your credentials to UCB::LDAP.authenticate()
|
18
|
+
# before performing your JobAppointment search.
|
19
|
+
#
|
20
|
+
class JobAppointment < Entry
|
21
|
+
@entity_name = 'personJobAppointment'
|
22
|
+
|
23
|
+
def cto_code
|
24
|
+
berkeleyEduPersonJobApptCTOCode
|
25
|
+
end
|
26
|
+
|
27
|
+
def deptid
|
28
|
+
berkeleyEduPersonJobApptDepartment
|
29
|
+
end
|
30
|
+
|
31
|
+
def record_number
|
32
|
+
berkeleyEduPersonJobApptEmpRecNumber.to_i
|
33
|
+
end
|
34
|
+
|
35
|
+
def personnel_program_code
|
36
|
+
berkeleyEduPersonJobApptPersPgmCode
|
37
|
+
end
|
38
|
+
|
39
|
+
def primary?
|
40
|
+
berkeleyEduPersonJobApptPrimaryFlag
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns Employee Relation Code
|
44
|
+
def erc_code
|
45
|
+
berkeleyEduPersonJobApptRelationsCode
|
46
|
+
end
|
47
|
+
|
48
|
+
def represented?
|
49
|
+
berkeleyEduPersonJobApptRepresentation != 'U'
|
50
|
+
end
|
51
|
+
|
52
|
+
def title_code
|
53
|
+
berkeleyEduPersonJobApptTitleCode
|
54
|
+
end
|
55
|
+
|
56
|
+
def appointment_type
|
57
|
+
berkeleyEduPersonJobApptType
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns +true+ if appointment is Without Salary
|
61
|
+
def wos?
|
62
|
+
berkeleyEduPersonJobApptWOS
|
63
|
+
end
|
64
|
+
|
65
|
+
class << self
|
66
|
+
# Returns an Array of JobAppointment for <tt>uid</tt>, sorted by
|
67
|
+
# record_number().
|
68
|
+
# Returns an empty Array ([]) if nothing is found.
|
69
|
+
#
|
70
|
+
def find_by_uid(uid)
|
71
|
+
base = "uid=#{uid},ou=people,dc=berkeley,dc=edu"
|
72
|
+
filter = Net::LDAP::Filter.eq("objectclass", 'berkeleyEduPersonJobAppt')
|
73
|
+
search(:base => base, :filter => filter).sort_by{|appt| appt.record_number}
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
#require 'open-uri'
|
2
|
+
#require 'net/http'
|
3
|
+
require 'yaml'
|
4
|
+
require 'net/https'
|
5
|
+
|
6
|
+
module UCB #:nodoc:
|
7
|
+
module LDAP
|
8
|
+
# = UCB::LDAP::Schema
|
9
|
+
#
|
10
|
+
# Class responsible for getting schema information for all of the UCB::LDAP
|
11
|
+
# entities. Attributes are modeled as instances of UCB::LDAP::Schema::Attribute.
|
12
|
+
#
|
13
|
+
# Each entity (Person, Org, etc.) has a Hash of attributes where the keys are
|
14
|
+
# canonical (see Entry.canonical) attribute/alias names
|
15
|
+
# and the values are Schema::Attribute's.
|
16
|
+
#
|
17
|
+
# You don't have to explicitly load schema information; the UCB::LDAP module
|
18
|
+
# loads schema information as needed. Unless you want to override the schema
|
19
|
+
# url (or file) you probably won't need to work directly with this class.
|
20
|
+
#
|
21
|
+
# == Schema Source
|
22
|
+
#
|
23
|
+
# Schema information is loaded from a url defined by the
|
24
|
+
# SCHEMA_* constants. A version of the file is distributed
|
25
|
+
# with this Gem and is used in case the web version is not accessible.
|
26
|
+
#
|
27
|
+
module Schema
|
28
|
+
|
29
|
+
SCHEMA_BASE_URL = 'calnet.berkeley.edu'
|
30
|
+
SCHEMA_CONTENT_PATH = '/developers/developerResources/yaml/schema/schema.yaml'
|
31
|
+
SCHEMA_FILE = "#{File.dirname(__FILE__)}/../schema/schema.yml"
|
32
|
+
|
33
|
+
class << self
|
34
|
+
|
35
|
+
# Returns a hash of all attributes for all entities. Keys are
|
36
|
+
# entity names, values hash of attributes for given entity.
|
37
|
+
def schema_hash()
|
38
|
+
@schema_hash ||= load_attributes
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns schema base url. Defaults to SCHEMA_BASE_URL constant.
|
42
|
+
def schema_base_url()
|
43
|
+
@schema_base_url || SCHEMA_BASE_URL
|
44
|
+
end
|
45
|
+
|
46
|
+
# Setter for schema_base_url(). Use this to override url of LDAP
|
47
|
+
# schema information.
|
48
|
+
def schema_base_url=(base_url)
|
49
|
+
@schema_base_url = base_url
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns schema content path. Defaults to SCHEMA_CONTENT_PATH constant.
|
53
|
+
def schema_content_path()
|
54
|
+
@schema_content_path || SCHEMA_CONTENT_PATH
|
55
|
+
end
|
56
|
+
|
57
|
+
# Setter for schema_content_path(). Use this to override content path of LDAP
|
58
|
+
# schema information.
|
59
|
+
def schema_content_path=(content_path)
|
60
|
+
@schema_content_path = content_path
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns schema file. Defaults fo SCHEMA_FILE constant.
|
64
|
+
def schema_file()
|
65
|
+
@schema_file || SCHEMA_FILE
|
66
|
+
end
|
67
|
+
|
68
|
+
# Setter for schema_file(). Use this to override location of
|
69
|
+
# local schema file.
|
70
|
+
def schema_file=(file)
|
71
|
+
@schema_file = file
|
72
|
+
end
|
73
|
+
|
74
|
+
#private unless $TESTING
|
75
|
+
|
76
|
+
# Setter for schema_hash()
|
77
|
+
def schema_hash=(h) #:nodoc:
|
78
|
+
@schema_hash = h
|
79
|
+
end
|
80
|
+
|
81
|
+
# Load attributes from URL or file
|
82
|
+
def load_attributes #:nodoc:
|
83
|
+
load_attributes_from_url
|
84
|
+
rescue
|
85
|
+
puts "Warning: schema loading from file"
|
86
|
+
load_attributes_from_file
|
87
|
+
end
|
88
|
+
|
89
|
+
def load_attributes_from_url() #:nodoc:
|
90
|
+
self.schema_hash = YAML.load(yaml_from_url)
|
91
|
+
end
|
92
|
+
|
93
|
+
def yaml_from_url() #:nodoc:
|
94
|
+
http = Net::HTTP.new(SCHEMA_BASE_URL, 443)
|
95
|
+
http.use_ssl = true
|
96
|
+
http.get(SCHEMA_CONTENT_PATH).body
|
97
|
+
end
|
98
|
+
|
99
|
+
def load_attributes_from_file() #:nodoc:
|
100
|
+
self.schema_hash = YAML.load(yaml_from_file)
|
101
|
+
end
|
102
|
+
|
103
|
+
def yaml_from_file #:nodoc:
|
104
|
+
IO.read(schema_file)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Get instance variable w/o loading -- for testing purposes.
|
108
|
+
def schema_hash_i() #:nodoc:
|
109
|
+
@schema_hash
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
|
2
|
+
module UCB
|
3
|
+
module LDAP
|
4
|
+
module Schema
|
5
|
+
# = UCB::LDAP::SchemaAttribute
|
6
|
+
#
|
7
|
+
# This class models <em>schema</em> information about an LDAP attribute.
|
8
|
+
#
|
9
|
+
# This class is used internally by various UCB::LDAP classes.
|
10
|
+
# Users of UCB::LDAP probably won't need to interact with this
|
11
|
+
# class directly.
|
12
|
+
#
|
13
|
+
# The LDAP entity classes have access to their Attribute's.
|
14
|
+
#
|
15
|
+
# uid_attr = UCB::LDAP::Person.attribute(:uid) # :symbol ok as attribute name
|
16
|
+
#
|
17
|
+
# uid_attr.name #=> 'uid'
|
18
|
+
# uid_attr.aliases #=> ['userid']
|
19
|
+
# uid_attr.description #=> 'Standard LDAP attribute type'
|
20
|
+
# uid_attr.multi_valued? #=> true
|
21
|
+
# uid_attr.required? #=> true
|
22
|
+
# uid_attr.type #=> 'string'
|
23
|
+
#
|
24
|
+
# uas_attr = UCB::LDAP::Person.attribute('berkeleyEduUasEligFlag') # case doesn't matter
|
25
|
+
#
|
26
|
+
# uas_attr.name #=> 'berkeleyEduUasEligFlag'
|
27
|
+
# uas_attr.aliases #=> ['ucbvalidflag']
|
28
|
+
# uas_attr.description #=> 'UAS Eligibility Flag'
|
29
|
+
# uas_attr.multi_valued? #=> false
|
30
|
+
# uas_attr.required? #=> false
|
31
|
+
# uas_attr.type #=> 'boolean'
|
32
|
+
#
|
33
|
+
class Attribute
|
34
|
+
|
35
|
+
# Constructor called by UCB::LDAP::Entry.set_schema_attributes().
|
36
|
+
def initialize(args) #:nodoc:
|
37
|
+
@name = args["name"]
|
38
|
+
@type = args["syntax"]
|
39
|
+
@aliases = args["aliases"] || []
|
40
|
+
@description = args["description"]
|
41
|
+
@required = args["required"]
|
42
|
+
@multi_valued = args["multi"]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns attribute name as found in the schema
|
46
|
+
def name
|
47
|
+
@name
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns Array of aliases as found in schema. Returns empty
|
51
|
+
# Array ([]) if no aliases.
|
52
|
+
#
|
53
|
+
def aliases
|
54
|
+
@aliases
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns (data) type. Used by get_value() to cast value to correct Ruby type.
|
58
|
+
#
|
59
|
+
# Supported types and corresponding Ruby type:
|
60
|
+
#
|
61
|
+
# * string String
|
62
|
+
# * integer Fixnum
|
63
|
+
# * boolean TrueClass / FalseClass
|
64
|
+
# * timestamp DateTime (convenience methods may return Date if attribute's semantics don't include time)
|
65
|
+
#
|
66
|
+
def type
|
67
|
+
@type
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns attribute description. Of limited value since all
|
71
|
+
# standard LDAP attributes have a description of
|
72
|
+
# "Standard LDAP attribute type".
|
73
|
+
def description
|
74
|
+
@description
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns <tt>true</tt> if attribute is required, else <tt>false</tt>
|
78
|
+
def required?
|
79
|
+
@required
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns <tt>true</tt> if attribute is multi-valued, else <tt>false</tt>.
|
83
|
+
# Multi-valued attribute values are returned as an Array.
|
84
|
+
def multi_valued?
|
85
|
+
@multi_valued
|
86
|
+
end
|
87
|
+
|
88
|
+
# Takes a value returned from an LDAP attribute (+Array+ of +String+)
|
89
|
+
# and returns value with correct cardinality (array or scalar)
|
90
|
+
# cast to correct #type.
|
91
|
+
def get_value(array)
|
92
|
+
if array.nil?
|
93
|
+
return false if boolean?
|
94
|
+
return [] if multi_valued?
|
95
|
+
return nil
|
96
|
+
end
|
97
|
+
typed_array = apply_type_to_array(array)
|
98
|
+
multi_valued? ? typed_array : typed_array.first
|
99
|
+
end
|
100
|
+
|
101
|
+
# Cast each element to correct type.
|
102
|
+
def apply_type_to_array(array) #:nodoc:
|
103
|
+
array.map{|scalar| apply_type_to_scalar scalar}
|
104
|
+
end
|
105
|
+
|
106
|
+
# Case element to correct type
|
107
|
+
def apply_type_to_scalar(string) #:nodoc:
|
108
|
+
return string if string?
|
109
|
+
return string.to_i if integer?
|
110
|
+
return %w{true 1}.include?(string) ? true : false if boolean?
|
111
|
+
return UCB::LDAP.local_datetime_parse(string) if timestamp?
|
112
|
+
raise "unknown type '#{type}' for attribute '#{name}'"
|
113
|
+
end
|
114
|
+
|
115
|
+
# Return <tt>true</tt> if attribute type is string.
|
116
|
+
def string?
|
117
|
+
type == "string"
|
118
|
+
end
|
119
|
+
|
120
|
+
# Return <tt>true</tt> if attribute type is integer.
|
121
|
+
def integer?
|
122
|
+
type == "integer"
|
123
|
+
end
|
124
|
+
|
125
|
+
# Return <tt>true</tt> if attribute type is boolean.
|
126
|
+
def boolean?
|
127
|
+
type == "boolean"
|
128
|
+
end
|
129
|
+
|
130
|
+
# Return <tt>true</tt> if attribute type is timestamp
|
131
|
+
def timestamp?
|
132
|
+
type == "timestamp"
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns a value in LDAP attribute value format (+Array+ of +String+).
|
136
|
+
def ldap_value(value)
|
137
|
+
return nil if value.nil?
|
138
|
+
return value.map{|v| ldap_value_stripped(v)} if value.instance_of?(Array)
|
139
|
+
return [ldap_value_stripped(value)]
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
# Remove leading/trailing white-space and imbedded newlines.
|
145
|
+
def ldap_value_stripped(s)
|
146
|
+
s.to_s.strip.gsub(/\n/,"")
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
|
2
|
+
module UCB
|
3
|
+
module LDAP
|
4
|
+
# = UCB::LDAP::Service
|
5
|
+
#
|
6
|
+
# This class models a person's service entries in the UCB LDAP directory.
|
7
|
+
#
|
8
|
+
# services = Services.find_by_uid("1234") #=> [#<UCB::LDAP::Service: ...>, ...]
|
9
|
+
#
|
10
|
+
# Servicess are usually loaded through a Person instance:
|
11
|
+
#
|
12
|
+
# p = Person.find_by_uid("1234") #=> #<UCB::LDAP::Person: ...>
|
13
|
+
# services = p.services #=> [#<UCB::LDAP::Service: ...>, ...]
|
14
|
+
#
|
15
|
+
# == Note on Binds
|
16
|
+
#
|
17
|
+
# You must have a privileged bind and pass your credentials to UCB::LDAP.authenticate()
|
18
|
+
# before performing your Service search.
|
19
|
+
#
|
20
|
+
class Service < Entry
|
21
|
+
@entity_name = 'personService'
|
22
|
+
|
23
|
+
def eligible_by
|
24
|
+
berkeleyEduPersonServiceEligibleBy
|
25
|
+
end
|
26
|
+
|
27
|
+
def eligible_date
|
28
|
+
berkeleyEduPersonServiceEligibleDate
|
29
|
+
end
|
30
|
+
|
31
|
+
def ended_by
|
32
|
+
berkeleyEduPersonServiceEndBy
|
33
|
+
end
|
34
|
+
|
35
|
+
def end_date
|
36
|
+
berkeleyEduPersonServiceEndDate
|
37
|
+
end
|
38
|
+
|
39
|
+
def entered_by
|
40
|
+
berkeleyEduPersonServiceEnteredBy
|
41
|
+
end
|
42
|
+
|
43
|
+
def entered_date
|
44
|
+
berkeleyEduPersonServiceEnteredDate
|
45
|
+
end
|
46
|
+
|
47
|
+
def level
|
48
|
+
berkeleyEduPersonServiceLevel
|
49
|
+
end
|
50
|
+
|
51
|
+
def modified_by
|
52
|
+
berkeleyEduPersonServiceModifiedBy
|
53
|
+
end
|
54
|
+
|
55
|
+
def modified_date
|
56
|
+
berkeleyEduPersonServiceModifiedDate
|
57
|
+
end
|
58
|
+
|
59
|
+
def naughty_bit
|
60
|
+
berkeleyEduPersonServiceNaughtyBit
|
61
|
+
end
|
62
|
+
|
63
|
+
def notified_by
|
64
|
+
berkeleyEduPersonServiceNotifyBy
|
65
|
+
end
|
66
|
+
|
67
|
+
def notify_date
|
68
|
+
berkeleyEduPersonServiceNotifyDate
|
69
|
+
end
|
70
|
+
|
71
|
+
def stopped_by
|
72
|
+
berkeleyEduPersonServiceStopBy
|
73
|
+
end
|
74
|
+
|
75
|
+
def stop_date
|
76
|
+
berkeleyEduPersonServiceStopDate
|
77
|
+
end
|
78
|
+
|
79
|
+
def value
|
80
|
+
berkeleyEduPersonServiceValue
|
81
|
+
end
|
82
|
+
|
83
|
+
def service
|
84
|
+
berkeleyEduService
|
85
|
+
end
|
86
|
+
|
87
|
+
def common_name
|
88
|
+
cn
|
89
|
+
end
|
90
|
+
|
91
|
+
def description
|
92
|
+
super.first
|
93
|
+
end
|
94
|
+
|
95
|
+
class << self
|
96
|
+
# Returns an Array of JobAppointment for <tt>uid</tt>, sorted by
|
97
|
+
# record_number().
|
98
|
+
# Returns an empty Array ([]) if nothing is found.
|
99
|
+
#
|
100
|
+
def find_by_uid(uid)
|
101
|
+
base = "uid=#{uid},ou=people,dc=berkeley,dc=edu"
|
102
|
+
filter = Net::LDAP::Filter.eq("objectclass", 'berkeleyEduPersonService')
|
103
|
+
search(:base => base, :filter => filter)
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|