d2l_sdk 0.1.9 → 0.1.10

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,40 @@
1
+ require_relative 'requests'
2
+ require 'json-schema'
3
+
4
+ ##################
5
+ ## ACTIONS: ######
6
+ ##################
7
+
8
+ # TODO: Delete a file or folder from the current user’s locker.
9
+ # => DELETE /d2l/api/le/(version)/locker/myLocker/(path)
10
+ # TODO: Delete a file or folder from the provided user’s locker.
11
+ # => DELETE /d2l/api/le/(version)/locker/user/(userId)/(path)
12
+ # TODO: Retrieve a specific object from the current user’s locker.
13
+ # => GET /d2l/api/le/(version)/locker/myLocker/(path)
14
+ # TODO: Retrieve a specific object from a provided user’s locker.
15
+ # => GET /d2l/api/le/(version)/locker/user/(userId)/(path)
16
+ # TODO: Add a new file or folder to the current user’s locker.
17
+ # => POST /d2l/api/le/(version)/locker/myLocker/(path)
18
+ # TODO: Add a new file or folder to the provided user’s locker.
19
+ # => POST /d2l/api/le/(version)/locker/user/(userId)/(path)
20
+ # TODO: Rename a folder in the current user’s locker.
21
+ # => PUT /d2l/api/le/(version)/locker/myLocker/(path)
22
+ # TODO: Rename a folder in the provided user’s locker.
23
+ # => PUT /d2l/api/le/(version)/locker/user/(userId)/(path)
24
+
25
+ ##################
26
+ ## LOCKERS: ######
27
+ ##################
28
+
29
+ # TODO: Delete a file or folder from the locker of a group in the provided org unit.
30
+ # => DELETE /d2l/api/le/(version)/(orgUnitId)/locker/group/(groupId)/(path)
31
+ # TODO: Determine if a locker has been set up for a group category within an org unit.
32
+ # => GET /d2l/api/lp/(version)/(orgUnitId)/groupcategories/(groupCategoryId)/locker
33
+ # TODO: Retrieve a specific object from a provided group’s locker.
34
+ # => GET /d2l/api/le/(version)/(orgUnitId)/locker/group/(groupId)/(path)
35
+ # TODO: Set up the locker for a group category within an org unit.
36
+ # => POST /d2l/api/lp/(version)/(orgUnitId)/groupcategories/(groupCategoryId)/locker
37
+ # TODO: Add a new file or folder to the locker for a group in the provided org unit.
38
+ # => POST /d2l/api/le/(version)/(orgUnitId)/locker/group/(groupId)/(path)
39
+ # TODO: Rename a folder in the locker for a group in the provided org unit.
40
+ # => PUT /d2l/api/le/(version)/(orgUnitId)/locker/group/(groupId)/(path)
@@ -0,0 +1,34 @@
1
+ require_relative 'requests'
2
+ require 'json-schema'
3
+
4
+ ##################
5
+ ## ACTIONS: ######
6
+ ##################
7
+
8
+ # TODO: Remove an LTI link.
9
+ # => DELETE /d2l/api/le/(version)/lti/link/(ltiLinkId)
10
+ # TODO: Retrieve the information for all LTI links registered for an org unit.
11
+ # => GET /d2l/api/le/(version)/lti/link/(orgUnitId)/
12
+ # TODO: Retrieve the information for a particular LTI link.
13
+ # => GET /d2l/api/le/(version)/lti/link/(orgUnitId)/(ltiLinkId)
14
+ # TODO: Register a new LTI link for an org unit.
15
+ # => POST /d2l/api/le/(version)/lti/link/(orgUnitId)
16
+ # TODO: Build a new quicklink around an existing LTI link.
17
+ # => POST /d2l/api/le/(version)/lti/quicklink/(orgUnitId)/(ltiLinkId)
18
+ # TODO: Update the information associated with a registered LTI link.
19
+ # => PUT /d2l/api/le/(version)/lti/link/(ltiLinkId)
20
+
21
+ #############################
22
+ ## LTI TOOL PROVIDERS: ######
23
+ #############################
24
+
25
+ # TODO: Remove the registration for an LTI tool provider.
26
+ # => DELETE /d2l/api/le/(version)/lti/tp/(tpId)
27
+ # TODO: Retrieve the information for all LTI tool providers registered for an org unit.
28
+ # => GET /d2l/api/le/(version)/lti/tp/(orgUnitId)/
29
+ # TODO: Retrieve the information for a particular LTI tool provider.
30
+ # => GET /d2l/api/le/(version)/lti/tp/(orgUnitId)/(tpId)
31
+ # TODO: Register a new LTI tool provider for an org unit.
32
+ # => POST /d2l/api/le/(version)/lti/tp/(orgUnitId)
33
+ # TODO: Update the information associated with a registered LTI tool provider.
34
+ # => PUT /d2l/api/le/(version)/lti/tp/(tpId)
@@ -67,6 +67,26 @@ end
67
67
  # part 2: attachments
68
68
  def create_news_item(org_unit_id, news_item_data, attachments = [])
69
69
  # POST /d2l/api/le/(version)/(orgUnitId)/news/
70
+ path = "/d2l/api/le/#{$le_ver}/#{org_unit_id}/news/"
71
+ json =
72
+ {
73
+ "Title" => "Placeholder_title",
74
+ "Body" =>
75
+ { # Composite: RichText
76
+ "Text" => "plaintext_text_here",
77
+ "HTML" => nil # OR the HTML_Formatted_version_of_text
78
+ },
79
+ "StartDate" => "UTCDateTime",
80
+ "EndDate" => nil, # nil or UTCDateTime -- e.g. 2017-03-28T18:54:56.000Z
81
+ "IsGlobal" => false,
82
+ "IsPublished" => false, # sets it as a draft
83
+ "ShowOnlyInCourseOfferings" => false
84
+ }.merge!(news_item_data)
85
+ files = attachments
86
+ method = "POST"
87
+ ap json
88
+ ap _news_upload(path, json, files, method)
89
+ # RETURNS a NewsItem JSON data block
70
90
  end
71
91
 
72
92
  # NOTE: UNSTABLE!!!
@@ -0,0 +1,27 @@
1
+ require_relative 'requests'
2
+ require 'json-schema'
3
+
4
+ ########################
5
+ # ACTIONS:##############
6
+ ########################
7
+
8
+ # TODO: --UNSTABLE-- Remove the specified capability.
9
+ # => DELETE /d2l/api/lp/(version)/permissions/tools/(toolId)/capabilities/(capabilityId)
10
+ # TODO: --UNSTABLE-- Reset a permission grant to “not allowed”.
11
+ # => DELETE /d2l/api/lp/(version)/permissions/tools/(toolId)/claims/allowed/(grantId)
12
+ # TODO: --UNSTABLE-- Retrieve all the capability grants for a tool.
13
+ # => GET /d2l/api/lp/(version)/permissions/tools/(toolId)/capabilities/
14
+ # TODO: --UNSTABLE-- Retrieve all the permission grants for a tool’s permissions claims.
15
+ # => GET /d2l/api/lp/(version)/permissions/tools/(toolId)/claims/
16
+ # TODO: --UNSTABLE-- Retrieve all the allowed permission grants for a tool for a tool’s permissions claims.
17
+ # => GET /d2l/api/lp/(version)/permissions/tools/(toolId)/claims/allowed/
18
+ # TODO: --UNSTABLE-- Determine the allowance state of a permission grant.
19
+ # => GET /d2l/api/lp/(version)/permissions/tools/(toolId)/claims/allowed/(grantId)
20
+ # TODO: --UNSTABLE-- Retrieve the meta-data for all of a tool’s permission claims.
21
+ # => GET /d2l/api/lp/(version)/permissions/tools/(toolId)/claims/metadata/
22
+ # TODO: --UNSTABLE-- Retrieve the meta-data for one of a tool’s permission claims.
23
+ # => GET /d2l/api/lp/(version)/permissions/tools/(toolId)/claims/metadata/(claimId)
24
+ # TODO: --UNSTABLE-- Grant a tool capability.
25
+ # => POST /d2l/api/lp/(version)/permissions/tools/(toolId)/capabilities/
26
+ # TODO: --UNSTABLE-- Set a permission grant to “allowed”.
27
+ # => PUT /d2l/api/lp/(version)/permissions/tools/(toolId)/claims/allowed/(grantId)
@@ -1,4 +1,8 @@
1
1
  require_relative 'auth'
2
+ require 'net/http'
3
+ require 'uri'
4
+ require 'mime/types'
5
+ require 'json'
2
6
 
3
7
  ########################
4
8
  # QUERIES/RESPONSE:#####
@@ -76,25 +80,231 @@ def _post(path, payload, isD2l = true)
76
80
  end
77
81
  end
78
82
  end
79
- =begin
80
- # in compliance with FTC1867 HTTP file upload
81
- def _upload(path, json, file, method, name, filename)
83
+
84
+ # NOTE: multipart code examples referrenced from danielwestendorf--
85
+ # FTC 1867 and FTC 2388 implementations are based upon the following url:
86
+ # => "https://coderwall.com/p/c-mu-a/http-posts-in-ruby"
87
+ # The code has obviously been modified for usage with basic D2L POST/PUT api methods
88
+ # in compliance with FTC 1867 & FTC 2388 HTTP file upload and according to examples
89
+ # shown on: "http://docs.valence.desire2learn.com/basic/fileupload.html"
90
+
91
+ # Upload a file to the learning repository.
92
+ def _learning_repository_upload(path, file, method)
93
+ # name = the content name,
94
+ # e.g. "Resource", "profileImage", "name", "description", "file", "targetUsers"
95
+ # file = the File's name in the directory.
96
+ # method = POST or PUT
97
+ # json = the json appended to the end of the request body
98
+ auth_uri = path
99
+ auth_uri = create_authenticated_uri(path, method)
100
+ uri = URI.parse(auth_uri)
101
+
82
102
  boundary = "xxBOUNDARYxx"
83
- http_req = "Content-Type: multipart/form-data; boundary=#{boundary}\n"\
84
- "Content-Length: {#{method} #{file.bytesize}}\n\n"\
85
- "#{boundary}\n"\
86
- "Content-Type: #{content-type}\n"
87
- "Content-Disposition: form-data; name = '#{name}'; filename='#{filename}'\n"\
88
- # Requires Content-Type and boundary specification on line 1
89
- # Requires Content-Length with specification of method on line 2
90
- # Requires boundary before the content
91
- # Requires Content-Disposition, name, and filename line 1 of content
92
- # Requires Content-Type as line 2 of content
93
- # Requires boundary after the content
94
- # url, payload, {:multipart => true}, req
95
- # if sending a file, multipart is autodetected
96
- end
97
- =end
103
+ header = {"Content-Type" => "multipart/form-data; boundary=#{boundary}"}
104
+ # setup the post body
105
+ post_body = []
106
+ post_body << "--#{boundary}\n"
107
+ post_body << "Content-Disposition: form-data; name = \"Resource\"; filename=\"#{File.basename(file)}\"\r\n"
108
+ post_body << "Content-Type: application/zip\r\n\r\n"
109
+ post_body << File.read(file)
110
+ post_body << "\r\n\r\n--#{boundary}--\r\n"
111
+
112
+ # Create the HTTP objects
113
+ http = Net::HTTP.new(uri.host, uri.port)
114
+ request = Net::HTTP::Post.new(uri.request_uri, header)
115
+ request.body = post_body.join
116
+
117
+ # Send the request
118
+ response = http.request(request)
119
+ JSON.parse(response)
120
+ end
121
+
122
+ # REVIEW: profile image upload process
123
+ def _profile_image_upload(path, file, method)
124
+ # name = the content name,
125
+ # e.g. "Resource", "profileImage", "name", "description", "file", "targetUsers"
126
+ # file = the File's name in the directory.
127
+ # method = POST or PUT
128
+ # json = the json appended to the end of the request body
129
+ auth_uri = path
130
+ auth_uri = create_authenticated_uri(path, method)
131
+ uri = URI.parse(auth_uri)
132
+
133
+ boundary = "xxBOUNDARYxx"
134
+ header = {"Content-Type" => "multipart/form-data; boundary=#{boundary}"}
135
+ # setup the post body
136
+ post_body = []
137
+ post_body << "--#{boundary}\n"
138
+ post_body << "Content-Disposition: form-data; name = \"profileImage\"; filename=\"#{File.basename(file)}\"\r\n"
139
+ post_body << "Content-Type: image/png\r\n\r\n"
140
+ post_body << File.read(file)
141
+ post_body << "\r\n\r\n--#{boundary}--\r\n"
142
+
143
+ # Create the HTTP objects
144
+ http = Net::HTTP.new(uri.host, uri.port)
145
+ request = Net::HTTP::Post.new(uri.request_uri, header)
146
+ request.body = post_body.join
147
+
148
+ # Send the request
149
+ response = http.request(request)
150
+ JSON.parse(response)
151
+ end
152
+
153
+ def _ePortfolio_upload(path, file, method, description)
154
+ # name = the content name,
155
+ # e.g. "Resource", "profileImage", "name", "description", "file", "targetUsers"
156
+ # filename = the File's name in the directory.
157
+ # method = POST or PUT
158
+ # json = the json appended to the end of the request body
159
+ auth_uri = path
160
+ auth_uri = create_authenticated_uri(path, method)
161
+ uri = URI.parse(auth_uri)
162
+
163
+ boundary = "xxBOUNDARYxx"
164
+ header = {"Content-Type" => "multipart/form-data; boundary=#{boundary}"}
165
+ # setup the post body
166
+ post_body = []
167
+ post_body << "--#{boundary}\r\n"
168
+ post_body << "Content-Type: text/plain\r\n"
169
+ post_body << "Content-Disposition: form-data; name = \"name\"\r\n\r\n"
170
+ post_body << "#{File.basename(file)}\r\n"
171
+
172
+ post_body << "--#{boundary}\r\n"
173
+ post_body << "Content-Type: text/plain\r\n"
174
+ post_body << "Content-Disposition: form-data; name = \"description\"\r\n\r\n"
175
+ post_body << "#{description}\r\n"
176
+
177
+ post_body << "--#{boundary}\r\n"
178
+ post_body << "Content-Type: text/plain\r\n"
179
+ post_body << "Content-Disposition: form-data; name = \"file\"; filename=\"#{File.basename(file)}\"\r\n\r\n"
180
+ post_body << File.read(file)
181
+ post_body << "\r\n\r\n--#{boundary}--\r\n"
182
+
183
+ # Create the HTTP objects
184
+ http = Net::HTTP.new(uri.host, uri.port)
185
+ request = Net::HTTP::Post.new(uri.request_uri, header)
186
+ request.body = post_body.join
187
+
188
+ # Send the request
189
+ response = http.request(request)
190
+ JSON.parse(response)
191
+ end
192
+
193
+ def _course_content_upload(path, json, file, method)
194
+ # name = the content name,
195
+ # e.g. "Resource", "profileImage", "name", "description", "file", "targetUsers"
196
+ # filename = the File's name in the directory.
197
+ # method = POST or PUT
198
+ # json = the json appended to the end of the request body
199
+ auth_uri = path
200
+ auth_uri = create_authenticated_uri(path, method)
201
+ uri = URI.parse(auth_uri)
202
+
203
+ boundary = "xxBOUNDARYxx"
204
+ header = {"Content-Type" => "multipart/mixed; boundary=#{boundary}"}
205
+ # setup the post body
206
+ post_body = []
207
+ post_body << "--#{boundary}\r\n"
208
+ post_body << "Content-Type: application/json\r\n\r\n"
209
+
210
+ post_body << json.to_json
211
+ post_body << "\r\n"
212
+
213
+ post_body << "--#{boundary}\r\n"
214
+ post_body << "Content-Disposition: form-data; name = \"\"; filename=\"#{File.basename(file)}\"\r\n\r\n"
215
+ post_body << "Content-Type: text/plain\r\n"
216
+ post_body << File.read(file)
217
+ post_body << "\r\n\r\n--#{boundary}--\r\n"
218
+
219
+ # Create the HTTP objects
220
+ http = Net::HTTP.new(uri.host, uri.port)
221
+ request = Net::HTTP::Post.new(uri.request_uri, header)
222
+ request.body = post_body.join
223
+
224
+ # Send the request
225
+ response = http.request(request)
226
+ JSON.parse(response)
227
+ end
228
+
229
+ def _dropbox_upload(path, json, file, method)
230
+ # name = the content name,
231
+ # e.g. "Resource", "profileImage", "name", "description", "file", "targetUsers"
232
+ # filename = the File's name in the directory.
233
+ # method = POST or PUT
234
+ # json = the json appended to the end of the request body
235
+ auth_uri = path
236
+ auth_uri = create_authenticated_uri(path, method)
237
+ uri = URI.parse(auth_uri)
238
+
239
+ boundary = "xxBOUNDARYxx"
240
+ header = {"Content-Type" => "multipart/mixed; boundary=#{boundary}"}
241
+ # setup the post body
242
+ post_body = []
243
+ post_body << "--#{boundary}\r\n"
244
+ post_body << "Content-Type: application/json\r\n\r\n"
245
+
246
+ post_body << json.to_json # e.g. {"Text" => "Here you go", "Html" => null}
247
+ post_body << "\r\n"
248
+ post_body << "--#{boundary}\r\n"
249
+ post_body << "Content-Disposition: form-data; name = \"\"; filename=\"#{File.basename(file)}\"\r\n"
250
+ post_body << "Content-Type: #{MIME::Types.type_for(file)}\r\n\r\n"
251
+
252
+ post_body << File.read(file)
253
+ post_body << "\r\n\r\n--#{boundary}--\r\n"
254
+
255
+ # Create the HTTP objects
256
+ http = Net::HTTP.new(uri.host, uri.port)
257
+ request = Net::HTTP::Post.new(uri.request_uri, header)
258
+ request.body = post_body.join
259
+
260
+ # Send the request
261
+ response = http.request(request)
262
+ JSON.parse(response)
263
+ end
264
+
265
+ # function to upload 1+ files to a news event.
266
+ # e.g. uploading 2 attachments to a news event (a text file; a png)
267
+ def _news_upload(path, json, files, method)
268
+ # name = the content name,
269
+ # e.g. "Resource", "profileImage", "name", "description", "file", "targetUsers"
270
+ # files = array of filenames
271
+ # method = POST or PUT
272
+ # json = the json appended to the end of the request body
273
+ auth_uri = path
274
+ auth_uri = create_authenticated_uri(path, method)
275
+ uri = URI.parse(auth_uri)
276
+
277
+ boundary = "xxBOUNDARYxx"
278
+ header = {"Content-Type" => "multipart/mixed; boundary=#{boundary}"}
279
+ # setup the post body
280
+ post_body = []
281
+ post_body << "--#{boundary}\r\n"
282
+ post_body << "Content-Type: application/json\r\n\r\n"
283
+
284
+ post_body << json.to_json # e.g. {"Text" => "Here you go", "Html" => null}
285
+
286
+ file_iteration = 0
287
+ files.each do |file|
288
+ post_body << "\r\n--#{boundary}\r\n"
289
+ post_body << "Content-Disposition: form-data; name = \"file #{file_iteration}\"; filename=\"#{File.basename(file)}\"\r\n"
290
+ post_body << "Content-Type: text/plain\r\n\r\n"
291
+ post_body << File.read(file)
292
+ file_iteration += 1
293
+ end
294
+ post_body << "\r\n\r\n--#{boundary}--\r\n"
295
+
296
+ # Create the HTTP objects
297
+ http = Net::HTTP.new(uri.host, uri.port)
298
+ http.set_debug_output($stdout)
299
+ http.use_ssl = true
300
+ request = Net::HTTP::Post.new(uri.request_uri, header)
301
+ request.body = post_body.join
302
+ puts request.body
303
+ # Send the request
304
+ response = http.request(request)
305
+ response.body
306
+ end
307
+
98
308
  # performs a put request using the path and the payload arguments. After first
99
309
  # creating an authenticated uri, the put request is performed using the
100
310
  # authenticated uri, the payload argument, and specifying that the payload is
@@ -1,14 +1,22 @@
1
1
  require_relative "requests"
2
2
 
3
3
  # init products to newest versions.
4
- $le_ver = get_latest_product_version('le')
5
- $lp_ver = get_latest_product_version('lp')
6
- $ep_ver = get_latest_product_version('ep')
4
+ $le_ver = get_latest_product_version('le') # learning environment
5
+ $lp_ver = get_latest_product_version('lp') # learning platform
6
+ $ep_ver = get_latest_product_version('ep') # Eportfolio
7
+ $LR_ver = get_latest_product_version('LR') # Learning repository
8
+ $bas_ver = get_latest_product_version('bas') # Award service
9
+ $lti_ver = get_latest_product_version('lti') # learning tools interoperability
10
+ # ext
11
+
7
12
  #lti, rp, LR, ext,
8
13
  puts "versions set to:"
9
14
  versions = {
10
- "le_ver" => $le_ver,
11
- "lp_ver" => $lp_ver,
12
- "ep_ver" => $ep_ver
15
+ "Learning Environment" => $le_ver,
16
+ "Learning Platform" => $lp_ver,
17
+ "Eportfolio" => $ep_ver,
18
+ "Learning Object Repository" => $LR_ver,
19
+ "Award Service" => $bas_ver,
20
+ "Learning Tools Interoperability" => $lti_ver
13
21
  }
14
22
  ap versions
@@ -212,7 +212,7 @@ def check_updated_user_data_validity(user_data)
212
212
  LastName ExternalEmail UserName
213
213
  Activation),
214
214
  'properties' => {
215
- 'OrgDefinedId' => { 'type' => 'string' },
215
+ 'OrgDefinedId' => { 'type' => %w(string null) },
216
216
  'FirstName' => { 'type' => 'string' },
217
217
  'MiddleName' => { 'type' => 'string' },
218
218
  'LastName' => { 'type' => 'string' },
@@ -279,11 +279,21 @@ def get_user_activation_settings(user_id)
279
279
  # RETURNS: a UserActivationData JSON block with the user’s current activation status.
280
280
  end
281
281
 
282
- # TODO: Update a particular user’s activation settings.
282
+ # REVIEW: Update a particular user’s activation settings.
283
283
  # RETURNS: ?
284
- def update_user_activation_settings(user_id, user_activation_data)
284
+ def update_user_activation_settings(user_id, is_active)
285
285
  # PUT /d2l/api/lp/(version)/users/(userId)/activation
286
- # RETURNS: ?
286
+ if is_active != true && is_active != false
287
+ raise ArgumentError, 'is_active is not a boolean'
288
+ else
289
+ path = "/d2l/api/lp/#{$lp_ver}/users/#{user_id}/activation"
290
+ payload =
291
+ {
292
+ "IsActive" => is_active
293
+ }
294
+ _put(path, payload)
295
+ # RETURNS: ?
296
+ end
287
297
  end
288
298
 
289
299
  ########################
@@ -291,7 +301,7 @@ end
291
301
  ########################
292
302
 
293
303
  # NOTE: UNSTABLE!
294
- # TODO: Link a user to a Google Apps user account.
304
+ # TODO: UNSTABLE!--Link a user to a Google Apps user account.
295
305
  # RETURNS: ?
296
306
  def link_user_google_apps_account(google_apps_linking_item)
297
307
  # POST /d2l/api/gae/(version)/linkuser