sharepoint-ruby 0.0.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 +7 -0
- data/lib/sharepoint-fields.rb +126 -0
- data/lib/sharepoint-files.rb +69 -0
- data/lib/sharepoint-http-auth.rb +30 -0
- data/lib/sharepoint-lists.rb +235 -0
- data/lib/sharepoint-object.rb +179 -0
- data/lib/sharepoint-properties.rb +96 -0
- data/lib/sharepoint-ruby.rb +131 -0
- data/lib/sharepoint-session.rb +92 -0
- data/lib/sharepoint-stringutils.rb +37 -0
- data/lib/sharepoint-types.rb +83 -0
- data/lib/sharepoint-users.rb +36 -0
- data/lib/soap/authenticate.xml.erb +28 -0
- metadata +75 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ae2fa825b6ae80d590550ff62b460e1dadcf48eb
|
4
|
+
data.tar.gz: 929e567c7977f3da76dfb0111578b422f195f5a1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 738befa9bedaf7032b6d3e7f00bc01fcd3145d16d4e44c35f18f38b86ab15267405b14ac1bd7f19573a481a66ec96ca21b1b62266c81ea47355422af6a5da343
|
7
|
+
data.tar.gz: f869e68e7d377126d05651a06022d23c02660cfd132d192306472f65e6fa21c63050e1993250018daa8a75f5a180e5c302820778b51cc8c61ff5ca9b94ced807
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Sharepoint
|
2
|
+
class Field < Sharepoint::Object
|
3
|
+
include Sharepoint::Type
|
4
|
+
sharepoint_resource
|
5
|
+
belongs_to :list
|
6
|
+
|
7
|
+
field 'DefaultValue'
|
8
|
+
field 'Description'
|
9
|
+
field 'Direction'
|
10
|
+
field 'EnforceUniqueValues'
|
11
|
+
field 'FieldTypeKind'
|
12
|
+
field 'Group'
|
13
|
+
field 'Hidden'
|
14
|
+
field 'Indexed'
|
15
|
+
field 'JSLink'
|
16
|
+
field 'ReadOnlyField'
|
17
|
+
field 'Required'
|
18
|
+
field 'SchemaXml'
|
19
|
+
field 'Scope'
|
20
|
+
field 'Sealed'
|
21
|
+
field 'Sortable'
|
22
|
+
field 'StaticName'
|
23
|
+
field 'Title'
|
24
|
+
field 'TypeAsString'
|
25
|
+
#field 'ValidationFormula'
|
26
|
+
#field 'ValidationMessage'
|
27
|
+
end
|
28
|
+
|
29
|
+
module Taxonomy
|
30
|
+
class TaxonomyField < Field
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class FieldCalculated < Field
|
35
|
+
field 'DateFormat'
|
36
|
+
field 'Formula'
|
37
|
+
field 'OutputType'
|
38
|
+
end
|
39
|
+
|
40
|
+
class FieldComputed < Field
|
41
|
+
field 'EnableLookup'
|
42
|
+
end
|
43
|
+
|
44
|
+
class FieldDateTime < Field
|
45
|
+
field 'DateTimeCalendarType'
|
46
|
+
field 'DisplayFormat'
|
47
|
+
field 'FriendlyDisplayFormat'
|
48
|
+
end
|
49
|
+
|
50
|
+
class FieldGeolocation < Field
|
51
|
+
end
|
52
|
+
|
53
|
+
class FieldGuid < Field
|
54
|
+
end
|
55
|
+
|
56
|
+
class FieldLookup < Field
|
57
|
+
field 'AllowMultipleValues'
|
58
|
+
field 'IsRelationship'
|
59
|
+
field 'LookUpField'
|
60
|
+
field 'LookUpList'
|
61
|
+
field 'LookUpWebId'
|
62
|
+
field 'PrimaryFieldId'
|
63
|
+
field 'RelationshipDeleteBehavior'
|
64
|
+
|
65
|
+
def create_uri
|
66
|
+
unless parent.nil?
|
67
|
+
parent.__metadata['uri'] + '/fields/addfield'
|
68
|
+
else
|
69
|
+
'fields/addfield'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def create
|
74
|
+
@site.query :post, create_uri, { parameters: @data }.to_json
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class FieldUser < FieldLookup
|
79
|
+
field 'AllowDisplay'
|
80
|
+
field 'Presence'
|
81
|
+
field 'SelectionGroup'
|
82
|
+
field 'SelectionMode'
|
83
|
+
end
|
84
|
+
|
85
|
+
class FieldMultiChoice < Field
|
86
|
+
field 'Choices'
|
87
|
+
field 'FillInChoice'
|
88
|
+
end
|
89
|
+
|
90
|
+
class FieldChoice < Field
|
91
|
+
field 'EditFormat'
|
92
|
+
end
|
93
|
+
|
94
|
+
class FieldRatingScale < Field
|
95
|
+
field 'GridEndNumber'
|
96
|
+
field 'GridNAOptionText'
|
97
|
+
field 'GridStartNumber'
|
98
|
+
field 'GridTextRangeAverage'
|
99
|
+
field 'GridTextRangeHigh'
|
100
|
+
field 'GridTextRangeLow'
|
101
|
+
end
|
102
|
+
|
103
|
+
class FieldMultiLineText < Field
|
104
|
+
field 'AllowHyperlink'
|
105
|
+
field 'AppendOnly'
|
106
|
+
field 'NumberOfLines'
|
107
|
+
field 'RestrictedMode'
|
108
|
+
field 'RichText'
|
109
|
+
end
|
110
|
+
|
111
|
+
class FieldNumber < Field
|
112
|
+
field 'MaximumValue'
|
113
|
+
field 'MinimumValue'
|
114
|
+
end
|
115
|
+
|
116
|
+
class FieldCurrency < FieldNumber
|
117
|
+
field 'CurrencyLocaleId'
|
118
|
+
end
|
119
|
+
|
120
|
+
class FieldText < Field
|
121
|
+
field 'MaxLength'
|
122
|
+
end
|
123
|
+
|
124
|
+
class FieldUrl < Field
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
module Sharepoint
|
4
|
+
class Folder < Sharepoint::Object
|
5
|
+
include Sharepoint::Type
|
6
|
+
sharepoint_resource get_from_name: 'GetFolderByServerRelativeUrl'
|
7
|
+
|
8
|
+
field 'WelcomePage'
|
9
|
+
field 'UniqueContentTypeOrder'
|
10
|
+
|
11
|
+
method :recycle
|
12
|
+
|
13
|
+
def file_from_name name
|
14
|
+
@site.query :get, "#{__metadata['uri']}/files/getbyurl('#{URI::encode(name.to_s)}')"
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_file name, content
|
18
|
+
uri = "#{__metadata['uri']}/files/add(overwrite=true,url='#{URI::encode(name.to_s)}')"
|
19
|
+
@site.query :post, uri, content
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_folder name
|
23
|
+
uri = "#{__metadata['uri']}/folders"
|
24
|
+
body = { '__metadata' => { 'type' => 'SP.Folder' }, 'ServerRelativeUrl' => name.to_s }
|
25
|
+
@site.query :post, uri, body.to_json
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class File < Sharepoint::Object
|
30
|
+
include Sharepoint::Type
|
31
|
+
belongs_to :folder
|
32
|
+
sharepoint_resource getter: 'GetFileByServerRelativeUrl', no_root_collection: true
|
33
|
+
|
34
|
+
method :approve, default_params: ({ comment: '' })
|
35
|
+
method :deny, default_params: ({ comment: '' })
|
36
|
+
method :checkin, default_params: ({ comment: '', checkintype: 0 })
|
37
|
+
method :checkout
|
38
|
+
method :undo_checkout
|
39
|
+
method :copy_to, default_params: ({ overwrite: true })
|
40
|
+
method :move_to, default_params: ({ flags: 9 })
|
41
|
+
method :get_limited_webpart_manager, default_params: ({ scope: 0 }), http_method: :get
|
42
|
+
method :download, endpoint: '$value', http_method: :get, skip_json: true
|
43
|
+
method :upload, endpoint: '$value', http_method: :put
|
44
|
+
method :publish, default_params: ({ comment: '' })
|
45
|
+
method :unpublish, default_params: ({ comment: '' })
|
46
|
+
method :recycle
|
47
|
+
|
48
|
+
def upload_from_file filename
|
49
|
+
content = String.new
|
50
|
+
::File.open filename, 'rb' do |file|
|
51
|
+
line = nil
|
52
|
+
content += line while line = file.gets
|
53
|
+
end
|
54
|
+
upload content
|
55
|
+
end
|
56
|
+
|
57
|
+
def download_to_file filename
|
58
|
+
content = download
|
59
|
+
::File.open filename, "w:#{content.encoding.name}" do |file|
|
60
|
+
file.write content
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class FileVersion < Sharepoint::Object
|
66
|
+
include Sharepoint::Type
|
67
|
+
belongs_to :file
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'curb'
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
module Sharepoint
|
5
|
+
module HttpAuth
|
6
|
+
class Session
|
7
|
+
attr_accessor :site
|
8
|
+
attr_reader :user, :password
|
9
|
+
|
10
|
+
def initialize site
|
11
|
+
@site = site
|
12
|
+
end
|
13
|
+
|
14
|
+
def authenticate user, password
|
15
|
+
@user = user
|
16
|
+
@password = password
|
17
|
+
end
|
18
|
+
|
19
|
+
def cookie
|
20
|
+
String.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def curl curb
|
24
|
+
curb.http_auth_types = :ntlm
|
25
|
+
curb.username = @user
|
26
|
+
curb.password = @password
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
module Sharepoint
|
2
|
+
LIST_TEMPLATE_TYPE = {
|
3
|
+
InvalidType: -1,
|
4
|
+
NoListTemplate: 0,
|
5
|
+
GenericList: 100,
|
6
|
+
DocumentLibrary: 101,
|
7
|
+
Survey: 102,
|
8
|
+
Links: 103,
|
9
|
+
Announcements: 104,
|
10
|
+
Contacts: 105,
|
11
|
+
Events: 106,
|
12
|
+
Tasks: 107,
|
13
|
+
DiscussionBoard: 108,
|
14
|
+
PictureLibrary: 109,
|
15
|
+
DataSources: 110,
|
16
|
+
UserInformation: 112,
|
17
|
+
WebPartCatalog: 113,
|
18
|
+
ListTemplateCatalog: 114,
|
19
|
+
XMLForm: 115,
|
20
|
+
MasterPageCatalog: 116,
|
21
|
+
NoCodeWorkflows: 117,
|
22
|
+
WorkflowProcess: 118,
|
23
|
+
WebPageLibrary: 119,
|
24
|
+
CustomGrid: 120,
|
25
|
+
SolutionCatalog: 121,
|
26
|
+
NoCodePublic: 122,
|
27
|
+
ThemeCatalog: 123,
|
28
|
+
DesignCatalog: 124,
|
29
|
+
AppDataCatalog: 125,
|
30
|
+
DataConnectionLibrary: 130,
|
31
|
+
WorkflowHistory: 140,
|
32
|
+
GanttTask: 150,
|
33
|
+
HelpLibrary: 151,
|
34
|
+
AccessRequest: 160,
|
35
|
+
TasksWithTimelineAndHierarchy: 171,
|
36
|
+
MaintenanceLogs: 175,
|
37
|
+
Meetings: 200,
|
38
|
+
Agenda: 201,
|
39
|
+
MeetingUser: 202,
|
40
|
+
Decision: 204,
|
41
|
+
MeetingObjective: 207,
|
42
|
+
TextBox: 210,
|
43
|
+
ThingsToBring: 211,
|
44
|
+
HomePageLibrary: 212,
|
45
|
+
Posts: 301,
|
46
|
+
Comments: 302,
|
47
|
+
Categories: 303,
|
48
|
+
Facility: 402,
|
49
|
+
Whereabouts: 403,
|
50
|
+
CallTrack: 404,
|
51
|
+
Circulation: 405,
|
52
|
+
Timecard: 420,
|
53
|
+
Hollidays: 421,
|
54
|
+
IMEDic: 499,
|
55
|
+
ExternalList: 600,
|
56
|
+
MySiteDocumentLibrary: 700,
|
57
|
+
IssueTracking: 1100,
|
58
|
+
AdminTasks: 1200,
|
59
|
+
HealthRules: 1220,
|
60
|
+
HealthReports: 1221,
|
61
|
+
DeveloperSiteDraftApps: 1230,
|
62
|
+
MicroFeed: 544 # Is undefined, but used by Sharepoint Online
|
63
|
+
}
|
64
|
+
|
65
|
+
module VtiBin
|
66
|
+
def self.translate_field_names input
|
67
|
+
return input unless defined? VtiDisplayNameDictionary
|
68
|
+
hash = Hash.new
|
69
|
+
input.keys.each do |key|
|
70
|
+
if VtiDisplayNameDictionary.keys.include? key
|
71
|
+
hash[VtiDisplayNameDictionary[key]] = input[key]
|
72
|
+
else
|
73
|
+
hash[key] = input[key]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
hash
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class List < Sharepoint::Object
|
81
|
+
include Sharepoint::Type
|
82
|
+
sharepoint_resource get_from_name: 'lists/getbytitle'
|
83
|
+
|
84
|
+
def find_items options = {}
|
85
|
+
@site.query :get, (make_item_filter options)
|
86
|
+
end
|
87
|
+
|
88
|
+
def item_count
|
89
|
+
@site.query :get, "#{__metadata['id']}/ItemCount"
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_item attributes
|
93
|
+
attributes['__metadata'] ||= Hash.new
|
94
|
+
attributes['__metadata']['type'] ||= list_item_entity_type_full_name
|
95
|
+
@site.query :post, item_uri, attributes.to_json
|
96
|
+
end
|
97
|
+
|
98
|
+
def add_folder path, attributes
|
99
|
+
path = path.gsub(/\/*$/, '') # remove slashes at the end of the path
|
100
|
+
site_url = "#{@site.protocole}://#{@site.server_url}/"
|
101
|
+
action = "#{site_url}_vti_bin/listdata.svc/#{self.title}"
|
102
|
+
path = root_folder.server_relative_url + '/' + path
|
103
|
+
attributes['ContentTypeID'] ||= '0x01200059042D1A09191046851FA83D5B89816A'
|
104
|
+
attributes['Path'] ||= path
|
105
|
+
payload = VtiBin.translate_field_names(attributes).to_json
|
106
|
+
# Create the item using _vti_bin api
|
107
|
+
response = @site.query :post, action, payload, true do |curl|
|
108
|
+
curl.headers['Slug'] = "#{path}/#{attributes['Title']}|0x0120"
|
109
|
+
end
|
110
|
+
response = JSON.parse response
|
111
|
+
unless response['d'].nil?
|
112
|
+
# Fetch the item we just created using the REST api
|
113
|
+
item_id = response['d']['ID']
|
114
|
+
@site.query :get, "#{site_url}_api/#{__metadata['id']}/items(#{item_id})"
|
115
|
+
else
|
116
|
+
raise Sharepoint::SPException.new response, action, payload
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
field 'BaseTemplate', access: [ :read, :initialize ], default: LIST_TEMPLATE_TYPE[:GenericList]
|
121
|
+
field 'ContentTypesEnabled', default: true
|
122
|
+
field 'DefaultContentApprovalWorkflowId'
|
123
|
+
field 'DefaultDisplayFormUrl'
|
124
|
+
field 'DefaultEditFormUrl'
|
125
|
+
field 'DefaultNewFormUrl'
|
126
|
+
field 'Description'
|
127
|
+
field 'Direction'
|
128
|
+
field 'DocumentTemplateUrl'
|
129
|
+
field 'DraftVersionVisibility', default: 1
|
130
|
+
field 'EnableAttachments', default: false
|
131
|
+
field 'EnableFolderCreation', default: true
|
132
|
+
field 'EnableMinorVersions', default: true
|
133
|
+
field 'EnableModeration', default: true
|
134
|
+
field 'EnableVersioning', default: true
|
135
|
+
field 'ForceCheckout', default: false
|
136
|
+
field 'Hidden', default: false
|
137
|
+
field 'IrmEnabled', default: false
|
138
|
+
field 'IrmExpire', default: false
|
139
|
+
field 'IrmReject', default: false
|
140
|
+
field 'IsApplicationList', default: false
|
141
|
+
field 'MultipleDataList', default: false
|
142
|
+
field 'NoCrawl', default: false
|
143
|
+
field 'OnQuickLaunch', default: false
|
144
|
+
field 'Title'
|
145
|
+
field 'ValidationFormula'
|
146
|
+
field 'ValidationMessage'
|
147
|
+
|
148
|
+
private
|
149
|
+
def item_uri
|
150
|
+
url = @data['Items']['__deferred']
|
151
|
+
url = url['uri'] if url.class != String
|
152
|
+
url
|
153
|
+
end
|
154
|
+
|
155
|
+
def make_item_filter options = {}
|
156
|
+
url = item_uri
|
157
|
+
has_options = false
|
158
|
+
options.each do |key,value|
|
159
|
+
url += if has_options then '&' else '?' end
|
160
|
+
url += "$#{key}=#{URI::encode value.to_s}"
|
161
|
+
has_options = true
|
162
|
+
end
|
163
|
+
url
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class ListItem < Sharepoint::Object
|
168
|
+
include Sharepoint::Type
|
169
|
+
belongs_to :list
|
170
|
+
|
171
|
+
method :break_role_inheritance, default_params: ({ copyroleassignements: true })
|
172
|
+
method :recycle
|
173
|
+
method :reset_role_inheritance
|
174
|
+
method :validate_update_item_list
|
175
|
+
end
|
176
|
+
|
177
|
+
class View < Sharepoint::Object
|
178
|
+
include Sharepoint::Type
|
179
|
+
belongs_to :list
|
180
|
+
|
181
|
+
field 'Aggregations'
|
182
|
+
field 'AggregationsStatus'
|
183
|
+
field 'ContentTypeId'
|
184
|
+
field 'DefaultView'
|
185
|
+
field 'DefaultViewForContentType'
|
186
|
+
field 'EditorModified'
|
187
|
+
field 'Formats'
|
188
|
+
field 'Hidden'
|
189
|
+
field 'IncludeRootFolder'
|
190
|
+
#field 'JsLink'
|
191
|
+
field 'ListViewXml'
|
192
|
+
field 'Method'
|
193
|
+
field 'MobileDefaultView'
|
194
|
+
field 'MobileView'
|
195
|
+
field 'Paged'
|
196
|
+
field 'RowLimit'
|
197
|
+
field 'Scope'
|
198
|
+
field 'Title'
|
199
|
+
field 'Toolbar'
|
200
|
+
field 'ViewData'
|
201
|
+
field 'ViewJoins'
|
202
|
+
field 'ViewProjectedFields'
|
203
|
+
field 'ViewQuery'
|
204
|
+
|
205
|
+
method :break_role_inheritance, default_params: ({ copyroleassignements: true })
|
206
|
+
method :recycle
|
207
|
+
method :render_list_form_data
|
208
|
+
method :reserve_list_item_id
|
209
|
+
end
|
210
|
+
|
211
|
+
class ViewFieldCollection < Sharepoint::Object
|
212
|
+
include Sharepoint::Type
|
213
|
+
sharepoint_resource
|
214
|
+
belongs_to :view
|
215
|
+
|
216
|
+
def add_view_field name
|
217
|
+
@site.query :post, "#{__metadata['uri']}/addviewfield('#{URI.encode name}')"
|
218
|
+
end
|
219
|
+
|
220
|
+
def move_view_field_to name, index
|
221
|
+
@site.query :post, "#{__metadata['uri']}/moveviewfieldto", {
|
222
|
+
field: name,
|
223
|
+
index: index
|
224
|
+
}.to_json
|
225
|
+
end
|
226
|
+
|
227
|
+
def remove_all_view_fields
|
228
|
+
@site.query :post, "#{__metadata['uri']}/removeallviewfields"
|
229
|
+
end
|
230
|
+
|
231
|
+
def remove_view_field name
|
232
|
+
@site.query :post, "#{__metadata['uri']}/removeviewfield('#{URI.encode name}')"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'sharepoint-properties'
|
2
|
+
require 'sharepoint-stringutils'
|
3
|
+
|
4
|
+
module Sharepoint
|
5
|
+
class Site
|
6
|
+
end
|
7
|
+
|
8
|
+
class Object < Sharepoint::ObjectProperties
|
9
|
+
class << self
|
10
|
+
attr_accessor :fields
|
11
|
+
|
12
|
+
def fields
|
13
|
+
@fields ||= []
|
14
|
+
if self.superclass != Sharepoint::Object
|
15
|
+
self.superclass.fields | @fields
|
16
|
+
else
|
17
|
+
@fields
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def field name, options = {}
|
24
|
+
options[:access] ||= [ :read, :write ]
|
25
|
+
@fields ||= []
|
26
|
+
@fields << { name: name, access: options[:access], default: options[:default] }
|
27
|
+
end
|
28
|
+
|
29
|
+
def method name, method_params = {}
|
30
|
+
method_params[:http_method] ||= :post
|
31
|
+
method_params[:endpoint] ||= name.to_s.camelize
|
32
|
+
method_params[:default_params] ||= Hash.new
|
33
|
+
define_method name, ->(params = Hash.new) do
|
34
|
+
action = "#{__metadata['uri']}/#{method_params[:endpoint]}"
|
35
|
+
body = nil
|
36
|
+
# Set default parameters
|
37
|
+
(method_params[:default_params].each do |key,value|
|
38
|
+
params[key] == value if params[key].nil?
|
39
|
+
end)
|
40
|
+
if (method_params[:http_method] == :get) and (params.class < Hash) and (params.keys.count > 0)
|
41
|
+
# if method is get, Fill action with parameters
|
42
|
+
action += '('
|
43
|
+
(params.each do |key,value|
|
44
|
+
action += ',' unless params.keys.first == key
|
45
|
+
action += key + '='
|
46
|
+
action += (if (value.class < String) or (value.class < Symbol)
|
47
|
+
"'#{(URI.encode value.gsub("'", %q(\\\')))}'"
|
48
|
+
else
|
49
|
+
value
|
50
|
+
end)
|
51
|
+
end)
|
52
|
+
action += ')'
|
53
|
+
else
|
54
|
+
# if method is post, send parameters in the body
|
55
|
+
body = (params.class < Hash ? params.to_json : params)
|
56
|
+
end
|
57
|
+
# Call action
|
58
|
+
@site.query method_params[:http_method], action, body, method_params[:skip_json]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def sharepoint_resource options = {}
|
63
|
+
options[:method_name] ||= (self.name).split('::').last.downcase + 's'
|
64
|
+
options[:getter] ||= options[:method_name]
|
65
|
+
options[:get_from_name] ||= options[:getter]
|
66
|
+
Sharepoint::Site.send :define_method, options[:method_name] do
|
67
|
+
self.query :get, options[:getter].to_s
|
68
|
+
end unless options[:no_root_collection] == true
|
69
|
+
Sharepoint::Site.send :define_method, (self.name).split('::').last.downcase do |id|
|
70
|
+
if id =~ /^[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}$/
|
71
|
+
self.query :get, "#{options[:getter]}(guid'#{id}')"
|
72
|
+
else
|
73
|
+
self.query :get, "#{options[:get_from_name]}('#{URI.encode id}')"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def belongs_to resource_name
|
79
|
+
resource_name = resource_name.to_s
|
80
|
+
class_name = (self.name).split('::').last.downcase
|
81
|
+
method_name = class_name.pluralize
|
82
|
+
define_singleton_method "all_from_#{resource_name}" do |resource|
|
83
|
+
resource.site.query :get, "#{resource.__metadata['uri']}/#{method_name}"
|
84
|
+
end
|
85
|
+
define_singleton_method "get_from_#{resource_name}" do |resource, name|
|
86
|
+
resource.site.query :get, "#{resource.__metadata['uri']}/#{method_name}('#{URI.encode name}')"
|
87
|
+
end
|
88
|
+
define_method "create_uri" do
|
89
|
+
unless self.parent.nil?
|
90
|
+
"#{self.parent.__metadata['uri']}/#{method_name}"
|
91
|
+
else
|
92
|
+
method_name
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
attr_accessor :parent
|
99
|
+
|
100
|
+
def initialize site, data
|
101
|
+
@parent = nil
|
102
|
+
super site, data
|
103
|
+
end
|
104
|
+
|
105
|
+
def guid
|
106
|
+
return @guid unless @guid.nil?
|
107
|
+
__metadata['id'].scan(/guid'([^']+)'/) do ||
|
108
|
+
@guid = $1
|
109
|
+
break
|
110
|
+
end
|
111
|
+
@guid
|
112
|
+
end
|
113
|
+
|
114
|
+
def reload
|
115
|
+
@site.query :get, __metadata['uri']
|
116
|
+
end
|
117
|
+
|
118
|
+
def save
|
119
|
+
if @data['__metadata'].nil? or @data['__metadata']['id'].nil?
|
120
|
+
create
|
121
|
+
elsif @updated_data.keys.count > 0
|
122
|
+
update
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def destroy
|
127
|
+
@site.query :post, resource_uri do |curl|
|
128
|
+
curl.headers['X-HTTP-Method'] = 'DELETE'
|
129
|
+
curl.headers['If-Match'] = __metadata['etag']
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def copy new_object = nil
|
134
|
+
updating = !new_object.nil?
|
135
|
+
new_object ||= self.class.new @site
|
136
|
+
self.class.fields.each do |field|
|
137
|
+
next unless @data.keys.include? field[:name].to_s
|
138
|
+
next if (field[:access] & [ :write, :initialize ]).count == 0
|
139
|
+
value = @data[field[:name].to_s]
|
140
|
+
if updating == false
|
141
|
+
new_object.data[field[:name].to_s] = value
|
142
|
+
elsif new_object.data[field[:name].to_s] != value
|
143
|
+
new_object.updated_data[field[:name].to_s] = value
|
144
|
+
end
|
145
|
+
end
|
146
|
+
new_object
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
def sharepoint_typename
|
151
|
+
if self.is_a?(Sharepoint::GenericSharepointObject)
|
152
|
+
@generic_type_name
|
153
|
+
else
|
154
|
+
self.class.name.split('::').last
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def resource_uri
|
159
|
+
@data['__metadata']['uri'].gsub(/^https:\/\/[^\/]+\/_api\/web\//i, '')
|
160
|
+
end
|
161
|
+
|
162
|
+
def create_uri
|
163
|
+
sharepoint_typename.downcase.pluralize
|
164
|
+
end
|
165
|
+
|
166
|
+
def create
|
167
|
+
@site.query :post, create_uri, @data.to_json
|
168
|
+
end
|
169
|
+
|
170
|
+
def update
|
171
|
+
@updated_data['__metadata'] ||= @data['__metadata']
|
172
|
+
@site.query :post, resource_uri, @updated_data.to_json do |curl|
|
173
|
+
curl.headers['X-HTTP-Method'] = 'MERGE'
|
174
|
+
curl.headers['If-Match'] = __metadata['etag']
|
175
|
+
end
|
176
|
+
@updated_data = Hash.new
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'sharepoint-stringutils'
|
2
|
+
|
3
|
+
module Sharepoint
|
4
|
+
class ObjectProperties
|
5
|
+
attr_accessor :site, :data, :updated_data
|
6
|
+
|
7
|
+
def initialize site, data
|
8
|
+
@site = site
|
9
|
+
@data = data
|
10
|
+
@updated_data = Hash.new
|
11
|
+
@properties = Hash.new
|
12
|
+
@properties_names = Array.new
|
13
|
+
@properties_original_names = Array.new
|
14
|
+
initialize_properties
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_property property, value = nil
|
18
|
+
editable = is_property_editable? property
|
19
|
+
property = property.to_s
|
20
|
+
@data[property] = nil if @data[property].nil?
|
21
|
+
@data[property] = value unless value.nil?
|
22
|
+
@updated_data[property] = value if (@initialize_properties == false) and (editable == true)
|
23
|
+
unless @properties_original_names.include? property
|
24
|
+
@properties_names << property.underscore.to_sym
|
25
|
+
@properties_original_names << property
|
26
|
+
define_singleton_method property.underscore do
|
27
|
+
get_property property
|
28
|
+
end
|
29
|
+
define_singleton_method property.underscore + '=' do |new_value|
|
30
|
+
@data[property] = new_value
|
31
|
+
@updated_data[property] = new_value
|
32
|
+
end if editable == true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_properties properties
|
37
|
+
properties.each do |property|
|
38
|
+
add_property property
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def available_properties
|
43
|
+
@properties_names
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def initialize_properties
|
49
|
+
@initialize_properties = true
|
50
|
+
# Create the properties defined for the Sharepoint type used
|
51
|
+
self.class.fields.each do |field|
|
52
|
+
add_property field[:name], field[:default] if field[:access].include? :read
|
53
|
+
end
|
54
|
+
# Set the values and create any missing properties from the OData object
|
55
|
+
@data.dup.each do |key,value|
|
56
|
+
add_property key, value
|
57
|
+
end
|
58
|
+
@initialize_properties = false
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_property property_name
|
62
|
+
data = @data[property_name]
|
63
|
+
if not @properties[property_name].nil?
|
64
|
+
@properties[property_name]
|
65
|
+
elsif data.class == Hash
|
66
|
+
if not data['__deferred'].nil?
|
67
|
+
@properties[property_name] = get_deferred_property property_name
|
68
|
+
elsif not data['__metadata'].nil?
|
69
|
+
@properties[property_name] = @site.make_object_from_data data
|
70
|
+
else
|
71
|
+
@properties[property_name] = data
|
72
|
+
end
|
73
|
+
elsif not data.nil?
|
74
|
+
@properties[property_name] = data
|
75
|
+
else
|
76
|
+
@properties[property_name] = nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_deferred_property property_name
|
81
|
+
deferred_data = @data[property_name]['__deferred']
|
82
|
+
uri = deferred_data['uri'].gsub /^http.*\/_api\/web\//i, ''
|
83
|
+
@site.query :get, uri
|
84
|
+
end
|
85
|
+
|
86
|
+
def is_property_editable? property_name
|
87
|
+
# We don't know a priori what the fields are for a generic object, so leave the validation work to the user
|
88
|
+
return true if self.is_a?(GenericSharepointObject)
|
89
|
+
|
90
|
+
self.class.fields.each do |field|
|
91
|
+
return field[:access].include? :write if field[:name] == property_name
|
92
|
+
end
|
93
|
+
false
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'curb'
|
2
|
+
require 'json'
|
3
|
+
require 'sharepoint-session'
|
4
|
+
require 'sharepoint-object'
|
5
|
+
require 'sharepoint-types'
|
6
|
+
|
7
|
+
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
|
+
class Site
|
23
|
+
attr_reader :server_url
|
24
|
+
attr_accessor :url, :protocole
|
25
|
+
attr_accessor :session
|
26
|
+
attr_accessor :name
|
27
|
+
attr_accessor :verbose
|
28
|
+
|
29
|
+
def initialize server_url, site_name
|
30
|
+
@server_url = server_url
|
31
|
+
@name = site_name
|
32
|
+
@url = "#{@server_url}/#{@name}"
|
33
|
+
@session = Session.new self
|
34
|
+
@web_context = nil
|
35
|
+
@protocole = 'https'
|
36
|
+
@verbose = false
|
37
|
+
end
|
38
|
+
|
39
|
+
def authentication_path
|
40
|
+
"#{@protocole}://#{@server_url}/_forms/default.aspx?wa=wsignin1.0"
|
41
|
+
end
|
42
|
+
|
43
|
+
def api_path uri
|
44
|
+
"#{@protocole}://#{@url}/_api/web/#{uri}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def filter_path uri
|
48
|
+
uri
|
49
|
+
end
|
50
|
+
|
51
|
+
def context_info
|
52
|
+
query :get, ''
|
53
|
+
end
|
54
|
+
|
55
|
+
# Sharepoint uses 'X-RequestDigest' as a CSRF security-like.
|
56
|
+
# The form_digest method acquires a token or uses a previously acquired
|
57
|
+
# token if it is still supposed to be valid.
|
58
|
+
def form_digest
|
59
|
+
if @web_context.nil? or (not @web_context.is_up_to_date?)
|
60
|
+
@getting_form_digest = true
|
61
|
+
@web_context = query :post, "#{@protocole}://#{@server_url}/_api/contextinfo"
|
62
|
+
@getting_form_digest = false
|
63
|
+
end
|
64
|
+
@web_context.form_digest_value
|
65
|
+
end
|
66
|
+
|
67
|
+
def query method, uri, body = nil, skip_json=false, &block
|
68
|
+
uri = if uri =~ /^http/ then uri else api_path(uri) end
|
69
|
+
arguments = [ uri ]
|
70
|
+
arguments << body if method != :get
|
71
|
+
result = Curl::Easy.send "http_#{method}", *arguments do |curl|
|
72
|
+
curl.headers["Cookie"] = @session.cookie
|
73
|
+
curl.headers["Accept"] = "application/json;odata=verbose"
|
74
|
+
if method != :get
|
75
|
+
curl.headers["Content-Type"] = curl.headers["Accept"]
|
76
|
+
curl.headers["X-RequestDigest"] = form_digest unless @getting_form_digest == true
|
77
|
+
end
|
78
|
+
curl.verbose = @verbose
|
79
|
+
@session.send :curl, curl unless not @session.methods.include? :curl
|
80
|
+
block.call curl unless block.nil?
|
81
|
+
end
|
82
|
+
|
83
|
+
unless skip_json || (result.body_str.nil? || result.body_str.empty?)
|
84
|
+
begin
|
85
|
+
data = JSON.parse result.body_str
|
86
|
+
raise Sharepoint::SPException.new data, uri, body unless data['error'].nil?
|
87
|
+
make_object_from_response data
|
88
|
+
rescue JSON::ParserError => e
|
89
|
+
raise Exception.new("Exception with body=#{body}, e=#{e.inspect}, #{e.backtrace.inspect}, response=#{result.body_str}")
|
90
|
+
end
|
91
|
+
else
|
92
|
+
result.body_str
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def make_object_from_response data
|
97
|
+
if data['d']['results'].nil?
|
98
|
+
data['d'] = data['d'][data['d'].keys.first] if data['d']['__metadata'].nil?
|
99
|
+
if not data['d'].nil?
|
100
|
+
make_object_from_data data['d']
|
101
|
+
else
|
102
|
+
nil
|
103
|
+
end
|
104
|
+
else
|
105
|
+
array = Array.new
|
106
|
+
data['d']['results'].each do |result|
|
107
|
+
array << (make_object_from_data result)
|
108
|
+
end
|
109
|
+
array
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Uses sharepoint's __metadata field to solve which Ruby class to instantiate,
|
114
|
+
# and return the corresponding Sharepoint::Object.
|
115
|
+
def make_object_from_data data
|
116
|
+
type_name = data['__metadata']['type'].gsub(/^SP\./, '')
|
117
|
+
type_parts = type_name.split '.'
|
118
|
+
type_name = type_parts.pop
|
119
|
+
constant = Sharepoint
|
120
|
+
type_parts.each do |part| constant = constant.const_get part end
|
121
|
+
|
122
|
+
klass = constant.const_get type_name rescue nil
|
123
|
+
if klass
|
124
|
+
klass.new self, data
|
125
|
+
else
|
126
|
+
Sharepoint::GenericSharepointObject.new type_name, self, data
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'curb'
|
3
|
+
|
4
|
+
module Sharepoint
|
5
|
+
MICROSOFT_STS_URL = "https://login.microsoftonline.com/extSTS.srf"
|
6
|
+
|
7
|
+
module Soap
|
8
|
+
class Authenticate
|
9
|
+
SOURCE = "soap/authenticate.xml.erb"
|
10
|
+
|
11
|
+
attr_accessor :username, :password, :login_url
|
12
|
+
|
13
|
+
def self.initialize
|
14
|
+
return if @initialized == true
|
15
|
+
@erb = ERB.new(::File.read ::File.dirname(__FILE__) + '/' + SOURCE)
|
16
|
+
@erb.filename = SOURCE
|
17
|
+
@erb.def_method self, 'render()'
|
18
|
+
@initialized = true
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize params = {}
|
22
|
+
Authenticate.initialize
|
23
|
+
@username = params[:username]
|
24
|
+
@password = params[:password]
|
25
|
+
@login_url = params[:url]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Session
|
31
|
+
class ConnexionToStsFailed < Exception ; end
|
32
|
+
class ConnexionToSharepointFailed < Exception; end
|
33
|
+
class UnknownAuthenticationError < Exception; end
|
34
|
+
class AuthenticationFailed < Exception
|
35
|
+
def initialize message ; super message ; end
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_accessor :site
|
39
|
+
|
40
|
+
def initialize site
|
41
|
+
@site = site
|
42
|
+
end
|
43
|
+
|
44
|
+
def authenticate user, password, sts_url = nil
|
45
|
+
sts_url ||= MICROSOFT_STS_URL
|
46
|
+
authenticate_to_sts user, password, sts_url
|
47
|
+
get_access_token
|
48
|
+
end
|
49
|
+
|
50
|
+
def cookie
|
51
|
+
"FedAuth=#{@fed_auth};rtFa=#{@rtFa}"
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def authenticate_to_sts user, password, sts_url
|
56
|
+
query = Soap::Authenticate.new username: user, password: password, url: @site.authentication_path
|
57
|
+
response = Curl::Easy.http_post sts_url, query.render rescue raise ConnexionToStsFailed.new
|
58
|
+
|
59
|
+
response.body_str.scan(/<wsse:BinarySecurityToken[^>]*>([^<]+)</) do
|
60
|
+
offset = ($~.offset 1)
|
61
|
+
@security_token = response.body[offset[0]..offset[1] - 1]
|
62
|
+
end
|
63
|
+
authentication_failed response.body_str if @security_token.nil?
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_cookie_from_header header, cookie_name
|
67
|
+
result = nil
|
68
|
+
header.scan(/#{cookie_name}=([^;]+);/) do
|
69
|
+
offset = $~.offset 1
|
70
|
+
result = header[offset[0]..offset[1] - 1]
|
71
|
+
end
|
72
|
+
result
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_access_token
|
76
|
+
http = Curl::Easy.http_post @site.authentication_path, @security_token
|
77
|
+
@rtFa = get_cookie_from_header http.header_str, 'rtFa'
|
78
|
+
@fed_auth = get_cookie_from_header http.header_str, 'FedAuth'
|
79
|
+
raise UnknownAuthenticationError.new if @fed_auth.nil? or @rtFa.nil?
|
80
|
+
end
|
81
|
+
|
82
|
+
def authentication_failed xml
|
83
|
+
message = 'Unknown authentication error'
|
84
|
+
xml.scan(/<psf:text[^>]*>([^<]+)</) do
|
85
|
+
offset = ($~.offset 1)
|
86
|
+
message = xml[offset[0]..offset[1] - 1]
|
87
|
+
end
|
88
|
+
raise AuthenticationFailed.new message
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Defines underscore and pluralize methods
|
2
|
+
# unless they've already been defined by another script.
|
3
|
+
|
4
|
+
unless String.new.methods.include? :underscore
|
5
|
+
class String
|
6
|
+
def underscore
|
7
|
+
self.gsub(/::/, '/').
|
8
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
9
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
10
|
+
tr("-", "_").
|
11
|
+
downcase
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
unless String.new.methods.include? :camelize
|
17
|
+
class String
|
18
|
+
def camelize
|
19
|
+
self.split("_").each {|s| s.capitalize! }.join("")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
unless String.new.methods.include? :pluralize
|
25
|
+
class String
|
26
|
+
def pluralize
|
27
|
+
if self.match /y$/
|
28
|
+
self.gsub /y$/, 'ies'
|
29
|
+
elsif self.match /us$/
|
30
|
+
self.gsub /us$/, 'i'
|
31
|
+
else
|
32
|
+
self + 's'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'sharepoint-object'
|
2
|
+
|
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
|
+
module Type
|
17
|
+
def initialize site, data = nil
|
18
|
+
data ||= Hash.new
|
19
|
+
data['__metadata'] ||= {
|
20
|
+
'type' => "SP.#{self.class.name.split('::').last}"
|
21
|
+
}
|
22
|
+
super site, data
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'sharepoint-users'
|
28
|
+
require 'sharepoint-lists'
|
29
|
+
require 'sharepoint-files'
|
30
|
+
require 'sharepoint-fields'
|
31
|
+
require 'date'
|
32
|
+
|
33
|
+
module Sharepoint
|
34
|
+
##
|
35
|
+
## Sharepoint Management
|
36
|
+
##
|
37
|
+
class Web < Sharepoint::Object
|
38
|
+
include Sharepoint::Type
|
39
|
+
|
40
|
+
field 'CustomMasterUrl'
|
41
|
+
field 'Description'
|
42
|
+
field 'EnableMinimalDownload'
|
43
|
+
field 'MasterUrl'
|
44
|
+
field 'QuickLaunchEnabled'
|
45
|
+
field 'SaveSiteAsTemplateEnabled'
|
46
|
+
field 'SyndicationEnabled'
|
47
|
+
field 'Title'
|
48
|
+
field 'TreeViewEnabled'
|
49
|
+
field 'UiVersion'
|
50
|
+
field 'UiVersionConfigurationEnabled'
|
51
|
+
|
52
|
+
method :apply_theme
|
53
|
+
method :break_role_inheritance, default_params: ({ clearsubscopes: true })
|
54
|
+
end
|
55
|
+
|
56
|
+
class ContextWebInformation < Sharepoint::Object
|
57
|
+
include Sharepoint::Type
|
58
|
+
|
59
|
+
def issued_time
|
60
|
+
strtime = (form_digest_value.split ',').last
|
61
|
+
DateTime.strptime strtime, '%d %b %Y %H:%M:%S %z'
|
62
|
+
end
|
63
|
+
|
64
|
+
def timeout_time
|
65
|
+
issued_time + Rational(form_digest_timeout_seconds, 86400)
|
66
|
+
end
|
67
|
+
|
68
|
+
def is_up_to_date?
|
69
|
+
DateTime.now < timeout_time
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class FeatureCollection < Sharepoint::Object
|
74
|
+
include Sharepoint::Type
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
## Other types
|
79
|
+
##
|
80
|
+
class PropertyValues < Sharepoint::Object
|
81
|
+
include Sharepoint::Type
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Sharepoint
|
2
|
+
class Group < Sharepoint::Object
|
3
|
+
include Sharepoint::Type
|
4
|
+
sharepoint_resource getter: :sitegroups
|
5
|
+
end
|
6
|
+
|
7
|
+
class User < Sharepoint::Object
|
8
|
+
include Sharepoint::Type
|
9
|
+
sharepoint_resource getter: :siteusers
|
10
|
+
belongs_to :group
|
11
|
+
end
|
12
|
+
|
13
|
+
class UserCustomAction < Sharepoint::Object
|
14
|
+
include Sharepoint::Type
|
15
|
+
sharepoint_resource
|
16
|
+
end
|
17
|
+
|
18
|
+
class RoleAssignment < Sharepoint::Object
|
19
|
+
include Sharepoint::Type
|
20
|
+
sharepoint_resource
|
21
|
+
end
|
22
|
+
|
23
|
+
class RoleDefinition < Sharepoint::Object
|
24
|
+
include Sharepoint::Type
|
25
|
+
end
|
26
|
+
|
27
|
+
class GenericSharepointObject < Sharepoint::Object
|
28
|
+
include Sharepoint::Type
|
29
|
+
sharepoint_resource
|
30
|
+
|
31
|
+
def initialize type_name, site, data
|
32
|
+
super site, data
|
33
|
+
@generic_type_name = type_name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
|
2
|
+
<s:Header>
|
3
|
+
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
|
4
|
+
<a:ReplyTo>
|
5
|
+
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
|
6
|
+
</a:ReplyTo>
|
7
|
+
<a:To s:mustUnderstand="1">https://login.microsoftonline.com/extSTS.srf</a:To>
|
8
|
+
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
|
9
|
+
<o:UsernameToken>
|
10
|
+
<o:Username><%= @username %></o:Username>
|
11
|
+
<o:Password><%= @password %></o:Password>
|
12
|
+
</o:UsernameToken>
|
13
|
+
</o:Security>
|
14
|
+
</s:Header>
|
15
|
+
<s:Body>
|
16
|
+
<t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
|
17
|
+
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
|
18
|
+
<a:EndpointReference>'
|
19
|
+
<a:Address><%= @login_url %></a:Address>'
|
20
|
+
</a:EndpointReference>'
|
21
|
+
</wsp:AppliesTo>'
|
22
|
+
<t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
|
23
|
+
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
|
24
|
+
<t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>'
|
25
|
+
</t:RequestSecurityToken>'
|
26
|
+
</s:Body>'
|
27
|
+
</s:Envelope>
|
28
|
+
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sharepoint-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Martin Moro
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-05-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: curb
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.8'
|
20
|
+
- - "<="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.8.6
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.8'
|
30
|
+
- - "<="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.8.6
|
33
|
+
description: Client for Sharepoint's REST API
|
34
|
+
email: michael@unetresgrossebite.com
|
35
|
+
executables: []
|
36
|
+
extensions: []
|
37
|
+
extra_rdoc_files: []
|
38
|
+
files:
|
39
|
+
- lib/sharepoint-fields.rb
|
40
|
+
- lib/sharepoint-files.rb
|
41
|
+
- lib/sharepoint-http-auth.rb
|
42
|
+
- lib/sharepoint-lists.rb
|
43
|
+
- lib/sharepoint-object.rb
|
44
|
+
- lib/sharepoint-properties.rb
|
45
|
+
- lib/sharepoint-ruby.rb
|
46
|
+
- lib/sharepoint-session.rb
|
47
|
+
- lib/sharepoint-stringutils.rb
|
48
|
+
- lib/sharepoint-types.rb
|
49
|
+
- lib/sharepoint-users.rb
|
50
|
+
- lib/soap/authenticate.xml.erb
|
51
|
+
homepage: https://github.com/Plaristote/sharepoint-ruby
|
52
|
+
licenses:
|
53
|
+
- BSD
|
54
|
+
metadata: {}
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 2.5.1
|
72
|
+
signing_key:
|
73
|
+
specification_version: 4
|
74
|
+
summary: sharepoint client
|
75
|
+
test_files: []
|