sharepoint-ruby 0.1.1 → 0.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.
- checksums.yaml +4 -4
- data/README.md +167 -0
- data/lib/sharepoint-data.rb +5 -0
- data/lib/sharepoint-errors.rb +34 -0
- data/lib/sharepoint-files.rb +26 -0
- data/lib/sharepoint-lists.rb +1 -1
- data/lib/sharepoint-ruby.rb +9 -20
- data/lib/sharepoint-session.rb +5 -6
- data/lib/sharepoint-types.rb +1 -12
- metadata +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06a548cde4c7aede93cbc0f46fd90e5343faff5f64e4d18bb877cf4ce4bdbf7e
|
4
|
+
data.tar.gz: 5b34f39ca74c0583f3dc5d509639f1dbe73972477aa2a259e6a741b7a0cbd649
|
5
5
|
SHA512:
|
6
|
-
metadata.gz: '
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0708c3ab5cf9238fd35617ebf07d634ef7ad0c766efec37f47ed4050938fc4aaecddc793b1a9ff4ce5e2ccc32cc0c829e650ad87ecf73abe3b5b1b6e4c857446'
|
7
|
+
data.tar.gz: ef28ea0e00baee2d803a30a36fedbb8b48e03e637972033e002db56fd401f8af33214bc30fb525275f41cb0503e8e3f5833e06bb6bef3cf46df21c94b7dcfdfb
|
data/README.md
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
sharepoint-ruby
|
2
|
+
===============
|
3
|
+
A ruby gem that maps Sharepoint's REST API in a simple and accessible fashion.
|
4
|
+
|
5
|
+
How to use
|
6
|
+
===============
|
7
|
+
First, you'll have to initialize a sharepoint site and open a session in order to start making requests to the REST API:
|
8
|
+
|
9
|
+
```Ruby
|
10
|
+
require 'sharepoint-ruby'
|
11
|
+
|
12
|
+
site = Sharepoint::Site.new 'mysite.sharepoint.com', 'server-relative-site-url'
|
13
|
+
site.session.authenticate 'mylogin', 'mypassword'
|
14
|
+
|
15
|
+
blog = Sharepoint::Site.new 'mytenant.sharepoint.com', 'sites/blog'
|
16
|
+
blog.session.authenticate 'user', 'pwd'
|
17
|
+
lists = blog.lists
|
18
|
+
for l in lists
|
19
|
+
puts l.title
|
20
|
+
end
|
21
|
+
```
|
22
|
+
|
23
|
+
Note that site.session.authenticate might throw an exception if the authentication doesn't go well (wrong urls, STS unavailable, or wrong login/password).
|
24
|
+
The exceptions might be of type ConnectionToStsFailed, AuthenticationFailed, ConnexionToSharepointFailed, UnknownAuthenticationError.
|
25
|
+
|
26
|
+
### Connecting to your own STS
|
27
|
+
By default, sharepoint-ruby uses Microsoft's STS (https://login.microsoftonline.com/extSTS.srf), which works for Sharepoint Online. You may use your own STS by using the optional third parameter of Sharepoint::Site.new:
|
28
|
+
|
29
|
+
```Ruby
|
30
|
+
site = Sharepoint::Site.new 'mysite.sharepoint.com', 'site-name'
|
31
|
+
site.session.authenticate 'username', 'password', 'https://sts_url.com/extSTS.srf'
|
32
|
+
```
|
33
|
+
|
34
|
+
### Connecting using NTLM
|
35
|
+
You may also connect using the NTLM method. For that purpose, you'll have to overwrite the default session handler with `Sharepoint::HttpAuth::Session`.
|
36
|
+
|
37
|
+
```Ruby
|
38
|
+
require 'sharepoint-http-auth'
|
39
|
+
|
40
|
+
site = Sharepoint::Site.new 'mysite.sharepoint.com', 'site-name'
|
41
|
+
site.session = Sharepoint::HttpAuth::Session.new site
|
42
|
+
site.session.authenticate 'login', 'password'
|
43
|
+
site.protocole = 'http' # default protocole is https: don't forget to set this if you use http.
|
44
|
+
```
|
45
|
+
|
46
|
+
### Connecting using Kerberos
|
47
|
+
You may also connect using Kerberos if you're using *MIT Kerberos*.
|
48
|
+
For that purpose, you'll have to overwrite the default session handler with `Sharepoint::KerberosAuth::Session`.
|
49
|
+
|
50
|
+
```Ruby
|
51
|
+
require 'sharepoint-kerberos-auth'
|
52
|
+
|
53
|
+
site = Sharepoint::Site.new 'mysite.sharepoint.com', 'site-name'
|
54
|
+
site.session = Sharepoint::KerberosAuth::Session.new site
|
55
|
+
site.session.authenticate 'login', 'password'
|
56
|
+
site.protocole = 'http' # default protocole is https: don't forget to set this if you use http.
|
57
|
+
```
|
58
|
+
|
59
|
+
### General features
|
60
|
+
|
61
|
+
Once you're logged in, you may access the site's ressource through the site object:
|
62
|
+
```Ruby
|
63
|
+
fields = site.fields # Get all the site's fields
|
64
|
+
groups = site.groups # Get all the site's groups
|
65
|
+
users = site.users # Get all the site's users
|
66
|
+
|
67
|
+
lists = site.lists # Get all the site's list
|
68
|
+
list = site.list 'Documents' # Get a list by title
|
69
|
+
list = site.list '51925dd7-2108-481a-b1ef-4bfa4e69d48b' # Get a list by guid
|
70
|
+
views = list.views # Get all the lists views
|
71
|
+
|
72
|
+
folders = site.folders # Get all the site's folder
|
73
|
+
folder = site.folder '/SiteAssets/documents' # Get a folder by server relative path
|
74
|
+
files = folder.files # Get all the folder's files
|
75
|
+
```
|
76
|
+
|
77
|
+
### OData mapping
|
78
|
+
When Sharepoint answers with an OData object, the `site.query` method will automatically map it to the corresponding Sharepoint::Object class.
|
79
|
+
For instance, if Sharepoint answered with an OData object of type 'SP.List', `site.query` will return an instance of the Sharepoint::List class. These classes implement a getter and a setter for all the properties declared for the corresponding object in Sharepoint's 2013 Documentation.
|
80
|
+
|
81
|
+
N.B: Note that the setter only exists if the property is declared as write-accessible in the documentation.
|
82
|
+
N.B#2: Note that despite the camel casing used by Sharepoint, the getter and setter are snake cased (i.e: the CustomMasterUrl property becomes accessible through the custom_master_url getter and custom_mater_url= getter).
|
83
|
+
|
84
|
+
#### Sharepoint::Object specifics
|
85
|
+
Sharepoint::Object contains a few methods to help you handle your objects:
|
86
|
+
|
87
|
+
The `guid` method can be used to retrieve the guid of any object.
|
88
|
+
|
89
|
+
The `reload` method returns an instance of the same object from the remote sharepoint site. It may be useful if you want to be sure that your object contains the latest changes.
|
90
|
+
|
91
|
+
The `save` method will automatically compile your changes and perform the MERGE request with the Sharepoint site.
|
92
|
+
|
93
|
+
The `destroy` method will destroy the remote ressource on the Sharepoint site.
|
94
|
+
|
95
|
+
The `copy` method can duplicate an existing object. If you send it a Sharepoint::Object as a parameter, it will duplicate into the parameter. If you don't send any parameter, it will create a new object. Note that no changes happen on the sharepoint site until you've called the `save` method on the returned object.
|
96
|
+
|
97
|
+
### Deferred objects
|
98
|
+
Some of the properties of the OData object are 'deferred', which means that the property only provides a link to a ressource that you would have to get for yourself.
|
99
|
+
Not with the sharepoint-ruby gem however: the first time you try to access a deferred property, the object will on it's own go look for the corresponding remote ressource: the result will be stored for later uses, and then be returned to you.
|
100
|
+
|
101
|
+
### Modifying Sharepoint's ressources
|
102
|
+
The Sharepoint REST API provides us with methods to create, update or delete resources. In the Sharepoint::Object, these behaviours are implemented through the save and delete methods.
|
103
|
+
|
104
|
+
##### Updating objects
|
105
|
+
This piece of code will change the custom master page used by the Sharepoint site to 'oslo.master':
|
106
|
+
```Ruby
|
107
|
+
web = site.context_info # Sharepoint::Site.context_info returns the Web object for the current site (see: http://msdn.microsoft.com/en-us/library/office/dn499819(v=office.15).aspx )
|
108
|
+
web.custom_master_url = '/_catalogs/masterpage/oslo.master'
|
109
|
+
web.save
|
110
|
+
```
|
111
|
+
|
112
|
+
##### Creating objects
|
113
|
+
You may also create your own objects. This will be slightly different: we will create our own instance of a Sharepoint::List object.
|
114
|
+
Some Sharepoint objects have values that can only be set during their initialization: `sharepoint-ruby` doesn't allow you to set these values through a setter.
|
115
|
+
In the case of list, Sharepoint will require you to specify the value for the `BaseTemplate` property. This is how you would specify the default value for an attribute that isn't write-accessible:
|
116
|
+
```Ruby
|
117
|
+
list = Sharepoint::List.new site, { 'BaseTemplate' => Sharepoint::LIST_TEMPLATE_TYPE[:GenericList] }
|
118
|
+
list.title = 'My new list'
|
119
|
+
list.description = 'A list created by sharepoint-ruby'
|
120
|
+
list = list.save # At creation, the remote object created will be returned by the save method.
|
121
|
+
```
|
122
|
+
Note that the attribute's name in the constructor remains camel cased (`BaseTemplate`), though the getter for this attribute is still snake cased (`base_template`).
|
123
|
+
|
124
|
+
##### Destroying objects
|
125
|
+
Now, say you want to destroy the list you just created, this will do nicely:
|
126
|
+
```Ruby
|
127
|
+
list.destroy
|
128
|
+
```
|
129
|
+
|
130
|
+
### Parenting
|
131
|
+
In the previous paragraph, we saw how to create a Sharepoint::List object. Sharepoint lists aren't parented to any other objects: Sharepoint views however are parented to a list. If you wanted to create a view for the list we just created, you would have to specify a parent for the view:
|
132
|
+
|
133
|
+
```Ruby
|
134
|
+
view = Sharepoint::View.new site
|
135
|
+
view.title = 'My new view'
|
136
|
+
view.personal_view = false
|
137
|
+
view.parent = list # Setting the view's parent to the Sharepoint::List
|
138
|
+
view.save
|
139
|
+
```
|
140
|
+
|
141
|
+
### Collections
|
142
|
+
In sharepoint-ruby, collections are merely arrays of Sharepoint::Objects. If you wish to add an object to a colleciton, set the parent to the object providing the collection.
|
143
|
+
|
144
|
+
### List Items
|
145
|
+
Sharepoint doesn't allow the user to fetch more than 100 items per query. When your list contains more than a 100 items, you may fetch them using the `find_items` method:
|
146
|
+
|
147
|
+
```Ruby
|
148
|
+
list = site.list 'My List'
|
149
|
+
# Use the skip option to paginate
|
150
|
+
list.find_items skip: 50 # returns items from 50-150
|
151
|
+
# You may use other operators in your query, such as orderby, select, filter and top:
|
152
|
+
list.find_items skip: 100, orderby: 'Title asc'
|
153
|
+
```
|
154
|
+
|
155
|
+
### Exceptions
|
156
|
+
Inevitably, some of your requests will fail. The object sharepoint returns when an error happens is also mapped by sharepoint-ruby in the Sharepoint::SPException class.
|
157
|
+
The SPException class contains methods to inspect the query that was made to the server:
|
158
|
+
|
159
|
+
```Ruby
|
160
|
+
begin
|
161
|
+
list = site.list 'title that does not exists'
|
162
|
+
rescue Sharepoint::SPException => e
|
163
|
+
puts "Sharepoint complained about something: #{e.message}"
|
164
|
+
puts "The action that was being executed was: #{e.uri}"
|
165
|
+
puts "The request had a body: #{e.request_body}" unless e.request_body.nil?
|
166
|
+
end
|
167
|
+
```
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Sharepoint
|
2
|
+
class Error < StandardError; end
|
3
|
+
|
4
|
+
class RequestError < Error; end
|
5
|
+
class DataError < Error
|
6
|
+
def initialize data, uri = nil, body = nil
|
7
|
+
@data = data['error']
|
8
|
+
@uri = uri
|
9
|
+
@body = body
|
10
|
+
end
|
11
|
+
|
12
|
+
def lang ; @data['message']['lang'] ; end
|
13
|
+
def message ; @data['message']['value'] ; end
|
14
|
+
def code ; @data['code'] ; end
|
15
|
+
def uri ; @uri ; end
|
16
|
+
def request_body ; @body ; end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @deprecated Use DataError instead
|
20
|
+
SPException = DataError
|
21
|
+
deprecate_constant :SPException
|
22
|
+
|
23
|
+
class UnsupportedType < Error
|
24
|
+
attr_accessor :type_name
|
25
|
+
|
26
|
+
def initialize type_name
|
27
|
+
@type_name = type_name
|
28
|
+
end
|
29
|
+
|
30
|
+
def message
|
31
|
+
"unsupported type '#{@type_name}'"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/sharepoint-files.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
+
require 'sharepoint-errors'
|
1
2
|
require 'open-uri'
|
3
|
+
require 'securerandom'
|
2
4
|
|
3
5
|
module Sharepoint
|
4
6
|
class Folder < Sharepoint::Object
|
@@ -24,6 +26,12 @@ module Sharepoint
|
|
24
26
|
body = { '__metadata' => { 'type' => 'SP.Folder' }, 'ServerRelativeUrl' => name.to_s }
|
25
27
|
@site.query :post, uri, body.to_json
|
26
28
|
end
|
29
|
+
|
30
|
+
def add_file_via_streaming name, file
|
31
|
+
add_file name, nil
|
32
|
+
spo_file = file_from_name name
|
33
|
+
spo_file.upload_file_via_streaming file
|
34
|
+
end
|
27
35
|
end
|
28
36
|
|
29
37
|
class File < Sharepoint::Object
|
@@ -60,6 +68,24 @@ module Sharepoint
|
|
60
68
|
file.write content
|
61
69
|
end
|
62
70
|
end
|
71
|
+
|
72
|
+
def upload_file_via_streaming file
|
73
|
+
uuid = SecureRandom.uuid
|
74
|
+
bytes_written = 0
|
75
|
+
::File.open(file) do |fh|
|
76
|
+
while data = fh.read(10 * 1024 * 1024) do
|
77
|
+
uri = (bytes_written == 0) ? "#{__metadata['uri']}/startupload(uploadId=guid'#{uuid}')" : "#{__metadata['uri']}/continueupload(uploadId=guid'#{uuid}',fileOffset=#{bytes_written})"
|
78
|
+
result = @site.query :post, uri, data, skip_json: true
|
79
|
+
new_position = (JSON.parse(result).dig('d', 'ContinueUpload') || JSON.parse(result).dig('d', 'StartUpload')).to_i
|
80
|
+
bytes_written += data.size
|
81
|
+
if new_position != bytes_written
|
82
|
+
raise Sharepoint::Error.new("Streamed #{bytes_written} bytes data, but sharepoint reports position #{new_position}")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
uri = "#{__metadata['uri']}/finishupload(uploadId=guid'#{uuid}',fileOffset=#{bytes_written})"
|
87
|
+
result = @site.query :post, uri, nil, skip_json: true
|
88
|
+
end
|
63
89
|
end
|
64
90
|
|
65
91
|
class FileVersion < Sharepoint::Object
|
data/lib/sharepoint-lists.rb
CHANGED
@@ -113,7 +113,7 @@ module Sharepoint
|
|
113
113
|
item_id = response['d']['ID']
|
114
114
|
@site.query :get, "#{site_url}_api/#{__metadata['id']}/items(#{item_id})"
|
115
115
|
else
|
116
|
-
raise Sharepoint::
|
116
|
+
raise Sharepoint::DataError.new response, action, payload
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
data/lib/sharepoint-ruby.rb
CHANGED
@@ -1,24 +1,11 @@
|
|
1
1
|
require 'curb'
|
2
2
|
require 'json'
|
3
|
+
require 'sharepoint-errors'
|
3
4
|
require 'sharepoint-session'
|
4
5
|
require 'sharepoint-object'
|
5
6
|
require 'sharepoint-types'
|
6
7
|
|
7
8
|
module Sharepoint
|
8
|
-
class SPException < Exception
|
9
|
-
def initialize data, uri = nil, body = nil
|
10
|
-
@data = data['error']
|
11
|
-
@uri = uri
|
12
|
-
@body = body
|
13
|
-
end
|
14
|
-
|
15
|
-
def lang ; @data['message']['lang'] ; end
|
16
|
-
def message ; @data['message']['value'] ; end
|
17
|
-
def code ; @data['code'] ; end
|
18
|
-
def uri ; @uri ; end
|
19
|
-
def request_body ; @body ; end
|
20
|
-
end
|
21
|
-
|
22
9
|
class Site
|
23
10
|
attr_reader :server_url
|
24
11
|
attr_accessor :url, :protocol
|
@@ -80,14 +67,16 @@ module Sharepoint
|
|
80
67
|
@session.send :curl, curl unless not @session.methods.include? :curl
|
81
68
|
block.call curl unless block.nil?
|
82
69
|
end
|
83
|
-
|
70
|
+
if !(skip_json || (result.body_str.nil? || result.body_str.empty?))
|
84
71
|
begin
|
85
72
|
data = JSON.parse result.body_str
|
86
|
-
raise Sharepoint::
|
73
|
+
raise Sharepoint::DataError.new data, uri, body unless data['error'].nil?
|
87
74
|
make_object_from_response data
|
88
75
|
rescue JSON::ParserError => e
|
89
|
-
raise
|
76
|
+
raise Sharepoint::RequestError.new("Exception with body=#{body}, e=#{e.inspect}, #{e.backtrace.inspect}, response=#{result.body_str}")
|
90
77
|
end
|
78
|
+
elsif result.status.to_i >= 400
|
79
|
+
raise Sharepoint::RequestError.new("#{method.to_s.upcase} #{uri} responded with #{result.status}")
|
91
80
|
else
|
92
81
|
result.body_str
|
93
82
|
end
|
@@ -119,10 +108,10 @@ module Sharepoint
|
|
119
108
|
type_parts = type_name.split '.'
|
120
109
|
type_name = type_parts.pop
|
121
110
|
constant = Sharepoint
|
122
|
-
type_parts.each do |part| constant = constant.const_get
|
111
|
+
type_parts.each do |part| constant = constant.const_get(part, false) end
|
123
112
|
|
124
|
-
|
125
|
-
|
113
|
+
if constant.const_defined? type_name
|
114
|
+
klass = constant.const_get type_name rescue nil
|
126
115
|
klass.new self, data
|
127
116
|
else
|
128
117
|
Sharepoint::GenericSharepointObject.new type_name, self, data
|
data/lib/sharepoint-session.rb
CHANGED
@@ -28,12 +28,11 @@ module Sharepoint
|
|
28
28
|
end
|
29
29
|
|
30
30
|
class Session
|
31
|
-
class
|
32
|
-
class
|
33
|
-
class
|
34
|
-
class
|
35
|
-
|
36
|
-
end
|
31
|
+
class Error < Sharepoint::Error; end
|
32
|
+
class ConnexionToStsFailed < Sharepoint::Session::Error; end
|
33
|
+
class ConnexionToSharepointFailed < Sharepoint::Session::Error; end
|
34
|
+
class UnknownAuthenticationError < Sharepoint::Session::Error; end
|
35
|
+
class AuthenticationFailed < Sharepoint::Session::Error; end
|
37
36
|
|
38
37
|
attr_accessor :site
|
39
38
|
|
data/lib/sharepoint-types.rb
CHANGED
@@ -1,18 +1,6 @@
|
|
1
1
|
require 'sharepoint-object'
|
2
2
|
|
3
3
|
module Sharepoint
|
4
|
-
class UnsupportedType < ::Exception
|
5
|
-
attr_accessor :type_name
|
6
|
-
|
7
|
-
def initialize type_name
|
8
|
-
@type_name = type_name
|
9
|
-
end
|
10
|
-
|
11
|
-
def message
|
12
|
-
"unsupported type '#{@type_name}'"
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
4
|
module Type
|
17
5
|
def initialize site, data = nil
|
18
6
|
data ||= Hash.new
|
@@ -28,6 +16,7 @@ require 'sharepoint-users'
|
|
28
16
|
require 'sharepoint-lists'
|
29
17
|
require 'sharepoint-files'
|
30
18
|
require 'sharepoint-fields'
|
19
|
+
require 'sharepoint-data'
|
31
20
|
require 'date'
|
32
21
|
|
33
22
|
module Sharepoint
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sharepoint-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Martin Moro
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: curb
|
@@ -36,6 +36,9 @@ executables: []
|
|
36
36
|
extensions: []
|
37
37
|
extra_rdoc_files: []
|
38
38
|
files:
|
39
|
+
- README.md
|
40
|
+
- lib/sharepoint-data.rb
|
41
|
+
- lib/sharepoint-errors.rb
|
39
42
|
- lib/sharepoint-fields.rb
|
40
43
|
- lib/sharepoint-files.rb
|
41
44
|
- lib/sharepoint-http-auth.rb
|
@@ -53,7 +56,7 @@ homepage: https://github.com/Plaristote/sharepoint-ruby
|
|
53
56
|
licenses:
|
54
57
|
- BSD
|
55
58
|
metadata: {}
|
56
|
-
post_install_message:
|
59
|
+
post_install_message:
|
57
60
|
rdoc_options: []
|
58
61
|
require_paths:
|
59
62
|
- lib
|
@@ -68,9 +71,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
71
|
- !ruby/object:Gem::Version
|
69
72
|
version: '0'
|
70
73
|
requirements: []
|
71
|
-
rubyforge_project:
|
74
|
+
rubyforge_project:
|
72
75
|
rubygems_version: 2.7.9
|
73
|
-
signing_key:
|
76
|
+
signing_key:
|
74
77
|
specification_version: 4
|
75
78
|
summary: sharepoint client
|
76
79
|
test_files: []
|