pyu-activesp 0.0.4.1.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.
@@ -0,0 +1,97 @@
1
+ # Copyright (c) 2010 XAOP bvba
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ #
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ #
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ # OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ module ActiveSP
27
+
28
+ class User < Base
29
+
30
+ extend Caching
31
+ extend PersistentCaching
32
+ include Util
33
+ include InSite
34
+
35
+ # @private
36
+ attr_reader :login_name
37
+
38
+ persistent { |site, login_name, *a| [site.connection, [:user, login_name]] }
39
+ # @private
40
+ def initialize(site, login_name, attributes_before_type_cast = nil)
41
+ @site, @login_name = site, login_name
42
+ @attributes_before_type_cast = attributes_before_type_cast if attributes_before_type_cast
43
+ end
44
+
45
+ # See {Base#key}
46
+ # @return [String]
47
+ def key
48
+ encode_key("U", [@login_name])
49
+ end
50
+
51
+ # See {Base#save}
52
+ # @return [void]
53
+ def save
54
+ p untype_cast_attributes(@site, nil, internal_attribute_types, changed_attributes)
55
+ end
56
+
57
+ # @private
58
+ def to_s
59
+ "#<ActiveSP::User login_name=#{login_name}>"
60
+ end
61
+
62
+ # @private
63
+ alias inspect to_s
64
+
65
+ private
66
+
67
+ def data
68
+ call("UserGroup", "get_user_info", "userLoginName" => @login_name).xpath("//spdir:User", NS).first
69
+ end
70
+ cache :data
71
+
72
+ def attributes_before_type_cast
73
+ clean_attributes(data.attributes)
74
+ end
75
+ cache :attributes_before_type_cast
76
+
77
+ def original_attributes
78
+ type_cast_attributes(@site, nil, internal_attribute_types, attributes_before_type_cast)
79
+ end
80
+ cache :original_attributes
81
+
82
+ def internal_attribute_types
83
+ @@internal_attribute_types ||= {
84
+ "Email" => GhostField.new("Email", "Text", false, true),
85
+ "ID" => GhostField.new("ID", "Text", false, true),
86
+ "IsDomainGroup" => GhostField.new("Email", "Bool", false, true),
87
+ "IsSiteAdmin" => GhostField.new("IsSiteAdmin", "Bool", false, true),
88
+ "LoginName" => GhostField.new("LoginName", "Text", false, true),
89
+ "Name" => GhostField.new("Name", "Text", false, true),
90
+ "Notes" => GhostField.new("Notes", "Text", false, true),
91
+ "Sid" => GhostField.new("Sid", "Text", false, true)
92
+ }
93
+ end
94
+
95
+ end
96
+
97
+ end
@@ -0,0 +1,326 @@
1
+ # Copyright (c) 2010 XAOP bvba
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ #
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ #
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ # OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ module ActiveSP
27
+
28
+ # @private
29
+ module Util
30
+
31
+ private
32
+
33
+ def decode_field_name(name)
34
+ name.gsub(/_x([0-9af]{4})_/i) { [$1.to_i(16)].pack("U") }
35
+ end
36
+
37
+ def clean_attributes(attributes)
38
+ attributes.inject({}) { |h, (k, v)| h[k] = v.to_s ; h }
39
+ end
40
+
41
+ def clean_item_attributes(attributes)
42
+ attributes.inject({}) { |h, (k, v)| h[k.sub(/\Aows_/, "")] = v.to_s ; h }
43
+ end
44
+
45
+ def type_cast_attributes(site, list, fields, attributes)
46
+ result = attributes.inject({}) do |h, (k, v)|
47
+ k = decode_field_name(k)
48
+ if field = fields[k]
49
+ case field.internal_type
50
+ when "ListReference"
51
+ when "StandardDateTime"
52
+ v = Time.parse(v)
53
+ when "DateTime"
54
+ v = Time.parse(v)
55
+ when "XMLDateTime"
56
+ v = Time.xmlschema(v.sub(/ /, "T"))
57
+ when "Computed", "Text", "Guid", "ContentTypeId", "URL"
58
+ when "Integer", "Counter", "Attachments"
59
+ v = v && v != "" ? Integer(v) : nil
60
+ when "ModStat" # 0
61
+ when "Number"
62
+ v = v.to_f
63
+ when "Boolean"
64
+ v = v == "1"
65
+ when "Bool"
66
+ v = !!v[/true/i]
67
+ when "File"
68
+ v = v.sub(/\A\d+;#/, "")
69
+ when "Note"
70
+
71
+ when "User"
72
+ d = split_multi(v)
73
+ v = create_user_or_group(site, d[2])
74
+ when "InternalUser"
75
+ v = create_user_or_group(site, v)
76
+ when "UserMulti"
77
+ d = split_multi(v)
78
+ v = (0...(d.length / 4)).map { |i| create_user_or_group(site, d[4 * i + 2]) }
79
+
80
+ when "Choice"
81
+ # For some reason there is no encoding here
82
+ when "MultiChoice"
83
+ # SharePoint disallows ;# inside choices and starts with a ;#
84
+ v = v.split(/;#/)[1..-1]
85
+
86
+ when "Lookup"
87
+ d = split_multi(v)
88
+ if field.List
89
+ v = construct_item_from_id(field.List, d[0])
90
+ else
91
+ v = d[2]
92
+ end
93
+ when "LookupMulti"
94
+ d = split_multi(v)
95
+ if field.List
96
+ v = (0...(d.length / 4)).map { |i| construct_item_from_id(field.List, d[4 * i]) }
97
+ else
98
+ v = (0...(d.length / 4)).map { |i| d[4 * i + 2] }
99
+ end
100
+
101
+ else
102
+ # raise NotImplementedError, "don't know type #{field.type.inspect} for #{k}=#{v.inspect}"
103
+ # Note: can't print self if it needs the attributes to be loaded, so just display the class
104
+ # warn "don't know type #{field.internal_type.inspect} for #{k}=#{v.inspect} on #{self.class}"
105
+ end
106
+ else
107
+ # raise ArgumentError, "can't find field #{k.inspect}"
108
+ # Note: can't print self if it needs the attributes to be loaded, so just display the class
109
+ # warn "can't find field #{k.inspect} on #{self.class}"
110
+ end
111
+ h[k] = v
112
+ h
113
+ end
114
+ fields.each_key do |k|
115
+ result[k] = nil unless result.has_key?(k)
116
+ end
117
+ result
118
+ end
119
+
120
+ def create_user_or_group(site, entry)
121
+ if entry == "System Account"
122
+ User.new(site.connection.root, "SHAREPOINT\\system")
123
+ elsif entry[/\\/]
124
+ User.new(site.connection.root, entry)
125
+ else
126
+ Group.new(site.connection.root, entry)
127
+ end
128
+ end
129
+
130
+ def type_check_attribute(field, value)
131
+ case field.internal_type
132
+ when "Text", "File"
133
+ value.to_s
134
+ when "Bool", "Boolean"
135
+ !!value
136
+ when "Integer"
137
+ Integer(value)
138
+ when "StandardDateTime", "XMLDateTime"
139
+ Time === value and value or raise ArgumentError, "wrong type for #{field.Name} attribute"
140
+ when "InternalUser"
141
+ value = value.to_s
142
+ @site.rootsite.user(value) and value or raise ArgumentError, "user with login #{value} does not exist for #{field.Name} attribute"
143
+ when "Lookup"
144
+ if field.List
145
+ if ::ActiveSP::Item === value && value.list == field.List
146
+ value
147
+ else
148
+ raise ArgumentError, "wrong type for #{field.Name} attribute"
149
+ end
150
+ else
151
+ value.to_s
152
+ end
153
+ when "LookupMulti"
154
+ if field.List
155
+ begin
156
+ value = Array(value)
157
+ rescue Exception
158
+ raise ArgumentError, "wrong type for #{field.Name} attribute"
159
+ end
160
+ value.map do |val|
161
+ if ::ActiveSP::Item === val && val.list == field.List
162
+ val
163
+ else
164
+ raise ArgumentError, "wrong type for #{field.Name} attribute"
165
+ end
166
+ end
167
+ else
168
+ raise ArgumentError, "wrong type for #{field.Name} attribute"
169
+ end
170
+ when "DateTime"
171
+ Time === value and value or raise ArgumentError, "wrong type for #{field.Name} attribute"
172
+ when "User"
173
+ if ::ActiveSP::User === value || field.attributes["UserSelectionMode"] == "PeopleAndGroups" && ::ActiveSP::Group === value
174
+ # TODO: check if the user is in the correct group in case a group is specified
175
+ value
176
+ else
177
+ raise ArgumentError, "wrong type for #{field.Name} attribute"
178
+ end
179
+ when "UserMulti"
180
+ begin
181
+ value = Array(value)
182
+ rescue Exception
183
+ raise ArgumentError, "wrong type for #{field.Name} attribute"
184
+ end
185
+ value.map do |val|
186
+ if ::ActiveSP::User === val || field.attributes["UserSelectionMode"] == "PeopleAndGroups" && ::ActiveSP::Group === val
187
+ # TODO: check if the user is in the correct group in case a group is specified
188
+ val
189
+ else
190
+ raise ArgumentError, "wrong type for #{field.Name} attribute"
191
+ end
192
+ end
193
+ else
194
+ raise "not yet #{field.Name}:#{field.internal_type}"
195
+ end
196
+ end
197
+
198
+ def type_check_attributes_for_creation(fields, attributes)
199
+ attributes.inject({}) do |h, (k, v)|
200
+ if field = fields[k]
201
+ if !field.ReadOnly
202
+ h[k] = type_check_attribute(field, v)
203
+ h
204
+ else
205
+ raise ArgumentError, "field #{field.Name} is read-only"
206
+ end
207
+ else
208
+ raise "can't find field #{k.inspect}"
209
+ end
210
+ end
211
+ end
212
+
213
+ def untype_cast_attributes(site, list, fields, attributes)
214
+ attributes.inject({}) do |h, (k, v)|
215
+ if field = fields[k]
216
+ case field.internal_type
217
+ when "Text", "File"
218
+ when "Bool"
219
+ v = v ? "TRUE" : "FALSE"
220
+ when "Boolean"
221
+ v = v ? "1" : "0"
222
+ when "Integer"
223
+ v = v.to_s
224
+ when "DateTime"
225
+ v = v.strftime("%Y-%m-%d %H:%M:%S")
226
+ when "User"
227
+ v = v.ID
228
+ when "UserMulti"
229
+ v = v.map { |ug| ug.ID }.join(";#;#")
230
+ when "Lookup"
231
+ v = v.ID
232
+ when "LookupMulti"
233
+ v = v.map { |i| i.ID }.join(";#;#")
234
+ else
235
+ raise "don't know type #{field.internal_type.inspect} for #{k}=#{v.inspect} on self"
236
+ end
237
+ else
238
+ raise "can't find field #{k.inspect} on #{self}"
239
+ end
240
+ h[k] = v
241
+ h
242
+ end
243
+ end
244
+
245
+ def construct_xml_for_copy_into_items(fields, attributes)
246
+ attributes.map do |k, v|
247
+ field = fields[k]
248
+ Builder::XmlMarkup.new.wsdl(
249
+ :FieldInformation,
250
+ "Type" => field.internal_type,
251
+ "Id" => field.ID,
252
+ "Value" => v,
253
+ "InternalName" => field.StaticName,
254
+ "DisplayName" => field.DisplayName
255
+ )
256
+ end.join("")
257
+ end
258
+
259
+ def construct_xml_for_update_list_items(xml, fields, attributes)
260
+ attributes.map do |k, v|
261
+ field = fields[k]
262
+ xml.Field(v, "Name" => field.StaticName)
263
+ end
264
+ end
265
+
266
+ def encode_key(type, trail)
267
+ "#{type}::#{trail.map { |t| t.to_s.gsub(/:/, ":-") }.join("::")}"
268
+ end
269
+
270
+ def decode_key(key)
271
+ type, *trail = key.split(/::/)
272
+ [type, trail.map { |t| t.gsub(/:-/, ':') }]
273
+ end
274
+
275
+ def split_multi(s)
276
+ # Figure out the exact escaping rules that SharePoint uses
277
+ s.scan(/((?:[^;]|;;#|;[^#;]|;;(?!#))+)(;#)?/).flatten
278
+ end
279
+
280
+ def construct_item_from_id(list, id)
281
+ query = Builder::XmlMarkup.new.Query do |xml|
282
+ xml.Where do |xml|
283
+ xml.Eq do |xml|
284
+ xml.FieldRef(:Name => "ID")
285
+ xml.Value(id, :Type => "Counter")
286
+ end
287
+ end
288
+ end
289
+ list.items(:query => query).first
290
+ end
291
+
292
+ def translate_internal_type(field)
293
+ case field.internal_type
294
+ when "Computed", "Text", "Guid", "ContentTypeId", "URL", "Choice", "MultiChoice", "File", "Note"
295
+ "Text"
296
+ when "Integer", "Counter", "Attachments", "ModStat"
297
+ "Integer"
298
+ when "Number"
299
+ "Float"
300
+ when "StandardDateTime", "DateTime", "XMLDateTime"
301
+ "DateTime"
302
+ when "Boolean", "Bool"
303
+ "Boolean"
304
+ when "User", "InternalUser", "UserMulti"
305
+ "UserReference"
306
+ when "Lookup", "LookupMulti"
307
+ if field.List
308
+ "ItemReference"
309
+ else
310
+ "Text"
311
+ end
312
+ when "ListReference"
313
+ "ListReference"
314
+ else
315
+ "Text"
316
+ end
317
+ end
318
+
319
+ # Somewhat dirty
320
+ def escape_xml(xml)
321
+ Builder::XmlMarkup.new.s(xml).scan(/\A<s>(.*)<\/s>\z/)
322
+ end
323
+
324
+ end
325
+
326
+ end
data/lib/activesp.rb ADDED
@@ -0,0 +1,53 @@
1
+ # Copyright (c) 2010 XAOP bvba
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ #
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ #
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ # OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ require 'nokogiri'
27
+ require 'time'
28
+
29
+ module ActiveSP
30
+ end
31
+
32
+ require 'activesp/util'
33
+ require 'activesp/caching'
34
+ require 'activesp/associations'
35
+ require 'activesp/persistent_caching'
36
+
37
+ require 'activesp/base'
38
+
39
+ require 'activesp/connection'
40
+ require 'activesp/root'
41
+ require 'activesp/site'
42
+ require 'activesp/list'
43
+ require 'activesp/item'
44
+ require 'activesp/folder'
45
+ require 'activesp/url'
46
+ require 'activesp/content_type'
47
+ require 'activesp/field'
48
+ require 'activesp/ghost_field'
49
+ require 'activesp/user'
50
+ require 'activesp/group'
51
+ require 'activesp/role'
52
+ require 'activesp/permission_set'
53
+ require 'activesp/file'
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pyu-activesp
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 4
9
+ - 1
10
+ - 2
11
+ version: 0.0.4.1.2
12
+ platform: ruby
13
+ authors:
14
+ - Peter Vanbroekhoven
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-10-28 00:00:00 -05:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: pyu-savon
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: nokogiri
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ description: An object-oriented interface to SharePoint that uses the web services provided by SharePoint to connect to it. Supports SharePoint 2007 and 2010.
49
+ email: peter@xaop.com
50
+ executables: []
51
+
52
+ extensions: []
53
+
54
+ extra_rdoc_files: []
55
+
56
+ files:
57
+ - VERSION
58
+ - LICENSE
59
+ - README.rdoc
60
+ - Rakefile
61
+ - lib/activesp.rb
62
+ - lib/activesp/caching.rb
63
+ - lib/activesp/util.rb
64
+ - lib/activesp/root.rb
65
+ - lib/activesp/site.rb
66
+ - lib/activesp/item.rb
67
+ - lib/activesp/user.rb
68
+ - lib/activesp/url.rb
69
+ - lib/activesp/associations.rb
70
+ - lib/activesp/file.rb
71
+ - lib/activesp/role.rb
72
+ - lib/activesp/persistent_caching.rb
73
+ - lib/activesp/folder.rb
74
+ - lib/activesp/content_type.rb
75
+ - lib/activesp/ghost_field.rb
76
+ - lib/activesp/permission_set.rb
77
+ - lib/activesp/connection.rb
78
+ - lib/activesp/group.rb
79
+ - lib/activesp/field.rb
80
+ - lib/activesp/list.rb
81
+ - lib/activesp/base.rb
82
+ has_rdoc: true
83
+ homepage: http://www.xaop.com/labs/activesp
84
+ licenses: []
85
+
86
+ post_install_message:
87
+ rdoc_options: []
88
+
89
+ require_paths:
90
+ - lib
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ segments:
98
+ - 1
99
+ - 8
100
+ - 1
101
+ version: 1.8.1
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ requirements: []
111
+
112
+ rubyforge_project:
113
+ rubygems_version: 1.3.7
114
+ signing_key:
115
+ specification_version: 3
116
+ summary: Interface to SharePoint
117
+ test_files: []
118
+