proof-sharepoint-ruby 1.0.0

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.
@@ -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,30 @@
1
+ require 'curb'
2
+ require 'cgi'
3
+
4
+ module Sharepoint
5
+ module KerberosAuth
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 = :gssnegotiate
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.protocol}://#{@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