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
@@ -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 PermissionSet
|
@@ -6,22 +31,32 @@ module ActiveSP
|
|
6
31
|
|
7
32
|
attr_reader :scope
|
8
33
|
|
34
|
+
# @private
|
9
35
|
def initialize(scope)
|
10
36
|
@scope = scope
|
11
37
|
end
|
12
38
|
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
|
39
|
+
# See {Base#key}
|
40
|
+
# @return [String]
|
17
41
|
def key
|
18
42
|
encode_key("P", [@scope.key])
|
19
43
|
end
|
20
44
|
|
45
|
+
# Returns the permissions in this permission set as an array of hashes with :accessor mapping to a user,
|
46
|
+
# group or role and :mask mapping to the permission as an integer
|
47
|
+
# @return [Array<Hash{:accessor, :permission => User, Group, Role, Integer}>]
|
48
|
+
# @example
|
49
|
+
# set.permissions #=> [{:accessor=>#<ActiveSP::User login_name=SHAREPOINT\system>, :mask=>134287360}]
|
50
|
+
def permissions
|
51
|
+
@scope.send(:permissions)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @private
|
21
55
|
def to_s
|
22
56
|
"#<ActiveSP::PermissionSet scope=#{@scope}>"
|
23
57
|
end
|
24
58
|
|
59
|
+
# @private
|
25
60
|
alias inspect to_s
|
26
61
|
|
27
62
|
end
|
@@ -1,7 +1,35 @@
|
|
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 PersistentCaching
|
4
30
|
|
31
|
+
private
|
32
|
+
|
5
33
|
def persistent(&blk)
|
6
34
|
class << self ; self ; end.instance_eval do
|
7
35
|
alias_method :old_new, :new
|
@@ -18,6 +46,7 @@ module ActiveSP
|
|
18
46
|
|
19
47
|
end
|
20
48
|
|
49
|
+
# @private
|
21
50
|
class PersistentCache
|
22
51
|
|
23
52
|
def initialize
|
@@ -38,11 +67,42 @@ module ActiveSP
|
|
38
67
|
|
39
68
|
module PersistentCachingConfig
|
40
69
|
|
70
|
+
# Configures the scope of the persistent cache. The default scope of the cache
|
71
|
+
# is the {Connection} object, i.e., each connection has its own cache. For example
|
72
|
+
# you can use this to make thread local caches. Note that the cache is not actually
|
73
|
+
# thread safe at this point so this may not be such a bad idea.
|
74
|
+
#
|
75
|
+
# Caching in ActiveSP at the moment is very aggressive. What this means that everything
|
76
|
+
# you ever accessed will be cached. You can override the cache for a particular object
|
77
|
+
# by calling {Base#reload} on it. One advantage of this caching strategy is that every time
|
78
|
+
# you access an object in SharePoint, it is guaranteed to be the same object in Ruby as
|
79
|
+
# well, irrespective of how you obtained a reference to that object. This eliminates a
|
80
|
+
# whole slew of issues, but you need to be aware of this.
|
81
|
+
#
|
82
|
+
# This method expects a block to which a new cache object is passed. The idea is that
|
83
|
+
# you store this cache object in a place that reflects the scope of your cache. If you
|
84
|
+
# already had a cache object stored for you current scope, you do not do anything with
|
85
|
+
# the cache object. The cache object that the block returns is the cache that will be used.
|
86
|
+
# Note that the block is called everytime ActiveSP needs the cache, so make it as
|
87
|
+
# efficient as possible. The example below illustrates how you can use the ||= operator
|
88
|
+
# for this to get a thread local cache.
|
89
|
+
#
|
90
|
+
# You can use this block to return a cache of your own. A cache is only expected to have
|
91
|
+
# a lookup method to which the cache key is passed (do not assume it is an integer or a
|
92
|
+
# string because it is not) as parameter and is expected to return the value for that
|
93
|
+
# key. In case of a cache miss, the method should yield to retrieve the value, store it
|
94
|
+
# with the given key and return the value. You can use this to plug in a cache that has
|
95
|
+
# a limited size, or that uses weak references to clean up the cache. The latter suggestion
|
96
|
+
# is a lot safer than the former!
|
97
|
+
#
|
98
|
+
# @example How to configure caching strategy
|
99
|
+
# c = ActiveSP::Connection.new(:login => l, :password => p, :root => r)
|
100
|
+
# c.configure_persistent_cache { |cache| Thread.current[:sp_cache] ||= cache }
|
41
101
|
def configure_persistent_cache(&blk)
|
42
102
|
@last_persistent_cache_object = PersistentCache.new
|
43
103
|
class << self ; self ; end.send(:define_method, :persistent_cache) do
|
44
104
|
cache = blk.call(@last_persistent_cache_object)
|
45
|
-
@last_persistent_cache_object = PersistentCache.new
|
105
|
+
@last_persistent_cache_object = PersistentCache.new if cache == @last_persistent_cache_object
|
46
106
|
cache
|
47
107
|
end
|
48
108
|
end
|
data/lib/activesp/role.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 Role < Base
|
@@ -7,43 +32,59 @@ module ActiveSP
|
|
7
32
|
include Util
|
8
33
|
include InSite
|
9
34
|
|
10
|
-
attr_reader :name
|
11
|
-
|
12
35
|
persistent { |site, name, *a| [site.connection, [:role, name]] }
|
36
|
+
# @private
|
13
37
|
def initialize(site, name)
|
14
38
|
@site, @name = site, name
|
15
39
|
end
|
16
40
|
|
41
|
+
# See {Base#key}
|
42
|
+
# @return [String]
|
17
43
|
def key
|
18
44
|
encode_key("R", [@name])
|
19
45
|
end
|
20
46
|
|
47
|
+
# Returns the list of users in this role
|
48
|
+
# @return [User]
|
21
49
|
def users
|
22
50
|
call("UserGroup", "get_user_collection_from_role", "roleName" => @name).xpath("//spdir:User", NS).map do |row|
|
23
51
|
attributes = clean_attributes(row.attributes)
|
24
52
|
User.new(@site, attributes["LoginName"])
|
25
53
|
end
|
26
54
|
end
|
27
|
-
cache :users, :dup =>
|
55
|
+
cache :users, :dup => :always
|
28
56
|
|
57
|
+
# Returns the list of groups in this role
|
58
|
+
# @return [Group]
|
29
59
|
def groups
|
30
60
|
call("UserGroup", "get_group_collection_from_role", "roleName" => @name).xpath("//spdir:Group", NS).map do |row|
|
31
61
|
attributes = clean_attributes(row.attributes)
|
32
62
|
Group.new(@site, attributes["Name"])
|
33
63
|
end
|
34
64
|
end
|
35
|
-
cache :groups, :dup =>
|
65
|
+
cache :groups, :dup => :always
|
66
|
+
|
67
|
+
# Returns true. The same method is present on {Group} where it returns false. Roles and groups can generally be
|
68
|
+
# duck-typed, and this method is there for the rare case where you do need to make the distinction
|
69
|
+
# @return [Boolean]
|
70
|
+
def is_role?
|
71
|
+
true
|
72
|
+
end
|
36
73
|
|
74
|
+
# See {Base#save}
|
75
|
+
# @return [void]
|
76
|
+
def save
|
77
|
+
p untype_cast_attributes(@site, nil, internal_attribute_types, changed_attributes)
|
78
|
+
end
|
79
|
+
|
80
|
+
# @private
|
37
81
|
def to_s
|
38
82
|
"#<ActiveSP::Role name=#{@name}>"
|
39
83
|
end
|
40
84
|
|
85
|
+
# @private
|
41
86
|
alias inspect to_s
|
42
87
|
|
43
|
-
def is_role?
|
44
|
-
true
|
45
|
-
end
|
46
|
-
|
47
88
|
private
|
48
89
|
|
49
90
|
def data
|
data/lib/activesp/root.rb
CHANGED
@@ -1,5 +1,31 @@
|
|
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
|
NS = {
|
4
30
|
"sp" => "http://schemas.microsoft.com/sharepoint/soap/",
|
5
31
|
"z" => "#RowsetSchema",
|
@@ -10,34 +36,71 @@ module ActiveSP
|
|
10
36
|
|
11
37
|
extend Caching
|
12
38
|
|
39
|
+
# Returns the root site as an object of class {Site}
|
40
|
+
# @return [Site]
|
13
41
|
def root
|
14
42
|
Site.new(self, @root_url)
|
15
43
|
end
|
16
44
|
cache :root
|
17
45
|
|
46
|
+
# Returns the list of users in the system
|
47
|
+
# @return [Array<User>]
|
18
48
|
def users
|
19
49
|
root.send(:call, "UserGroup", "get_user_collection_from_site").xpath("//spdir:User", NS).map do |row|
|
20
50
|
attributes = clean_attributes(row.attributes)
|
21
51
|
User.new(root, attributes["LoginName"])
|
22
52
|
end
|
23
53
|
end
|
24
|
-
cache :users, :dup =>
|
54
|
+
cache :users, :dup => :always
|
25
55
|
|
56
|
+
# Returns the user with the given login, or nil when the user does not exist
|
57
|
+
# @param [String] login The login of the user
|
58
|
+
# @return [User, nil]
|
59
|
+
def user(login)
|
60
|
+
if user = users_by_login[login]
|
61
|
+
user
|
62
|
+
elsif data = root.send(:call, "UserGroup", "get_user_info", "userLoginName" => login).xpath("//spdir:User", NS).first
|
63
|
+
users_by_login[login] = User.new(root, login, clean_attributes(data))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the list of groups in the system
|
68
|
+
# @return [Array<Group>]
|
26
69
|
def groups
|
27
70
|
root.send(:call, "UserGroup", "get_group_collection_from_site").xpath("//spdir:Group", NS).map do |row|
|
28
71
|
attributes = clean_attributes(row.attributes)
|
29
72
|
Group.new(root, attributes["Name"])
|
30
73
|
end
|
31
74
|
end
|
32
|
-
cache :groups, :dup =>
|
75
|
+
cache :groups, :dup => :always
|
76
|
+
|
77
|
+
def group(name)
|
78
|
+
if group = groups_by_name[name]
|
79
|
+
group
|
80
|
+
end
|
81
|
+
end
|
33
82
|
|
83
|
+
# Returns the list of roles in the system
|
84
|
+
# @return [Array<Role>]
|
34
85
|
def roles
|
35
86
|
root.send(:call, "UserGroup", "get_role_collection_from_web").xpath("//spdir:Role", NS).map do |row|
|
36
87
|
attributes = clean_attributes(row.attributes)
|
37
88
|
Role.new(root, attributes["Name"])
|
38
89
|
end
|
39
90
|
end
|
40
|
-
cache :roles, :dup =>
|
91
|
+
cache :roles, :dup => :always
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def users_by_login
|
96
|
+
users.inject({}) { |h, u| h[u.login_name] = u ; h }
|
97
|
+
end
|
98
|
+
cache :users_by_login
|
99
|
+
|
100
|
+
def groups_by_name
|
101
|
+
groups.inject({}) { |h, g| h[g.Name] = g ; h }
|
102
|
+
end
|
103
|
+
cache :groups_by_name
|
41
104
|
|
42
105
|
end
|
43
106
|
|
@@ -47,6 +110,7 @@ module ActiveSP
|
|
47
110
|
|
48
111
|
end
|
49
112
|
|
113
|
+
# @private
|
50
114
|
module InSite
|
51
115
|
|
52
116
|
private
|
data/lib/activesp/site.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 Site < Base
|
@@ -6,51 +31,73 @@ module ActiveSP
|
|
6
31
|
extend PersistentCaching
|
7
32
|
include Util
|
8
33
|
|
9
|
-
|
34
|
+
# The URL of this site
|
35
|
+
# @return [String]
|
36
|
+
attr_reader :url
|
37
|
+
# @private
|
38
|
+
attr_reader :connection
|
10
39
|
|
11
40
|
persistent { |connection, url, *a| [connection, [:site, url]] }
|
41
|
+
# @private
|
12
42
|
def initialize(connection, url, depth = 0)
|
13
43
|
@connection, @url, @depth = connection, url, depth
|
14
44
|
@services = {}
|
15
45
|
end
|
16
46
|
|
47
|
+
# @private
|
17
48
|
def relative_url(url = @url)
|
18
49
|
url[@connection.root_url.rindex("/") + 1..-1]
|
19
50
|
end
|
20
51
|
|
52
|
+
# Returns the containing site, or nil if this is the root site
|
53
|
+
# @return [Site]
|
21
54
|
def supersite
|
22
|
-
|
23
|
-
Site.new(@connection, File.dirname(@url), @depth - 1)
|
55
|
+
unless is_root_site?
|
56
|
+
Site.new(@connection, ::File.dirname(@url), @depth - 1)
|
24
57
|
end
|
25
58
|
end
|
26
59
|
cache :supersite
|
27
60
|
|
61
|
+
# Returns the root site, or this site if it is the root site
|
62
|
+
# @return [Site]
|
28
63
|
def rootsite
|
29
|
-
|
64
|
+
is_root_site? ? self : supersite.rootsite
|
30
65
|
end
|
31
66
|
cache :rootsite
|
32
67
|
|
68
|
+
# Returns true if this site is the root site
|
69
|
+
# @return [Boolean]
|
33
70
|
def is_root_site?
|
34
71
|
@depth == 0
|
35
72
|
end
|
36
73
|
|
37
|
-
|
74
|
+
# See {Base#key}
|
75
|
+
# @return [String]
|
76
|
+
def key # This documentation is not ideal. The ideal doesn't work out of the box
|
38
77
|
encode_key("S", [@url[@connection.root_url.length + 1..-1], @depth])
|
39
78
|
end
|
40
79
|
|
80
|
+
# Returns the list of sites below this site. Does not recurse
|
81
|
+
# @return [Array<List>]
|
41
82
|
def sites
|
42
83
|
result = call("Webs", "get_web_collection")
|
43
84
|
result.xpath("//sp:Web", NS).map { |web| Site.new(connection, web["Url"].to_s, @depth + 1) }
|
44
85
|
end
|
45
|
-
cache :sites, :dup =>
|
86
|
+
cache :sites, :dup => :always
|
46
87
|
|
88
|
+
# Returns the site with the given name. This name is what appears in the URL as name and is immutable. Return nil
|
89
|
+
# if such a site does not exist
|
90
|
+
# @param [String] name The name if the site
|
91
|
+
# @return [Site]
|
47
92
|
def site(name)
|
48
|
-
result = call("Webs", "get_web", "webUrl" => File.join(@url, name))
|
93
|
+
result = call("Webs", "get_web", "webUrl" => ::File.join(@url, name))
|
49
94
|
Site.new(connection, result.xpath("//sp:Web", NS).first["Url"].to_s, @depth + 1)
|
50
95
|
rescue Savon::SOAPFault
|
51
96
|
nil
|
52
97
|
end
|
53
98
|
|
99
|
+
# Returns the list if lists in this sute. Does not recurse
|
100
|
+
# @return [Array<List>]
|
54
101
|
def lists
|
55
102
|
result1 = call("Lists", "get_list_collection")
|
56
103
|
result2 = call("SiteData", "get_list_collection")
|
@@ -66,28 +113,42 @@ module ActiveSP
|
|
66
113
|
List.new(self, list["ID"].to_s, list["Title"].to_s, clean_attributes(list.attributes), result2_by_id[list["ID"].to_s])
|
67
114
|
end
|
68
115
|
end
|
69
|
-
cache :lists, :dup =>
|
116
|
+
cache :lists, :dup => :always
|
70
117
|
|
118
|
+
# Returns the list with the given name. The name is what appears in the URL as name and is immutable. Returns nil
|
119
|
+
# if such a list does not exist
|
120
|
+
# @param [String] name The name of the list
|
121
|
+
# @return [List]
|
71
122
|
def list(name)
|
72
|
-
lists.find { |list| File.basename(list.
|
123
|
+
lists.find { |list| ::File.basename(list.url) == name }
|
73
124
|
end
|
74
125
|
|
126
|
+
# Returns the site or list with the given name, or nil if it does not exist
|
127
|
+
# @param [String] name The name of the site or list
|
128
|
+
# @return [Site, List]
|
75
129
|
def /(name)
|
76
130
|
list(name) || site(name)
|
77
131
|
end
|
78
132
|
|
133
|
+
# Returns the list of content types defined for this site. These include the content types defined on
|
134
|
+
# containing sites as they are automatically inherited
|
135
|
+
# @return [Array<ContentType>]
|
79
136
|
def content_types
|
80
137
|
result = call("Webs", "get_content_types", "listName" => @id)
|
81
138
|
result.xpath("//sp:ContentType", NS).map do |content_type|
|
82
139
|
supersite && supersite.content_type(content_type["ID"]) || ContentType.new(self, nil, content_type["ID"], content_type["Name"], content_type["Description"], content_type["Version"], content_type["Group"])
|
83
140
|
end
|
84
141
|
end
|
85
|
-
cache :content_types, :dup =>
|
142
|
+
cache :content_types, :dup => :always
|
86
143
|
|
144
|
+
# @private
|
87
145
|
def content_type(id)
|
88
146
|
content_types.find { |t| t.id == id }
|
89
147
|
end
|
90
148
|
|
149
|
+
# Returns the permission set associated with this site. This returns the permission set of
|
150
|
+
# the containing site if it does not have a permission set of its own
|
151
|
+
# @return [PermissionSet]
|
91
152
|
def permission_set
|
92
153
|
if attributes["InheritedSecurity"]
|
93
154
|
supersite.permission_set
|
@@ -97,27 +158,47 @@ module ActiveSP
|
|
97
158
|
end
|
98
159
|
cache :permission_set
|
99
160
|
|
161
|
+
# Returns the list of fields for this site. This includes fields inherited from containing sites
|
162
|
+
# @return [Array<Field>]
|
100
163
|
def fields
|
101
164
|
call("Webs", "get_columns").xpath("//sp:Field", NS).map do |field|
|
102
165
|
attributes = clean_attributes(field.attributes)
|
103
166
|
supersite && supersite.field(attributes["ID"].downcase) || Field.new(self, attributes["ID"].downcase, attributes["StaticName"], attributes["Type"], nil, attributes) if attributes["ID"] && attributes["StaticName"]
|
104
167
|
end.compact
|
105
168
|
end
|
106
|
-
cache :fields, :dup =>
|
169
|
+
cache :fields, :dup => :always
|
107
170
|
|
171
|
+
# Returns the result of {Site#fields} hashed by name
|
172
|
+
# @return [Hash{String => Field}]
|
108
173
|
def fields_by_name
|
109
174
|
fields.inject({}) { |h, f| h[f.attributes["StaticName"]] = f ; h }
|
110
175
|
end
|
111
|
-
cache :fields_by_name, :dup =>
|
176
|
+
cache :fields_by_name, :dup => :always
|
112
177
|
|
178
|
+
# @private
|
113
179
|
def field(id)
|
114
180
|
fields.find { |f| f.ID == id }
|
115
181
|
end
|
116
182
|
|
183
|
+
# See {Base#save}
|
184
|
+
# @return [void]
|
185
|
+
def save
|
186
|
+
p untype_cast_attributes(self, nil, internal_attribute_types, changed_attributes)
|
187
|
+
end
|
188
|
+
|
189
|
+
def accessible?
|
190
|
+
data
|
191
|
+
true
|
192
|
+
rescue Savon::HTTPError
|
193
|
+
false
|
194
|
+
end
|
195
|
+
|
196
|
+
# @private
|
117
197
|
def to_s
|
118
198
|
"#<ActiveSP::Site url=#{@url}>"
|
119
199
|
end
|
120
200
|
|
201
|
+
# @private
|
121
202
|
alias inspect to_s
|
122
203
|
|
123
204
|
private
|
@@ -136,17 +217,25 @@ module ActiveSP
|
|
136
217
|
end
|
137
218
|
|
138
219
|
def data
|
220
|
+
# Looks like you can't call this as a non-admin. To investigate further
|
139
221
|
call("SiteData", "get_web")
|
222
|
+
rescue Savon::HTTPError
|
223
|
+
# This can fail when you don't have access to this site
|
224
|
+
call("Webs", "get_web", "webUrl" => ".")
|
140
225
|
end
|
141
226
|
cache :data
|
142
227
|
|
143
228
|
def attributes_before_type_cast
|
144
|
-
element = data.xpath("//sp:sWebMetadata", NS).first
|
145
|
-
|
146
|
-
|
147
|
-
|
229
|
+
if element = data.xpath("//sp:sWebMetadata", NS).first
|
230
|
+
result = {}
|
231
|
+
element.children.each do |ch|
|
232
|
+
result[ch.name] = ch.inner_text
|
233
|
+
end
|
234
|
+
result
|
235
|
+
else
|
236
|
+
element = data.xpath("//sp:Web", NS).first
|
237
|
+
clean_attributes(element.attributes)
|
148
238
|
end
|
149
|
-
result
|
150
239
|
end
|
151
240
|
cache :attributes_before_type_cast
|
152
241
|
|
@@ -176,19 +265,20 @@ module ActiveSP
|
|
176
265
|
end
|
177
266
|
|
178
267
|
def permissions
|
179
|
-
result = call("Permissions", "get_permission_collection", "objectName" => File.basename(@url), "objectType" => "Web")
|
268
|
+
result = call("Permissions", "get_permission_collection", "objectName" => ::File.basename(@url), "objectType" => "Web")
|
180
269
|
result.xpath("//spdir:Permission", NS).map do |row|
|
181
270
|
accessor = row["MemberIsUser"][/true/i] ? User.new(rootsite, row["UserLogin"]) : Group.new(rootsite, row["GroupName"])
|
182
271
|
{ :mask => Integer(row["Mask"]), :accessor => accessor }
|
183
272
|
end
|
184
273
|
end
|
185
|
-
cache :permissions, :dup =>
|
274
|
+
cache :permissions, :dup => :always
|
186
275
|
|
276
|
+
# @private
|
187
277
|
class Service
|
188
278
|
|
189
279
|
def initialize(site, name)
|
190
280
|
@site, @name = site, name
|
191
|
-
@client = Savon::Client.new(File.join(site.url, "_vti_bin", name + ".asmx?WSDL"))
|
281
|
+
@client = Savon::Client.new(::File.join(URI.escape(site.url), "_vti_bin", name + ".asmx?WSDL"))
|
192
282
|
@client.request.ntlm_auth(site.connection.login, site.connection.password) if site.connection.login
|
193
283
|
end
|
194
284
|
|