pyu-activesp 0.0.4.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+