activesp 0.0.1 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +25 -0
- data/README.rdoc +105 -0
- data/Rakefile +35 -6
- data/VERSION +1 -1
- data/lib/activesp.rb +27 -0
- data/lib/activesp/associations.rb +76 -0
- data/lib/activesp/base.rb +93 -7
- data/lib/activesp/caching.rb +32 -3
- data/lib/activesp/connection.rb +53 -16
- data/lib/activesp/content_type.rb +50 -1
- data/lib/activesp/field.rb +48 -2
- data/lib/activesp/file.rb +71 -0
- data/lib/activesp/folder.rb +72 -9
- data/lib/activesp/ghost_field.rb +70 -1
- data/lib/activesp/group.rb +46 -7
- data/lib/activesp/item.rb +252 -23
- data/lib/activesp/list.rb +284 -81
- data/lib/activesp/permission_set.rb +39 -4
- data/lib/activesp/persistent_caching.rb +61 -1
- data/lib/activesp/role.rb +49 -8
- data/lib/activesp/root.rb +67 -3
- data/lib/activesp/site.rb +110 -20
- data/lib/activesp/url.rb +27 -0
- data/lib/activesp/user.rb +39 -1
- data/lib/activesp/util.rb +198 -40
- metadata +42 -16
data/lib/activesp/caching.rb
CHANGED
@@ -1,8 +1,37 @@
|
|
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
|
+
|
1
26
|
module ActiveSP
|
2
27
|
|
28
|
+
# @private
|
3
29
|
module Caching
|
4
30
|
|
31
|
+
private
|
32
|
+
|
5
33
|
def cache(name, options = {})
|
34
|
+
options = options.dup
|
6
35
|
duplicate = options.delete(:dup)
|
7
36
|
options.empty? or raise ArgumentError, "unsupported options #{options.keys.map { |k| k.inspect }.join(", ")}"
|
8
37
|
(@cached_methods ||= []) << name
|
@@ -14,11 +43,11 @@ module ActiveSP
|
|
14
43
|
if defined? @#{name}
|
15
44
|
@#{name}
|
16
45
|
else
|
17
|
-
@#{name} = #{name}__uncached(*a, &b)
|
18
|
-
end#{".dup" if duplicate}
|
46
|
+
@#{name} = #{name}__uncached(*a, &b)#{".dup" if duplicate == :once}
|
47
|
+
end#{".dup" if duplicate == :always}
|
19
48
|
end
|
20
49
|
#{access} :#{name}
|
21
|
-
|
50
|
+
remove_method(:reload) if instance_methods(false).include?("reload")
|
22
51
|
def reload
|
23
52
|
#{@cached_methods.map { |m| "remove_instance_variable(:@#{m}) if defined?(@#{m})" }.join(';')}
|
24
53
|
super if defined? super
|
data/lib/activesp/connection.rb
CHANGED
@@ -1,3 +1,28 @@
|
|
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
|
+
|
1
26
|
require 'savon'
|
2
27
|
require 'net/ntlm_http'
|
3
28
|
|
@@ -9,29 +34,40 @@ end
|
|
9
34
|
|
10
35
|
module ActiveSP
|
11
36
|
|
37
|
+
# This class is uses to configure the connection to a SharePoint repository. This is
|
38
|
+
# the starting point for doing anything with SharePoint.
|
12
39
|
class Connection
|
13
40
|
|
14
41
|
include Util
|
15
42
|
include PersistentCachingConfig
|
16
43
|
|
44
|
+
# @private
|
17
45
|
# TODO: create profile
|
18
46
|
attr_reader :login, :password, :root_url, :trace
|
19
47
|
|
48
|
+
# @param [Hash] options The connection options
|
49
|
+
# @option options [String] :root The URL of the root site
|
50
|
+
# @option options [String] :login (nil) The login
|
51
|
+
# @option options [String] :password (nil) The password associated with the given login. Is mandatory if the login is specified. Also can't be "password" as that is inherently insafe. We don't explicitly check for this, but it can't be that.
|
20
52
|
def initialize(options = {})
|
53
|
+
options = options.dup
|
21
54
|
@root_url = options.delete(:root) or raise ArgumentError, "missing :root option"
|
22
55
|
@login = options.delete(:login)
|
23
56
|
@password = options.delete(:password)
|
24
57
|
@trace = options.delete(:trace)
|
25
58
|
options.empty? or raise ArgumentError, "unknown options #{options.keys.map { |k| k.inspect }.join(", ")}"
|
26
59
|
cache = nil
|
27
|
-
configure_persistent_cache { |c| cache
|
60
|
+
configure_persistent_cache { |c| cache ||= c }
|
28
61
|
end
|
29
62
|
|
63
|
+
# Finds the object with the given key
|
64
|
+
# @param [String] key The key of the object to find
|
65
|
+
# @return [Base, nil] The object with the given key, or nil if no object with the given key is found
|
30
66
|
def find_by_key(key)
|
31
67
|
type, trail = decode_key(key)
|
32
68
|
case type[0]
|
33
69
|
when ?S
|
34
|
-
ActiveSP::Site.new(self, trail[0] == "" ? @root_url : File.join(@root_url, trail[0]), trail[1].to_i)
|
70
|
+
ActiveSP::Site.new(self, trail[0] == "" ? @root_url : ::File.join(@root_url, trail[0]), trail[1].to_i)
|
35
71
|
when ?L
|
36
72
|
ActiveSP::List.new(find_by_key(trail[0]), trail[1])
|
37
73
|
when ?U
|
@@ -45,19 +81,11 @@ module ActiveSP
|
|
45
81
|
when ?P
|
46
82
|
ActiveSP::PermissionSet.new(find_by_key(trail[0]))
|
47
83
|
when ?F
|
48
|
-
|
49
|
-
|
50
|
-
ActiveSP::Folder.new(parent.list, trail[1], parent)
|
51
|
-
else
|
52
|
-
ActiveSP::Folder.new(parent, trail[1], nil)
|
53
|
-
end
|
84
|
+
list = find_by_key(trail[0])
|
85
|
+
ActiveSP::Folder.new(list, trail[1])
|
54
86
|
when ?I
|
55
|
-
|
56
|
-
|
57
|
-
ActiveSP::Item.new(parent.list, trail[1], parent)
|
58
|
-
else
|
59
|
-
ActiveSP::Item.new(parent, trail[1], nil)
|
60
|
-
end
|
87
|
+
list = find_by_key(trail[0])
|
88
|
+
ActiveSP::Item.new(list, trail[1])
|
61
89
|
when ?T
|
62
90
|
parent = find_by_key(trail[0])
|
63
91
|
if ActiveSP::List === parent
|
@@ -70,6 +98,12 @@ module ActiveSP
|
|
70
98
|
end
|
71
99
|
end
|
72
100
|
|
101
|
+
# Fetches the content at the given URL using the login and password with which this
|
102
|
+
# connection was constructed, if any. Always uses the GET method. Supports only
|
103
|
+
# HTTP as protocol at the time of writing. This is useful for fetching content files
|
104
|
+
# from the server.
|
105
|
+
# @param [String] url The URL to fetch
|
106
|
+
# @return [String] The content fetched from the URL
|
73
107
|
def fetch(url)
|
74
108
|
# TODO: support HTTPS too
|
75
109
|
@open_params ||= begin
|
@@ -78,9 +112,12 @@ module ActiveSP
|
|
78
112
|
end
|
79
113
|
Net::HTTP.start(*@open_params) do |http|
|
80
114
|
request = Net::HTTP::Get.new(URL(url).full_path.gsub(/ /, "%20"))
|
81
|
-
request.ntlm_auth(@login, @password)
|
115
|
+
request.ntlm_auth(@login, @password) if @login
|
82
116
|
response = http.request(request)
|
83
|
-
response
|
117
|
+
# if Net::HTTPFound === response
|
118
|
+
# response = fetch(response["location"])
|
119
|
+
# end
|
120
|
+
# response
|
84
121
|
end
|
85
122
|
end
|
86
123
|
|
@@ -1,3 +1,28 @@
|
|
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
|
+
|
1
26
|
module ActiveSP
|
2
27
|
|
3
28
|
class ContentType < Base
|
@@ -7,9 +32,11 @@ module ActiveSP
|
|
7
32
|
extend PersistentCaching
|
8
33
|
include Util
|
9
34
|
|
35
|
+
# @private
|
10
36
|
attr_reader :id
|
11
37
|
|
12
38
|
persistent { |site, list, id, *a| [site.connection, [:content_type, id]] }
|
39
|
+
# @private
|
13
40
|
def initialize(site, list, id, name = nil, description = nil, version = nil, group = nil)
|
14
41
|
@site, @list, @id = site, list, id
|
15
42
|
@Name = name if name
|
@@ -18,49 +45,71 @@ module ActiveSP
|
|
18
45
|
@Group = group if group
|
19
46
|
end
|
20
47
|
|
48
|
+
# Returns the scope of the content type. This can be either a site or a list
|
49
|
+
# @return [Site, List]
|
21
50
|
def scope
|
22
51
|
@list || @site
|
23
52
|
end
|
24
53
|
|
54
|
+
# Returns the supertype of this content type. This is the content type as defined on the containing
|
55
|
+
# site in case this content type has a list as scope. returns nil for a content type that has a site
|
56
|
+
# as scope
|
57
|
+
# @return [ContentType, nil]
|
25
58
|
def supertype
|
26
59
|
superkey = split_id[0..-2].join("")
|
27
60
|
(@list ? @list.content_type(superkey) : nil) || @site.content_type(superkey)
|
28
61
|
end
|
29
62
|
cache :supertype
|
30
63
|
|
64
|
+
# See {Base#key}
|
65
|
+
# @return [String]
|
31
66
|
def key
|
32
67
|
encode_key("T", [scope.key, @id])
|
33
68
|
end
|
34
69
|
|
70
|
+
# @private
|
35
71
|
def Name
|
36
72
|
data["Name"].to_s
|
37
73
|
end
|
38
74
|
cache :Name
|
39
75
|
|
76
|
+
# @private
|
40
77
|
def Description
|
41
78
|
data["Description"].to_s
|
42
79
|
end
|
43
80
|
cache :Description
|
44
81
|
|
82
|
+
# @private
|
45
83
|
def Version
|
46
84
|
data["Version"].to_s
|
47
85
|
end
|
48
86
|
cache :Version
|
49
87
|
|
88
|
+
# @private
|
50
89
|
def Group
|
51
90
|
data["Group"].to_s
|
52
91
|
end
|
53
92
|
cache :Group
|
54
93
|
|
94
|
+
# Returns the list of fields defined for this content type
|
95
|
+
# @return [Array<Field>]
|
55
96
|
def fields
|
56
97
|
data.xpath("//sp:Field", NS).map { |field| scope.field(field["ID"]) }.compact
|
57
98
|
end
|
58
|
-
cache :fields, :dup =>
|
99
|
+
cache :fields, :dup => :always
|
59
100
|
|
101
|
+
# See {Base#save}
|
102
|
+
# @return [void]
|
103
|
+
def save
|
104
|
+
p untype_cast_attributes(@site, nil, internal_attribute_types, changed_attributes)
|
105
|
+
end
|
106
|
+
|
107
|
+
# @private
|
60
108
|
def to_s
|
61
109
|
"#<ActiveSP::ContentType Name=#{self.Name}>"
|
62
110
|
end
|
63
111
|
|
112
|
+
# @private
|
64
113
|
alias inspect to_s
|
65
114
|
|
66
115
|
private
|
data/lib/activesp/field.rb
CHANGED
@@ -1,3 +1,28 @@
|
|
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
|
+
|
1
26
|
module ActiveSP
|
2
27
|
|
3
28
|
class Field < Base
|
@@ -6,41 +31,62 @@ module ActiveSP
|
|
6
31
|
extend Caching
|
7
32
|
include Util
|
8
33
|
|
9
|
-
|
34
|
+
# @private
|
35
|
+
attr_reader :ID, :Name, :internal_type
|
36
|
+
# Returns the scope of the field. This can be a site or a list
|
37
|
+
# @return [Site, List]
|
38
|
+
attr_reader :scope
|
39
|
+
# Returns the parent field. This is the field defined on the containing site in case the field has a list as scope
|
40
|
+
# @return [Field]
|
41
|
+
attr_reader :parent
|
10
42
|
|
11
43
|
# There is no call to get to the field info directly, so these should always
|
12
44
|
# be accessed through the site or list they belong to. Hence, we do not use
|
13
45
|
# caching here as it is useless.
|
46
|
+
# @private
|
14
47
|
def initialize(scope, id, name, type, parent, attributes_before_type_cast)
|
15
48
|
@scope, @ID, @Name, @internal_type, @parent, @attributes_before_type_cast = scope, id, name, type, parent, attributes_before_type_cast
|
16
49
|
@site = Site === @scope ? @scope : @scope.site
|
17
50
|
end
|
18
51
|
|
52
|
+
# See {Base#key}
|
53
|
+
# @return [String]
|
19
54
|
def key
|
20
55
|
encode_key("A", [@scope.key, @ID])
|
21
56
|
end
|
22
57
|
|
58
|
+
# @private
|
23
59
|
def List
|
24
60
|
list_for_lookup
|
25
61
|
end
|
26
62
|
|
63
|
+
# @private
|
27
64
|
def Type
|
28
65
|
translate_internal_type(self)
|
29
66
|
end
|
30
67
|
|
31
|
-
#
|
68
|
+
# @private
|
32
69
|
def Mult
|
33
70
|
!!attributes["Mult"]
|
34
71
|
end
|
35
72
|
|
73
|
+
# @private
|
36
74
|
def ReadOnly
|
37
75
|
!!attributes["ReadOnly"]
|
38
76
|
end
|
39
77
|
|
78
|
+
# See {Base#save}
|
79
|
+
# @return [void]
|
80
|
+
def save
|
81
|
+
p untype_cast_attributes(@site, nil, internal_attribute_types, changed_attributes)
|
82
|
+
end
|
83
|
+
|
84
|
+
# @private
|
40
85
|
def to_s
|
41
86
|
"#<ActiveSP::Field name=#{self.Name}>"
|
42
87
|
end
|
43
88
|
|
89
|
+
# @private
|
44
90
|
alias inspect to_s
|
45
91
|
|
46
92
|
private
|
@@ -0,0 +1,71 @@
|
|
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 File
|
29
|
+
|
30
|
+
include InSite
|
31
|
+
|
32
|
+
attr_reader :url
|
33
|
+
|
34
|
+
def initialize(item, url, destroyable)
|
35
|
+
@item, @url, @destroyable = item, url, destroyable
|
36
|
+
@site = @item.list.site
|
37
|
+
end
|
38
|
+
|
39
|
+
def file_name
|
40
|
+
::File.basename(@url)
|
41
|
+
end
|
42
|
+
|
43
|
+
def data
|
44
|
+
@item.list.site.connection.fetch(@url).body
|
45
|
+
end
|
46
|
+
|
47
|
+
def destroy
|
48
|
+
if @destroyable
|
49
|
+
result = call("Lists", "delete_attachment", "listName" => @item.list.id, "listItemID" => @item.ID, "url" => @url)
|
50
|
+
if delete_result = result.xpath("//sp:DeleteAttachmentResponse", NS).first
|
51
|
+
self
|
52
|
+
else
|
53
|
+
raise "file could not be deleted"
|
54
|
+
end
|
55
|
+
else
|
56
|
+
raise TypeError, "this file cannot be destroyed"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# @private
|
61
|
+
def to_s
|
62
|
+
"#<ActiveSP::File url=#{@url}>"
|
63
|
+
end
|
64
|
+
|
65
|
+
# @private
|
66
|
+
alias inspect to_s
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|