simple_crowd 1.1.3 → 1.2.0.beta2
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/lib/simple_crowd.rb +0 -2
- data/lib/simple_crowd/client.rb +59 -26
- data/lib/simple_crowd/crowd_entity.rb +143 -144
- data/lib/simple_crowd/crowd_error.rb +7 -3
- data/lib/simple_crowd/group.rb +4 -3
- data/lib/simple_crowd/mock_client.rb +14 -3
- data/lib/simple_crowd/user.rb +14 -8
- data/lib/simple_crowd/version.rb +1 -1
- data/simple_crowd.gemspec +0 -1
- data/test/crowd_config.yml.example +5 -0
- data/test/factories.rb +3 -3
- data/test/test_client.rb +37 -34
- data/test/test_user.rb +30 -21
- metadata +5 -22
- data/lib/simple_crowd/mappers/soap_attributes.rb +0 -13
data/lib/simple_crowd.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'savon'
|
2
|
-
require 'hashie'
|
3
2
|
require 'yaml'
|
4
3
|
require 'forwardable'
|
5
4
|
require 'simple_crowd/crowd_entity'
|
@@ -7,7 +6,6 @@ require 'simple_crowd/crowd_error'
|
|
7
6
|
require 'simple_crowd/user'
|
8
7
|
require 'simple_crowd/group'
|
9
8
|
require 'simple_crowd/client'
|
10
|
-
require 'simple_crowd/mappers/soap_attributes'
|
11
9
|
require 'simple_crowd/cache/null_store'
|
12
10
|
Dir['simple_crowd/mappers/*.rb'].each {|file| require File.basename(file, File.extname(file)) }
|
13
11
|
|
data/lib/simple_crowd/client.rb
CHANGED
@@ -82,7 +82,7 @@ module SimpleCrowd
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def find_group_by_name name
|
85
|
-
SimpleCrowd::Group.
|
85
|
+
SimpleCrowd::Group.from_soap simple_soap_call(:find_group_by_name, name)
|
86
86
|
end
|
87
87
|
|
88
88
|
def find_all_group_names
|
@@ -114,15 +114,15 @@ module SimpleCrowd
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def find_user_by_name name
|
117
|
-
SimpleCrowd::User.
|
117
|
+
SimpleCrowd::User.from_soap simple_soap_call(:find_principal_by_name, name) rescue nil
|
118
118
|
end
|
119
119
|
|
120
120
|
def find_user_with_attributes_by_name name
|
121
|
-
SimpleCrowd::User.
|
121
|
+
SimpleCrowd::User.from_soap simple_soap_call(:find_principal_with_attributes_by_name, name) rescue nil
|
122
122
|
end
|
123
123
|
|
124
124
|
def find_user_by_token token
|
125
|
-
SimpleCrowd::User.
|
125
|
+
SimpleCrowd::User.from_soap simple_soap_call(:find_principal_by_token, token) rescue nil
|
126
126
|
end
|
127
127
|
|
128
128
|
def find_username_by_token token
|
@@ -137,15 +137,31 @@ module SimpleCrowd
|
|
137
137
|
|
138
138
|
# Partial email match
|
139
139
|
def search_users_by_email email
|
140
|
-
search_users({'
|
141
|
-
end
|
142
|
-
|
143
|
-
|
144
|
-
|
140
|
+
search_users({'email' => email})
|
141
|
+
end
|
142
|
+
|
143
|
+
# Search Crowd users using the given criteria.
|
144
|
+
#
|
145
|
+
# critieria should be a hash of SimpleCrowd::User properties or attributes.
|
146
|
+
# Not all properties are supported, see (https://developer.atlassian.com/display/CROWDDEV/Using+the+Search+API)
|
147
|
+
#
|
148
|
+
# NOTE: Atlassian Crowd contains a bug that ignores the limit and start
|
149
|
+
# parameters
|
150
|
+
#
|
151
|
+
# For example:
|
152
|
+
# client.search_users(:email => 'foo', :display_name => 'bar')
|
153
|
+
def search_users criteria, limit=0, start=0
|
154
|
+
# Convert search criteria to Crowd search restrictions
|
155
|
+
restrictions = criteria.inject({}) do |h, (key, val)|
|
156
|
+
key = User.search_restriction_for(key).to_s
|
157
|
+
h[key] = val
|
158
|
+
h
|
159
|
+
end
|
160
|
+
soap_restrictions = add_soap_namespace(prepare_search_restrictions(restrictions, limit, start))
|
145
161
|
users = simple_soap_call :search_principals, soap_restrictions rescue []
|
146
162
|
return [] if users.nil? || users[:soap_principal].nil?
|
147
163
|
users = users[:soap_principal].is_a?(Array) ? users[:soap_principal] : [users[:soap_principal]]
|
148
|
-
users.map{|u| SimpleCrowd::User.
|
164
|
+
users.map{|u| SimpleCrowd::User.from_soap u}
|
149
165
|
end
|
150
166
|
|
151
167
|
def add_user user, credential
|
@@ -153,15 +169,16 @@ module SimpleCrowd
|
|
153
169
|
[:email, :first_name, :last_name].each do |k|
|
154
170
|
user.send(:"#{k}=", "") if user.send(k).nil?
|
155
171
|
end
|
156
|
-
soap_user = user.
|
172
|
+
soap_user = user.to_soap
|
157
173
|
# We don't use these attributes when creating
|
158
174
|
soap_user.delete(:id)
|
159
175
|
soap_user.delete(:directory_id)
|
160
176
|
# Add blank attributes if missing
|
161
177
|
|
162
178
|
# Declare require namespaces
|
163
|
-
soap_user = soap_user
|
164
|
-
|
179
|
+
soap_user = add_soap_namespace(soap_user)
|
180
|
+
|
181
|
+
SimpleCrowd::User.from_soap simple_soap_call(:add_principal, soap_user, {'auth:credential' => credential, 'auth:encryptedCredential' => false})
|
165
182
|
end
|
166
183
|
|
167
184
|
def remove_user name
|
@@ -182,8 +199,8 @@ module SimpleCrowd
|
|
182
199
|
# @param value [String] of attribute to update
|
183
200
|
def update_user_attribute user, name, value
|
184
201
|
return unless (name.is_a?(String) || name.is_a?(Symbol)) && (value.is_a?(String) || value.is_a?(Array))
|
185
|
-
soap_attr =
|
186
|
-
simple_soap_call :update_principal_attribute, user, soap_attr
|
202
|
+
soap_attr = add_soap_namespace({:name => name, :values => {:string => value}})
|
203
|
+
simple_soap_call :update_principal_attribute, user, soap_attr
|
187
204
|
true
|
188
205
|
end
|
189
206
|
alias_method :add_user_attribute, :update_user_attribute
|
@@ -196,10 +213,11 @@ module SimpleCrowd
|
|
196
213
|
return if attrs_to_update.empty?
|
197
214
|
|
198
215
|
attrs_to_update.each do |a|
|
199
|
-
|
200
|
-
|
201
|
-
self.update_user_attribute user.username, soap_prop, user.send(a)
|
216
|
+
key = SimpleCrowd::User.soap_key_for(a)
|
217
|
+
self.update_user_attribute user.username, key, user.send(a)
|
202
218
|
end
|
219
|
+
user.clean
|
220
|
+
user
|
203
221
|
end
|
204
222
|
|
205
223
|
def app_token
|
@@ -266,10 +284,8 @@ module SimpleCrowd
|
|
266
284
|
old_raise_errors = client.config.raise_errors
|
267
285
|
client.config.raise_errors = true
|
268
286
|
yield
|
269
|
-
rescue Savon::SOAP::Fault =>
|
270
|
-
raise CrowdError.new(
|
271
|
-
rescue Savon::HTTP::Error => e
|
272
|
-
raise CrowdError.new(e.to_s)
|
287
|
+
rescue Savon::SOAP::Fault, Savon::HTTP::Error => e
|
288
|
+
raise CrowdError.new(e)
|
273
289
|
ensure
|
274
290
|
client.config.raise_errors = old_raise_errors
|
275
291
|
end
|
@@ -324,10 +340,13 @@ module SimpleCrowd
|
|
324
340
|
}
|
325
341
|
end
|
326
342
|
|
327
|
-
def prepare_search_restrictions restrictions
|
328
|
-
|
329
|
-
|
330
|
-
|
343
|
+
def prepare_search_restrictions restrictions, limit=0, start=0
|
344
|
+
restrictions = restrictions.inject([]) do |arr, (key, val)|
|
345
|
+
arr << {'name' => key, 'value' => val}
|
346
|
+
end
|
347
|
+
restrictions << {'name' => 'search.max.results', 'value' => limit.to_i} if limit.to_i > 0
|
348
|
+
restrictions << {'name' => 'search.index.start', 'value' => start.to_i} if start.to_i > 0
|
349
|
+
{'searchRestriction' => restrictions}
|
331
350
|
end
|
332
351
|
|
333
352
|
def hash_authenticated_token name = @options[:app_name], token = nil
|
@@ -342,5 +361,19 @@ module SimpleCrowd
|
|
342
361
|
def cache_key(key)
|
343
362
|
"#{@options[:cache_prefix]}#{key}"
|
344
363
|
end
|
364
|
+
|
365
|
+
def add_soap_namespace(enum)
|
366
|
+
if enum.is_a?(Hash)
|
367
|
+
enum.inject({}) do |h, (k, v)|
|
368
|
+
k = k == :string ? "wsdl:#{k}" : "int:#{k}"
|
369
|
+
h[k] = v.is_a?(Enumerable) ? add_soap_namespace(v) : v
|
370
|
+
h
|
371
|
+
end
|
372
|
+
else
|
373
|
+
enum.map do |v|
|
374
|
+
v.is_a?(Enumerable) ? add_soap_namespace(v) : v
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
345
378
|
end
|
346
379
|
end
|
@@ -1,199 +1,198 @@
|
|
1
1
|
module SimpleCrowd
|
2
|
-
class
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
property :maps, :default => {}
|
8
|
-
property :mappers, :default => {}
|
9
|
-
def immutable?; @immutable; end
|
10
|
-
def is_attribute?; @attribute end
|
11
|
-
end
|
12
|
-
class CrowdEntity < Hashie::Mash
|
13
|
-
def initialize(data = {}, notused = nil)
|
14
|
-
self.class.properties.each do |prop|
|
15
|
-
self.send("#{prop.name}=", self.class.defaults[prop.name.to_sym])
|
2
|
+
class CrowdEntity
|
3
|
+
|
4
|
+
def initialize(attrs={})
|
5
|
+
self.class.defaults.each do |key, val|
|
6
|
+
send(:"#{key.to_s}=", val)
|
16
7
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
data.each_pair do |att, value|
|
21
|
-
#ruby_att = att_to_ruby att
|
22
|
-
ruby_att = att
|
23
|
-
real_att = real_key_for ruby_att
|
24
|
-
(@attributes ||= []) << real_att if attrs.include?(att)
|
25
|
-
prop = self.class.property_by_name(real_att)
|
26
|
-
self.send("#{real_att}=", value) unless prop.nil?
|
27
|
-
self[real_att] = value if prop.nil?
|
8
|
+
|
9
|
+
attrs.each do |key, val|
|
10
|
+
send(:"#{key.to_s}=", val) if self.respond_to?("#{key.to_s}=", true)
|
28
11
|
end
|
29
|
-
# We just initialized the attributes so clear the dirty status
|
30
12
|
dirty_properties.clear
|
31
13
|
end
|
32
|
-
|
14
|
+
|
15
|
+
def self.property(property_name, opts={})
|
33
16
|
property_name = property_name.to_sym
|
34
17
|
|
35
|
-
|
36
|
-
|
37
|
-
options.reject! {|key, val| key.to_s =~ /^map_(.*)$/ || key.to_s =~ /^mapper_(.*)$/ }
|
38
|
-
(@properties ||= []) << ExtendedProperty.new({:name => property_name, :maps => maps, :mappers => mappers}.merge(options))
|
39
|
-
(@attributes ||= []) << property_name if options[:attribute]
|
18
|
+
@properties ||= []
|
19
|
+
@properties << property_name unless @properties.include?(property_name)
|
40
20
|
|
41
|
-
class_eval <<-
|
21
|
+
class_eval <<-PROPERTY, __FILE__, __LINE__ + 1
|
42
22
|
def #{property_name}
|
43
|
-
|
23
|
+
@#{property_name}
|
44
24
|
end
|
45
25
|
def #{property_name}=(val)
|
46
|
-
(dirty_properties << :#{property_name}).uniq! unless val ==
|
47
|
-
|
26
|
+
(dirty_properties << :#{property_name}).uniq! unless val == @#{property_name}
|
27
|
+
@#{property_name} = val
|
48
28
|
end
|
49
|
-
|
29
|
+
PROPERTY
|
50
30
|
|
51
|
-
|
52
|
-
|
53
|
-
alias_method :"#{v}=", :"#{property_name}="
|
31
|
+
if opts[:immutable]
|
32
|
+
private :"#{property_name}="
|
54
33
|
end
|
55
|
-
end
|
56
34
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
35
|
+
if opts[:map_soap]
|
36
|
+
v = :"#{opts[:map_soap]}"
|
37
|
+
@soap_to_property_map ||= {}
|
38
|
+
@property_to_soap_map ||= {}
|
39
|
+
@soap_to_property_map[v] = property_name
|
40
|
+
@property_to_soap_map[property_name] = v
|
63
41
|
end
|
64
42
|
|
65
|
-
|
43
|
+
if opts[:search_restriction]
|
44
|
+
@property_to_search_restriction_map ||= {}
|
45
|
+
@property_to_search_restriction_map[property_name] = opts[:search_restriction]
|
46
|
+
end
|
47
|
+
|
48
|
+
if opts[:default]
|
49
|
+
@defaults ||= {}
|
50
|
+
@defaults[property_name] = opts[:default]
|
51
|
+
end
|
66
52
|
end
|
67
53
|
|
68
|
-
def self.
|
69
|
-
|
70
|
-
|
54
|
+
def self.attribute(attr_name, opts={})
|
55
|
+
attr_name = attr_name.to_sym
|
56
|
+
@attributes ||= []
|
57
|
+
@attributes << attr_name
|
58
|
+
self.property(attr_name, opts)
|
71
59
|
end
|
72
60
|
|
73
|
-
def self.
|
74
|
-
|
75
|
-
properties.select {|p| p.name == property_name || p.maps.value?(property_name)}
|
61
|
+
def self.properties
|
62
|
+
@properties.freeze
|
76
63
|
end
|
77
64
|
|
78
|
-
def self.
|
79
|
-
|
65
|
+
def self.attributes
|
66
|
+
@attributes.freeze
|
80
67
|
end
|
81
68
|
|
82
69
|
def self.defaults
|
83
|
-
|
70
|
+
@defaults.freeze
|
84
71
|
end
|
85
72
|
|
86
|
-
def
|
87
|
-
@
|
88
|
-
unless hash.nil?
|
89
|
-
@attribute_mappers.merge! hash if hash.is_a? Hash
|
90
|
-
end
|
91
|
-
@attribute_mappers
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.map_for type
|
95
|
-
type = type.to_sym
|
96
|
-
properties.inject({}) {|hash, prop| hash[prop.name] = prop.maps[type] unless prop.maps[type].nil?; hash }
|
97
|
-
end
|
98
|
-
|
99
|
-
def self.map_to type, entity
|
100
|
-
map = map_for type
|
101
|
-
attrs = {}
|
102
|
-
out = entity.inject({}) do |hash, (key, val)|
|
103
|
-
key = key.to_sym
|
104
|
-
catch(:skip_prop) do
|
105
|
-
unless val.nil?
|
106
|
-
mapped_key = map[key].nil? ? key : map[key]
|
107
|
-
prop = property_by_name key
|
108
|
-
if prop.nil?
|
109
|
-
attrs[mapped_key] = val
|
110
|
-
throw :skip_prop
|
111
|
-
end
|
112
|
-
mapper = prop.mappers[type]
|
113
|
-
#val = val.inject({}) {|attrs, (k, v)| attrs[property_by_name(k).maps[type]]= v unless v.nil?; attrs} if key == :attributes
|
114
|
-
val = mapper.produce val unless mapper.nil?
|
115
|
-
if prop.attribute || entity.attributes_keys.include?(key)
|
116
|
-
attrs[mapped_key] = val
|
117
|
-
else
|
118
|
-
hash[mapped_key] = val
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
hash
|
123
|
-
end
|
124
|
-
out[:attributes] = attribute_mappers[type].produce attrs
|
125
|
-
out
|
73
|
+
def dirty_properties
|
74
|
+
@dirty_properties ||= Array.new
|
126
75
|
end
|
127
76
|
|
128
|
-
def
|
129
|
-
|
130
|
-
parsed_entity = entity.inject({}) do |hash, (key, val)|
|
131
|
-
prop = property_by_name key
|
132
|
-
unless prop.nil?
|
133
|
-
mapper = prop.mappers[type]
|
134
|
-
val = mapper.parse val unless mapper.nil?
|
135
|
-
end
|
136
|
-
hash[key] = val
|
137
|
-
hash
|
138
|
-
end
|
139
|
-
self.new(parsed_entity)
|
77
|
+
def dirty_attributes
|
78
|
+
dirty_properties & self.class.attributes
|
140
79
|
end
|
141
80
|
|
142
|
-
def
|
143
|
-
|
81
|
+
def dirty?(prop=nil)
|
82
|
+
prop.nil? ? !@dirty_properties.empty? : @dirty_properties.include?(prop)
|
144
83
|
end
|
145
84
|
|
146
|
-
def
|
147
|
-
|
148
|
-
|
149
|
-
if
|
150
|
-
keys << elder.instance_variable_get("@attributes")
|
151
|
-
end
|
85
|
+
def update(properties_and_attributes)
|
86
|
+
return unless properties_and_attributes
|
87
|
+
properties_and_attributes.each do |key, val|
|
88
|
+
send(:"#{key.to_s}=", val) if self.respond_to?("#{key.to_s}=")
|
152
89
|
end
|
153
|
-
keys << @attributes unless @attributes.nil?
|
154
|
-
keys.flatten.uniq
|
155
90
|
end
|
156
91
|
|
157
|
-
def
|
158
|
-
|
92
|
+
def clean
|
93
|
+
@dirty_properties.clear
|
94
|
+
end
|
95
|
+
|
96
|
+
def [](key)
|
97
|
+
respond_to?(:"#{key}") ? send(:"#{key}") : nil
|
159
98
|
end
|
160
99
|
|
161
|
-
def
|
162
|
-
|
100
|
+
def valid?
|
101
|
+
errors.empty?
|
163
102
|
end
|
164
103
|
|
165
|
-
def
|
166
|
-
|
104
|
+
def errors
|
105
|
+
{}
|
167
106
|
end
|
168
107
|
|
169
|
-
def
|
170
|
-
|
108
|
+
def to_hash
|
109
|
+
(self.class.properties || []).inject({}) do |hash, key|
|
110
|
+
hash[key] = send(key) if respond_to?(key)
|
111
|
+
hash
|
112
|
+
end
|
171
113
|
end
|
172
114
|
|
173
|
-
def
|
174
|
-
|
115
|
+
def inspect
|
116
|
+
ret = "#<#{self.class.to_s}"
|
117
|
+
self.class.properties.each do |key|
|
118
|
+
ret << " #{key}=#{self.instance_variable_get("@#{key}").inspect}"
|
119
|
+
end
|
120
|
+
ret << ">"
|
121
|
+
ret
|
175
122
|
end
|
176
123
|
|
177
|
-
def
|
178
|
-
|
179
|
-
|
124
|
+
def self.from_soap(data)
|
125
|
+
data = data.dup if data
|
126
|
+
|
127
|
+
# Merge attributes into the main hash
|
128
|
+
if data && data[:attributes] && data[:attributes][:soap_attribute]
|
129
|
+
attrs = {}
|
130
|
+
attrs = data[:attributes][:soap_attribute].inject({}) do |hash, attr|
|
131
|
+
hash[attr[:name]] = attr[:values][:string]
|
132
|
+
hash
|
133
|
+
end
|
134
|
+
data.delete :attributes
|
135
|
+
data.merge! attrs
|
136
|
+
end
|
137
|
+
|
138
|
+
# Clean soap values
|
139
|
+
data.each do |(key, val)|
|
140
|
+
if val.is_a?(Hash) && val[:"@xmlns"]
|
141
|
+
val.delete(:"@xmlns")
|
142
|
+
data[key] = nil if val.empty?
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Map soap values to property values
|
147
|
+
if @soap_to_property_map
|
148
|
+
data = data.inject({}) do |hash, (key, val)|
|
149
|
+
key = :"#{key}"
|
150
|
+
if @soap_to_property_map.has_key?(key)
|
151
|
+
hash[@soap_to_property_map[key]] = val
|
152
|
+
else
|
153
|
+
hash[key] = val
|
154
|
+
end
|
155
|
+
hash
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
self.new data
|
180
160
|
end
|
181
161
|
|
182
|
-
def
|
183
|
-
|
184
|
-
|
185
|
-
|
162
|
+
def to_soap
|
163
|
+
properties = self.class.properties || []
|
164
|
+
attributes = self.class.attributes || []
|
165
|
+
|
166
|
+
data = {}
|
167
|
+
data[:attributes] = {:SOAPAttribute => []} unless attributes.empty?
|
168
|
+
properties.each do |prop|
|
169
|
+
key = self.class.soap_key_for(prop)
|
170
|
+
val = send(prop)
|
171
|
+
|
172
|
+
if attributes.include?(prop)
|
173
|
+
data[:attributes][:SOAPAttribute] << {:name => key, :values => {:string => val}}
|
174
|
+
else
|
175
|
+
data[key] = val
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
data
|
186
180
|
end
|
187
181
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
182
|
+
def self.soap_key_for(property_key)
|
183
|
+
property_key = :"#{property_key}"
|
184
|
+
if @property_to_soap_map && @property_to_soap_map.has_key?(property_key)
|
185
|
+
return @property_to_soap_map[property_key]
|
186
|
+
end
|
187
|
+
property_key
|
192
188
|
end
|
193
|
-
|
194
|
-
|
189
|
+
|
190
|
+
def self.search_restriction_for(property_key)
|
191
|
+
property_key = :"#{property_key}"
|
192
|
+
if @property_to_search_restriction_map && @property_to_search_restriction_map.has_key?(property_key)
|
193
|
+
return @property_to_search_restriction_map[property_key]
|
194
|
+
end
|
195
|
+
property_key
|
195
196
|
end
|
196
|
-
def real_key_for att; self.class.real_key_for att; end
|
197
|
-
def att_to_ruby att; self.class.att_to_ruby att; end
|
198
197
|
end
|
199
198
|
end
|
@@ -4,17 +4,21 @@ module SimpleCrowd
|
|
4
4
|
attr_reader :type
|
5
5
|
attr_reader :original
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
super string
|
7
|
+
def initialize(original, message=nil)
|
9
8
|
@original = original
|
10
9
|
|
11
10
|
if original.is_a?(Savon::SOAP::Fault)
|
11
|
+
fault = original.to_hash[:fault] || {}
|
12
12
|
@response = original.http
|
13
|
-
@type =
|
13
|
+
@type = fault[:detail].keys.first rescue :fault
|
14
|
+
message = fault[:faultstring] if message.blank?
|
14
15
|
elsif original.is_a?(Savon::HTTP::Error)
|
15
16
|
@response = original.http
|
16
17
|
@type = :http
|
17
18
|
end
|
19
|
+
|
20
|
+
message = original.to_s if message.blank?
|
21
|
+
super message
|
18
22
|
end
|
19
23
|
|
20
24
|
def type? type
|
data/lib/simple_crowd/group.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module SimpleCrowd
|
2
2
|
class Group < CrowdEntity
|
3
|
-
property :id
|
4
|
-
property :name
|
3
|
+
property :id, :immutable => true
|
4
|
+
property :name, :immutable => true
|
5
|
+
property :directory_id, :immutable => true
|
6
|
+
|
5
7
|
property :active, :default => true
|
6
8
|
property :description
|
7
|
-
property :directory_id
|
8
9
|
|
9
10
|
property :members
|
10
11
|
end
|
@@ -23,7 +23,7 @@ module SimpleCrowd
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def authenticate_user name, password, factors = nil
|
26
|
-
(user = find_user_by_name(name)) && user.password && user.password == password ? new_user_token(name) : nil
|
26
|
+
(user = find_user_by_name(name)) && user.instance_variable_get('@password') && user.instance_variable_get('@password') == password ? new_user_token(name) : nil
|
27
27
|
end
|
28
28
|
def create_user_token name
|
29
29
|
new_user_token(name) if find_user_by_name(name)
|
@@ -54,9 +54,19 @@ module SimpleCrowd
|
|
54
54
|
def search_users_by_email email
|
55
55
|
users.select{|u| u.email =~ /#{email}/}
|
56
56
|
end
|
57
|
+
def search_users criteria, limit=0, start=0
|
58
|
+
users = users()
|
59
|
+
criteria.each do |search_key, search_val|
|
60
|
+
users = users.select do |user|
|
61
|
+
val = user[:"#{search_key}"]
|
62
|
+
val && val.downcase.include?(search_val.downcase)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
users
|
66
|
+
end
|
57
67
|
def add_user user, credential
|
58
68
|
if user && user.username && !find_user_by_name(user.username)
|
59
|
-
user.password
|
69
|
+
user.instance_variable_set('@password', credential)
|
60
70
|
self.class.users << user
|
61
71
|
user
|
62
72
|
end
|
@@ -67,7 +77,7 @@ module SimpleCrowd
|
|
67
77
|
end
|
68
78
|
def update_user_credential name, credential, encrypted = false
|
69
79
|
if user = find_user_by_name(name)
|
70
|
-
user.password
|
80
|
+
user.instance_variable_set('@password', credential)
|
71
81
|
end
|
72
82
|
end
|
73
83
|
def update_user_attribute user, name, value
|
@@ -87,6 +97,7 @@ module SimpleCrowd
|
|
87
97
|
attrs_to_update.each do |a|
|
88
98
|
stored_user[a] = user.send(a)
|
89
99
|
end
|
100
|
+
user.clean
|
90
101
|
end
|
91
102
|
|
92
103
|
def is_group_member? group, user
|
data/lib/simple_crowd/user.rb
CHANGED
@@ -1,17 +1,23 @@
|
|
1
1
|
module SimpleCrowd
|
2
2
|
class User < CrowdEntity
|
3
|
-
|
4
3
|
# Immutable properties
|
5
4
|
property :id, :immutable => true
|
6
5
|
property :username, :immutable => true, :map_soap => :name
|
7
|
-
property :
|
8
|
-
|
9
|
-
property :
|
6
|
+
property :directory_id, :immutable => true, :search_restriction => 'principal.directory.id'
|
7
|
+
|
8
|
+
property :active, :default => true, :search_restriction => 'principal.active'
|
9
|
+
property :description
|
10
10
|
|
11
11
|
# Assumed available attributes (with soap aliases)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
attribute :first_name, :map_soap => :givenName
|
13
|
+
attribute :last_name, :map_soap => :sn
|
14
|
+
attribute :display_name, :map_soap => :displayName, :search_restriction => 'principal.fullname'
|
15
|
+
attribute :email, :map_soap => :mail, :search_restriction => 'principal.email'
|
16
|
+
|
17
|
+
def errors
|
18
|
+
errors = super
|
19
|
+
errors[:username] = "cannot be blank" if username.to_s == ""
|
20
|
+
errors
|
21
|
+
end
|
16
22
|
end
|
17
23
|
end
|
data/lib/simple_crowd/version.rb
CHANGED
data/simple_crowd.gemspec
CHANGED
@@ -19,7 +19,6 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
21
|
s.add_runtime_dependency(%q<savon>, [">= 1.0.0"])
|
22
|
-
s.add_runtime_dependency(%q<hashie>, [">= 1.0.0"])
|
23
22
|
|
24
23
|
s.add_development_dependency(%q<bundler>, [">= 1.0.21"])
|
25
24
|
s.add_development_dependency(%q<rake>, [">= 0"])
|
data/test/factories.rb
CHANGED
@@ -3,9 +3,9 @@ FactoryGirl.define do
|
|
3
3
|
first_name 'Test'
|
4
4
|
last_name 'User'
|
5
5
|
display_name {|a| "#{a.first_name} #{a.last_name}"}
|
6
|
-
email {|a| "#{a.first_name}.#{a.last_name}@
|
7
|
-
sequence(:username) {|n| "
|
6
|
+
email {|a| "#{a.first_name}.#{a.last_name}@testing.com".downcase }
|
7
|
+
sequence(:username) {|n| "testadd#{n}" }
|
8
8
|
# Clear dirty properties
|
9
|
-
|
9
|
+
after(:build) { |user| user.dirty_properties.clear }
|
10
10
|
end
|
11
11
|
end
|
data/test/test_client.rb
CHANGED
@@ -2,10 +2,10 @@ require 'helper'
|
|
2
2
|
|
3
3
|
class TestClient < Test::Unit::TestCase
|
4
4
|
CROWD_CONFIG = YAML.load_file($CROWD_CONFIG_PATH)['crowd']
|
5
|
-
TEST_USER=
|
6
|
-
TEST_PASSWORD=
|
7
|
-
TEST_GROUP=
|
8
|
-
TEST_EMAIL=
|
5
|
+
TEST_USER = CROWD_CONFIG['test_user']
|
6
|
+
TEST_PASSWORD = CROWD_CONFIG['test_pass']
|
7
|
+
TEST_GROUP = CROWD_CONFIG['test_group']
|
8
|
+
TEST_EMAIL = CROWD_CONFIG['test_email']
|
9
9
|
context "A Client" do
|
10
10
|
setup do
|
11
11
|
@client = SimpleCrowd::Client.new({:service_url => CROWD_CONFIG['service_url'],
|
@@ -133,8 +133,9 @@ class TestClient < Test::Unit::TestCase
|
|
133
133
|
should "find user by name" do
|
134
134
|
user = @client.find_user_by_name TEST_USER
|
135
135
|
user.should_not be nil
|
136
|
-
[:id, :username, :
|
137
|
-
|
136
|
+
[:id, :username, :active, :directory_id, :first_name, :last_name, :email].each do |key|
|
137
|
+
user.send(key).should_not be nil
|
138
|
+
end
|
138
139
|
assert_requested :post, @service_url, :times => 2
|
139
140
|
end
|
140
141
|
should "find user by token" do
|
@@ -161,7 +162,7 @@ class TestClient < Test::Unit::TestCase
|
|
161
162
|
user.last_name.should == "User"
|
162
163
|
|
163
164
|
# partial searches should return nothing
|
164
|
-
user = @client.find_user_by_email TEST_EMAIL
|
165
|
+
user = @client.find_user_by_email TEST_EMAIL[0..-5]
|
165
166
|
user.should be nil
|
166
167
|
|
167
168
|
assert_requested :post, @service_url, :times => 3
|
@@ -222,33 +223,35 @@ class TestClient < Test::Unit::TestCase
|
|
222
223
|
updateduser.first_name.should == 'UpdatedFirst'
|
223
224
|
@client.remove_user username
|
224
225
|
end
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
226
|
+
# TODO: Implement!
|
227
|
+
#should "update user custom attribute" do
|
228
|
+
# username = "test_update"
|
229
|
+
# localuser = FactoryGirl.build(:user, :username => username)
|
230
|
+
# remoteuser = @client.add_user(localuser, "updatepass")
|
231
|
+
# @client.update_user_attribute(username, 'customAttr', 'customVal').should be true
|
232
|
+
# remoteuser = @client.find_user_with_attributes_by_name username
|
233
|
+
# remoteuser.last_name.should == localuser.last_name
|
234
|
+
#
|
235
|
+
# remoteuser[:customAttr].should == 'customVal'
|
236
|
+
# @client.remove_user username
|
237
|
+
#end
|
238
|
+
# TODO: Implement!
|
239
|
+
#should "update user attribute array" do
|
240
|
+
# username = "test_update"
|
241
|
+
# localuser = FactoryGirl.build(:user, :username => username)
|
242
|
+
# remoteuser = @client.add_user(localuser, "updatepass")
|
243
|
+
# test_array = ["one", "two", "4"]
|
244
|
+
# @client.update_user_attribute(username, 'arrayTest', test_array).should be true
|
245
|
+
# remoteuser = @client.find_user_with_attributes_by_name username
|
246
|
+
# remoteuser.last_name.should == localuser.last_name
|
247
|
+
# remoteuser[:arrayTest].sort.should == test_array.sort
|
248
|
+
# test_array.delete "two"
|
249
|
+
# @client.update_user_attribute(username, 'arrayTest', test_array).should be true
|
250
|
+
# remoteuser = @client.find_user_with_attributes_by_name username
|
251
|
+
# remoteuser[:arrayTest].sort.should == test_array.sort
|
252
|
+
# remoteuser[:arrayTest].include?("two").should be false
|
253
|
+
# @client.remove_user username
|
254
|
+
#end
|
252
255
|
should "update user" do
|
253
256
|
username = "test_update"
|
254
257
|
localuser = FactoryGirl.build(:user, :username => username)
|
data/test/test_user.rb
CHANGED
@@ -22,12 +22,13 @@ class TestUser < Test::Unit::TestCase
|
|
22
22
|
|
23
23
|
should "test attributes" do
|
24
24
|
@user.first_name = "Blah"
|
25
|
-
@user.givenName.should == "Blah"
|
26
25
|
end
|
27
26
|
|
28
27
|
should "update with" do
|
29
28
|
@user.dirty?.should be false
|
30
|
-
@user.
|
29
|
+
@user.first_name = @user.first_name
|
30
|
+
@user.dirty?.should be false
|
31
|
+
@user.last_name = "Updated"
|
31
32
|
@user.dirty?.should be true
|
32
33
|
@user.dirty_properties.length.should == 1
|
33
34
|
@user.dirty?(:last_name).should be true
|
@@ -35,34 +36,42 @@ class TestUser < Test::Unit::TestCase
|
|
35
36
|
end
|
36
37
|
|
37
38
|
should "map to soap" do
|
38
|
-
soap_user = @user.
|
39
|
+
soap_user = @user.to_soap
|
39
40
|
soap_user.should_not be nil
|
40
|
-
soap_user[:attributes].key?(
|
41
|
-
soap_user[:attributes][
|
41
|
+
soap_user[:attributes].key?(:SOAPAttribute).should be true
|
42
|
+
soap_user[:attributes][:SOAPAttribute].length.should == @user.class.attributes.length
|
42
43
|
soap_user[:name].should == @user.username
|
43
|
-
soap_user[:attributes][
|
44
|
+
soap_user[:attributes][:SOAPAttribute].select{|a|a[:name] == :mail}[0][:values][:string].should == @user.email
|
44
45
|
end
|
45
46
|
should "parse from soap" do
|
46
|
-
soap_user = {
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
soap_user = {
|
48
|
+
:id=>"-1",
|
49
|
+
:active=>true,
|
50
|
+
:attributes=>{
|
51
|
+
:soap_attribute=>[
|
52
|
+
{:name=>"givenName", :values=>{:string=>"parsefirstname"}},
|
53
|
+
{:name=>"sn", :values=>{:string=>"parselastname"}},
|
54
|
+
{:name=>"displayName", :values=>{:string=>"parsedisplayname"}},
|
55
|
+
{:name=>"mail", :values=>{:string=>"test@thinkwell.com"}},
|
56
|
+
{:name=>"customAttr", :values=>{:string => ["custom1", "custom2"]}}
|
57
|
+
],
|
58
|
+
:@xmlns=>"http://soap.integration.crowd.atlassian.com"
|
59
|
+
},
|
60
|
+
:description=>{:@xmlns=>"http://soap.integration.crowd.atlassian.com"},
|
61
|
+
:directory_id=>"32769",
|
62
|
+
:name=>"testparse"
|
63
|
+
}
|
64
|
+
|
65
|
+
obj_user = SimpleCrowd::User.from_soap soap_user
|
53
66
|
obj_user.should_not be_nil
|
54
67
|
obj_user.active.should == true
|
55
68
|
obj_user.first_name.should == "parsefirstname"
|
56
69
|
obj_user.last_name.should == "parselastname"
|
57
70
|
obj_user.display_name.should == "parsedisplayname"
|
58
|
-
obj_user.
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
should "mark new props as atttributes" do
|
63
|
-
curr_attributes = @user.attributes_keys
|
64
|
-
@user[:new_prop] = "new value"
|
65
|
-
(@user.attributes_keys - curr_attributes).should == [:new_prop]
|
71
|
+
obj_user.email.should == "test@thinkwell.com"
|
72
|
+
obj_user.description.should be_nil
|
73
|
+
#obj_user.customAttr.should == ["custom1", "custom2"]
|
74
|
+
#(obj_user.attributes_keys - [:first_name, :last_name, :display_name, :customAttr, :email]).empty?.should be true
|
66
75
|
end
|
67
76
|
|
68
77
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_crowd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.2.0.beta2
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Paul Strong
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: savon
|
@@ -27,22 +27,6 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 1.0.0
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: hashie
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ! '>='
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: 1.0.0
|
38
|
-
type: :runtime
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ! '>='
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: 1.0.0
|
46
30
|
- !ruby/object:Gem::Dependency
|
47
31
|
name: bundler
|
48
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -93,7 +77,6 @@ files:
|
|
93
77
|
- lib/simple_crowd/crowd_entity.rb
|
94
78
|
- lib/simple_crowd/crowd_error.rb
|
95
79
|
- lib/simple_crowd/group.rb
|
96
|
-
- lib/simple_crowd/mappers/soap_attributes.rb
|
97
80
|
- lib/simple_crowd/mock_client.rb
|
98
81
|
- lib/simple_crowd/user.rb
|
99
82
|
- lib/simple_crowd/version.rb
|
@@ -119,9 +102,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
119
102
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
103
|
none: false
|
121
104
|
requirements:
|
122
|
-
- - ! '
|
105
|
+
- - ! '>'
|
123
106
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
107
|
+
version: 1.3.1
|
125
108
|
requirements: []
|
126
109
|
rubyforge_project: simple_crowd
|
127
110
|
rubygems_version: 1.8.24
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module SimpleCrowd
|
2
|
-
module Mappers
|
3
|
-
class SoapAttributes
|
4
|
-
def self.produce hash
|
5
|
-
{"int:SOAPAttribute" => hash.inject([]) {|attrs, (key, val)| attrs << {"int:name" => key, "int:values" => {"wsdl:string" => val}}}}
|
6
|
-
end
|
7
|
-
def self.parse attributes
|
8
|
-
soap = attributes[:soap_attribute]
|
9
|
-
(soap && soap.inject({}) {|hash, attr| hash[attr[:name].to_sym] = attr[:values][:string]; hash }) || {}
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|