sharepoint-ruby 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|