d2l_api 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/bin/.DS_Store +0 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/d2l_api.gemspec +41 -0
- data/lib/.DS_Store +0 -0
- data/lib/d2l_api.rb +11 -0
- data/lib/d2l_api/.DS_Store +0 -0
- data/lib/d2l_api/auth.rb +84 -0
- data/lib/d2l_api/config.rb +11 -0
- data/lib/d2l_api/course.rb +109 -0
- data/lib/d2l_api/course_template.rb +135 -0
- data/lib/d2l_api/org_unit.rb +185 -0
- data/lib/d2l_api/requests.rb +92 -0
- data/lib/d2l_api/semester.rb +120 -0
- data/lib/d2l_api/user.rb +172 -0
- data/lib/d2l_api/version.rb +3 -0
- metadata +182 -0
@@ -0,0 +1,135 @@
|
|
1
|
+
require_relative 'requests'
|
2
|
+
########################
|
3
|
+
# COURSE TEMPLATES:#####
|
4
|
+
########################
|
5
|
+
|
6
|
+
# This method creates a course template using a merged payload between a
|
7
|
+
# pre-formatted payload and the argument "course_template_data". Upon this merge
|
8
|
+
# the path is defined for the POST http method that is then executed to create
|
9
|
+
# the course_template object.
|
10
|
+
# Required: "Name", "Code"
|
11
|
+
# /d2l/api/lp/(version)/coursetemplates/ [POST]
|
12
|
+
def create_course_template(course_template_data)
|
13
|
+
# ForceLocale- course override the user’s locale preference
|
14
|
+
# Path- root path to use for this course offering’s course content
|
15
|
+
# if your back-end service has path enforcement set on for
|
16
|
+
# new org units, leave this property as an empty string
|
17
|
+
# Define a valid, empty payload and merge! with the user_data. Print it.
|
18
|
+
payload = { 'Name' => '', # String
|
19
|
+
'Code' => 'off_SEMESTERCODE_STARNUM', # String
|
20
|
+
'Path' => '', # String
|
21
|
+
'ParentOrgUnitIds' => [99_989], # number: D2L_ID
|
22
|
+
}.merge!(course_template_data)
|
23
|
+
puts "Creating Course Template:"
|
24
|
+
ap payload
|
25
|
+
# Define a path referencing the courses path
|
26
|
+
path = "/d2l/api/lp/#{$version}/coursetemplates/"
|
27
|
+
_post(path, payload)
|
28
|
+
puts '[+] Course template creation completed successfully'.green
|
29
|
+
end
|
30
|
+
|
31
|
+
# Retrieves a course template based upon an explicitly defined course template
|
32
|
+
# org_unit_id or Identifier. This is done by using the identifier as a component
|
33
|
+
# of the path, and then performing a GET http method that is then returned.
|
34
|
+
#
|
35
|
+
# returns: JSON course template data
|
36
|
+
# /d2l/api/lp/(version)/coursetemplates/(orgUnitId) [GET]
|
37
|
+
def get_course_template(org_unit_id)
|
38
|
+
path = "/d2l/api/lp/#{$version}/coursetemplates/" + org_unit_id.to_s
|
39
|
+
_get(path)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Instead of explicitly retrieving a single course template, this method uses
|
43
|
+
# the routing table to retrieve all of the organizations descendants with the
|
44
|
+
# outTypeId of 2. What this means is that it is literally retrieving any and all
|
45
|
+
# course templates that have an ancestor of the organization...which should be
|
46
|
+
# all of them.
|
47
|
+
#
|
48
|
+
# returns: JSON array of course template data objects
|
49
|
+
def get_all_course_templates
|
50
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/6606/descendants/?ouTypeId=2"
|
51
|
+
_get(path)
|
52
|
+
end
|
53
|
+
|
54
|
+
# This method retrieves all course templates that have a specific string, as
|
55
|
+
# specified by org_unit_name, within their names. This is done by first defining
|
56
|
+
# that none are found yet and initializing an empty array. Then, by searching
|
57
|
+
# through all course templates for ones that do have a particular string within
|
58
|
+
# their name, the matches are pushed into the previously empty array of matches.
|
59
|
+
# This array is subsequently returned; if none were found, a message is returned
|
60
|
+
#
|
61
|
+
# returns: JSON array of matching course template data objects
|
62
|
+
def get_course_template_by_name(org_unit_name)
|
63
|
+
course_template_not_found = true
|
64
|
+
course_template_results = []
|
65
|
+
puts "[+] Searching for templates using search string: \'#{org_unit_name}\'".yellow
|
66
|
+
results = get_all_course_templates
|
67
|
+
results.each do |x|
|
68
|
+
if x['Name'].downcase.include? org_unit_name.downcase
|
69
|
+
course_template_not_found = false
|
70
|
+
course_template_results.push(x)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
if course_template_not_found
|
74
|
+
puts '[-] No templates could be found based upon the search string.'.yellow
|
75
|
+
end
|
76
|
+
course_template_results
|
77
|
+
end
|
78
|
+
|
79
|
+
# Moreso a helper method, but this really just returns the schema of the
|
80
|
+
# course templates. This is predefined in the routing table, and retrieved via
|
81
|
+
# a GET http method.
|
82
|
+
#
|
83
|
+
# returns: JSON of course templates schema
|
84
|
+
# /d2l/api/lp/(version)/coursetemplates/schema [GET]
|
85
|
+
def get_course_templates_schema
|
86
|
+
path = "/d2l/api/lp/#{$version}/coursetemplates/schema"
|
87
|
+
_get(path)
|
88
|
+
end
|
89
|
+
|
90
|
+
# This is the primary method utilized to update course templates. As only the
|
91
|
+
# Name and the Code can be changed in an update, they are pre-defined to
|
92
|
+
# conform to the required update data. The update is then performed via a
|
93
|
+
# PUT http method that is executed using a path referencing the course template.
|
94
|
+
# /d2l/api/lp/(version)/coursetemplates/(orgUnitId) [PUT]
|
95
|
+
def update_course_template(org_unit_id, new_data)
|
96
|
+
# Define a valid, empty payload and merge! with the new data.
|
97
|
+
payload = { 'Name' => '', # String
|
98
|
+
'Code' => 'off_SEMESTERCODE_STARNUM', # String
|
99
|
+
}.merge!(new_data)
|
100
|
+
puts "Updating course template #{org_unit_id}"
|
101
|
+
#ap payload
|
102
|
+
# Define a path referencing the courses path
|
103
|
+
path = "/d2l/api/lp/#{$version}/coursetemplates/" + org_unit_id.to_s
|
104
|
+
_put(path, payload)
|
105
|
+
puts '[+] Course template update completed successfully'.green
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
# Simply, a course template can be deleted by refencing it using its Identifier
|
110
|
+
# as an argument for this method. The argument is then used to refernce the obj
|
111
|
+
# by a path and then the path is passed in for a delete http method.
|
112
|
+
# /d2l/api/lp/(version)/coursetemplates/(orgUnitId) [DELETE]
|
113
|
+
def delete_course_template(org_unit_id)
|
114
|
+
path = "/d2l/api/lp/#{$version}/coursetemplates/" + org_unit_id.to_s
|
115
|
+
_delete(path)
|
116
|
+
puts '[+] Course template data deleted successfully'.green
|
117
|
+
end
|
118
|
+
|
119
|
+
# As a more streamlined approach to deleting many course templates conforming to
|
120
|
+
# a particular naming style, this function performs deletions based on a string.
|
121
|
+
# Using the name argument, +get_course_template_by_name+ is called in order to
|
122
|
+
# retrieve all matching templates. They are then deleted by referencing each
|
123
|
+
# of their Identifiers as arguments for +delete_course_template+.
|
124
|
+
def delete_all_course_templates_with_name(name)
|
125
|
+
puts "[!] Deleting all course templates with the name: #{name}"
|
126
|
+
get_course_template_by_name(name).each do |course_template|
|
127
|
+
puts "[!] Deleting the following course:".red
|
128
|
+
ap course_template
|
129
|
+
delete_course_template(course_template["Identifier"])
|
130
|
+
end
|
131
|
+
end
|
132
|
+
#TO DO:
|
133
|
+
def delete_course_templates_by_regex(regex)
|
134
|
+
|
135
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require_relative 'requests'
|
2
|
+
########################
|
3
|
+
# Org Units:############
|
4
|
+
########################
|
5
|
+
|
6
|
+
# gets all descendents of a particular org unit, as referenced by the
|
7
|
+
# "org_unit_id" argument. A get request is then performed by a preformatted
|
8
|
+
# path.
|
9
|
+
def get_org_unit_descendants(org_unit_id)
|
10
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/#{org_unit_id}/descendants/"
|
11
|
+
_get(path)
|
12
|
+
# return json of org_unit descendants
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_paged_org_unit_descendants(org_unit_id)
|
16
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/#{org_unit_id}/descendants/paged/"
|
17
|
+
_get(path)
|
18
|
+
# return json of org_unit descendants
|
19
|
+
end
|
20
|
+
|
21
|
+
# gets all parents of a particular org unit, as referenced by the
|
22
|
+
# "org_unit_id" argument. A get request is then performed by a preformatted
|
23
|
+
# path.
|
24
|
+
def get_org_unit_parents(org_unit_id)
|
25
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/#{org_unit_id}/parents/"
|
26
|
+
_get(path)
|
27
|
+
# return json of org_unit parents
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_parent_to_org_unit(parent_ou_id, child_ou_id)
|
31
|
+
# Must follow structure of data
|
32
|
+
# (course <-- semester <== org -->custom dept--> dept -->templates--> courses)
|
33
|
+
# Refer to valence documentation for further structural understanding..
|
34
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/#{child_ou_id}/parents/"
|
35
|
+
_post(path, parent_ou_id)
|
36
|
+
# return json of org_unit parents
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_org_unit_ancestors(org_unit_id)
|
40
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/#{org_unit_id}/ancestors/"
|
41
|
+
_get(path)
|
42
|
+
# return json of org_unit parents
|
43
|
+
end
|
44
|
+
|
45
|
+
# gets all children of a particular org unit, as referenced by the
|
46
|
+
# "org_unit_id" argument. A get request is then performed by a preformatted
|
47
|
+
# path.
|
48
|
+
def get_org_unit_children(org_unit_id)
|
49
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/#{org_unit_id}/children/"
|
50
|
+
_get(path)
|
51
|
+
# return json of org_unit children
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_paged_org_unit_children(org_unit_id)
|
55
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/#{org_unit_id}/children/paged/"
|
56
|
+
_get(path)
|
57
|
+
# return json of org_unit children
|
58
|
+
end
|
59
|
+
|
60
|
+
# gets all properties of a particular org unit, as referenced by the
|
61
|
+
# "org_unit_id" argument. A get request is then performed by a preformatted
|
62
|
+
# path.
|
63
|
+
def get_org_unit_properties(org_unit_id)
|
64
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/#{org_unit_id}"
|
65
|
+
_get(path)
|
66
|
+
# return json of org_unit properties
|
67
|
+
end
|
68
|
+
|
69
|
+
def delete_relationship_of_child_with_parent(parent_ou_id, child_ou_id)
|
70
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/#{parent_ou_id}/children/#{child_ou_id}"
|
71
|
+
_delete(path)
|
72
|
+
end
|
73
|
+
|
74
|
+
def delete_relationship_of_parent_with_child(parent_ou_id, child_ou_id)
|
75
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/#{child_ou_id}/parents/#{parent_ou_id}"
|
76
|
+
_delete(path)
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_all_childless_org_units
|
80
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/childless/"
|
81
|
+
_get(path)
|
82
|
+
# ONLY RETRIEVES FIRST 100
|
83
|
+
end
|
84
|
+
|
85
|
+
def get_all_orphans
|
86
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/orphans/"
|
87
|
+
_get(path)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Adds a child to the org unit by using org_unit_id to reference the soon-to-be
|
91
|
+
# parent of the child_org_unit and referencing the soon-to-be child through the
|
92
|
+
# child_org_unit_id argument. Then, a path is created to reference the children
|
93
|
+
# of the soon-to-be parent and executing a post http method that adds the child.
|
94
|
+
#
|
95
|
+
# TL;DR, this adds a child org_unit to the children of an org_unit.
|
96
|
+
def add_child_org_unit(org_unit_id, child_org_unit_id)
|
97
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/#{org_unit_id}/children/"
|
98
|
+
_post(path, child_org_unit_id)
|
99
|
+
end
|
100
|
+
|
101
|
+
def get_recycled_org_units
|
102
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/recyclebin/"
|
103
|
+
_get(path)
|
104
|
+
# GETS ONLY FIRST 100
|
105
|
+
end
|
106
|
+
|
107
|
+
# An org unit is recycled by executing a POST http method and recycling it. The
|
108
|
+
# path for the recycling is created using the org_unit_id argument and then the
|
109
|
+
# post method is executed afterwards.
|
110
|
+
def recycle_org_unit(org_unit_id)
|
111
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/recyclebin/#{org_unit_id}/recycle"
|
112
|
+
_post(path, {})
|
113
|
+
end
|
114
|
+
|
115
|
+
def delete_recycled_org_unit(org_unit_id)
|
116
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/recyclebin/#{org_unit_id}"
|
117
|
+
_delete(path)
|
118
|
+
end
|
119
|
+
|
120
|
+
def restore_recycled_org_unit(org_unit_id)
|
121
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/recyclebin/#{org_unit_id}/restore"
|
122
|
+
_post(path, {})
|
123
|
+
end
|
124
|
+
|
125
|
+
# Functions considered for basic added functionality to api, not sure if needed.
|
126
|
+
def create_custom_org_unit(org_unit_data)
|
127
|
+
# Requires the type to have the correct parent. This will work fine in this
|
128
|
+
# sample, as the department (101) can have the parent Organiation (6606)
|
129
|
+
payload = { 'Type' => 101, # Number:D2LID
|
130
|
+
'Name' => 'custom_ou_name', # String
|
131
|
+
'Code' => 'custom_ou_code', # String
|
132
|
+
'Parents' => [6606], # Number:D2LID
|
133
|
+
}.merge!(org_unit_data)
|
134
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/"
|
135
|
+
_post(path, payload)
|
136
|
+
end
|
137
|
+
|
138
|
+
def update_org_unit(org_unit_id, org_unit_data)
|
139
|
+
previous_data = get_org_unit_properties(org_unit_id)
|
140
|
+
payload = { # Can only update NAME, CODE, and PATH variables
|
141
|
+
'Identifier' => org_unit_id.to_s, # String: D2LID // DO NOT CHANGE
|
142
|
+
'Name' => previous_data['Name'], # String
|
143
|
+
# String #YearNUM where NUM{sp:01,su:06,fl:08} | nil
|
144
|
+
'Code' => previous_data['Code'],
|
145
|
+
# String: /content/enforced/IDENTIFIER-CODE/
|
146
|
+
'Path' => "/content/enforced/#{org_unit_id}-#{previous_data['Code']}/",
|
147
|
+
'Type' => previous_data['Type']
|
148
|
+
# example:
|
149
|
+
# { # DO NOT CHANGE THESE
|
150
|
+
# 'Id' => 5, # <number:D2LID>
|
151
|
+
# 'Code' => 'Semester', # <string>
|
152
|
+
# 'Name' => 'Semester', # <string>
|
153
|
+
# }
|
154
|
+
}.merge!(org_unit_data)
|
155
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/#{org_unit_id}"
|
156
|
+
puts '[-] Attempting put request (updating orgunit)...'
|
157
|
+
_put(path, payload)
|
158
|
+
puts '[+] Semester update completed successfully'.green
|
159
|
+
end
|
160
|
+
|
161
|
+
# Retrieves the organization info. Only gets a small amount of information,
|
162
|
+
# but may be useful in some instances.
|
163
|
+
def get_organization_info
|
164
|
+
path = "/d2l/api/lp/#{$version}/organization/info"
|
165
|
+
_get(path)
|
166
|
+
end
|
167
|
+
|
168
|
+
def get_all_org_units_by_type_id(outype_id)
|
169
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/6606/children/?ouTypeId=#{outype_id}"
|
170
|
+
_get(path)
|
171
|
+
end
|
172
|
+
|
173
|
+
# This retrieves information about a partituclar org unit type, referenced via
|
174
|
+
# the outype_id argument. This is then returned as a JSON object.
|
175
|
+
def get_outype(outype_id)
|
176
|
+
path = "/d2l/api/lp/#{$version}/outypes/#{outype_id}"
|
177
|
+
_get(path)
|
178
|
+
end
|
179
|
+
|
180
|
+
# retrieves all outypes that are known and visible. This is returned as a JSON
|
181
|
+
# array of orgunittype data blocks.
|
182
|
+
def get_all_outypes
|
183
|
+
path = "/d2l/api/lp/#{$version}/outypes/"
|
184
|
+
_get(path)
|
185
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require_relative 'auth'
|
2
|
+
|
3
|
+
########################
|
4
|
+
# QUERIES/RESPONSE:#####
|
5
|
+
########################
|
6
|
+
|
7
|
+
# performs a get request on a particular path of the host.
|
8
|
+
# To do this, a uniform resource identifier string is created using the path and
|
9
|
+
# specifying that this is a get request. Then, the RestClient get method is
|
10
|
+
# used to retrieve the data and parse it as a JSON. Then, the parsed response is
|
11
|
+
# returned. Otherwise, nothing is returned and the response code is printed
|
12
|
+
#
|
13
|
+
# returns: JSON parsed response.
|
14
|
+
def _get(path)
|
15
|
+
uri_string = create_authenticated_uri(path, 'GET')
|
16
|
+
RestClient.get(uri_string) do |response, _request, _result|
|
17
|
+
case response.code
|
18
|
+
when 200
|
19
|
+
# ap JSON.parse(response) # Here is the JSON fmt'd response printed
|
20
|
+
JSON.parse(response)
|
21
|
+
else
|
22
|
+
display_response_code(response.code)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# performs a post request using the path and the payload arguments. First, an
|
28
|
+
# authenticated uri is created to reference a particular resource. Then, the
|
29
|
+
# post method is executed using the payload and specifying that it is formatted
|
30
|
+
# as JSON.
|
31
|
+
def _post(path, payload)
|
32
|
+
auth_uri = create_authenticated_uri(path, 'POST')
|
33
|
+
RestClient.post(auth_uri, payload.to_json, content_type: :json)
|
34
|
+
end
|
35
|
+
|
36
|
+
# performs a put request using the path and the payload arguments. After first
|
37
|
+
# creating an authenticated uri, the put request is performed using the
|
38
|
+
# authenticated uri, the payload argument, and specifying that the payload is
|
39
|
+
# formatted in JSON.
|
40
|
+
def _put(path, payload)
|
41
|
+
auth_uri = create_authenticated_uri(path, 'PUT')
|
42
|
+
# Perform the put action, updating the data; Provide feedback to client.
|
43
|
+
RestClient.put(auth_uri, payload.to_json, content_type: :json)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Performs a delete request by creating an authenticated uri and using the
|
47
|
+
# RestClient delete method and specifying the content_type as being JSON.
|
48
|
+
def _delete(path)
|
49
|
+
auth_uri = create_authenticated_uri(path, 'DELETE')
|
50
|
+
RestClient.delete(auth_uri, content_type: :json)
|
51
|
+
end
|
52
|
+
|
53
|
+
# based upon the specific code that is returned from the http method, this
|
54
|
+
# displays the response, in the case that it is an error within the request
|
55
|
+
# or the server. This is simply informative and assists in describing the
|
56
|
+
# lacking response information from the valence api. In the case of a Bad
|
57
|
+
# Request, it is likely that it cannot be further specified without looking
|
58
|
+
# back at the d2l_api documentation or looking at the documentation on
|
59
|
+
# the docs.valence.desire2learn.com website.
|
60
|
+
def display_response_code(code)
|
61
|
+
case code
|
62
|
+
when 400
|
63
|
+
puts '[!] 400: Bad Request'
|
64
|
+
when 401
|
65
|
+
puts '[!] 401: Unauthorized'
|
66
|
+
|
67
|
+
when 403
|
68
|
+
print '[!] Error Code Forbidden 403: accessing the page or resource '\
|
69
|
+
'you were trying to reach is absolutely forbidden for some reason.'
|
70
|
+
when 404
|
71
|
+
puts '[!] 404: Not Found'
|
72
|
+
when 405
|
73
|
+
puts '[!] 405: Method Not Allowed'
|
74
|
+
when 406
|
75
|
+
puts 'Unacceptable Type'\
|
76
|
+
'Unable to provide content type matching the client\'s Accept header.'
|
77
|
+
when 412
|
78
|
+
puts '[!] 412: Precondition failed\n'\
|
79
|
+
'Unsupported or invalid parameters, or missing required parameters.'
|
80
|
+
when 415
|
81
|
+
puts '[!] 415: Unsupported Media Type'\
|
82
|
+
'A PUT or POST payload cannot be accepted.'
|
83
|
+
when 423
|
84
|
+
puts '[!] 423'
|
85
|
+
when 500
|
86
|
+
puts '[!] 500: General Service Error\n'\
|
87
|
+
'Empty response body. The service has encountered an unexpected'\
|
88
|
+
'state and cannot continue to handle your action request.'
|
89
|
+
when 504
|
90
|
+
puts '[!] 504: Service Error'
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require_relative "requests"
|
2
|
+
########################
|
3
|
+
# SEMESTER:#############
|
4
|
+
########################
|
5
|
+
|
6
|
+
# Creates a semester based upon a merged result from merging a preformatted
|
7
|
+
# payload and the inputed semester data. This is then created server-side
|
8
|
+
# via executing a POST http method using a predefined path and the new payload.
|
9
|
+
def create_semester_data(semester_data)
|
10
|
+
# Define a valid, empty payload and merge! with the semester_data. Print it.
|
11
|
+
payload = { 'Type' => 5, # Number:D2LID
|
12
|
+
'Name' => 'Winter 2013 Semester', # String
|
13
|
+
'Code' => '201701', # String #YearNUM where NUM{sp:01,su:06,fl:08}
|
14
|
+
'Parents' => [6606], # ARR of Number:D2LID
|
15
|
+
}.merge!(semester_data)
|
16
|
+
#ap payload
|
17
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/"
|
18
|
+
_post(path, payload)
|
19
|
+
puts '[+] Semester creation completed successfully'.green
|
20
|
+
end
|
21
|
+
|
22
|
+
# This retrieves all semesters via getting all children from the main
|
23
|
+
# organization and filtering them by the default data type of semesters.
|
24
|
+
#
|
25
|
+
# Returns: Array of all semester JSON formatted data
|
26
|
+
def get_all_semesters
|
27
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/6606/children/?ouTypeId=5"
|
28
|
+
_get(path)
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_semester_by_id(org_unit_id)
|
32
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/" + org_unit_id.to_s
|
33
|
+
_get(path)
|
34
|
+
# return json of org_unit properties
|
35
|
+
end
|
36
|
+
# Rather than retrieving all semesters, this retrieves all semesters by a
|
37
|
+
# particular string. First, a boolean is created where it is assumed the
|
38
|
+
# semester is not found. Then an array is created with all the 'found' semesters
|
39
|
+
# assuming none are found, but providing the structure to still return uniform
|
40
|
+
# data that can be iterated. Then, by iterating through all semesters and only
|
41
|
+
# storing ones that conform to the search string, all matched semesters are then
|
42
|
+
# returned.
|
43
|
+
#
|
44
|
+
# Returns: Array of all semester JSON formatted data (with search string in name)
|
45
|
+
def get_semester_by_name(search_string)
|
46
|
+
semester_not_found = true
|
47
|
+
semester_results = []
|
48
|
+
puts "[+] Searching for semesters using search string: \'#{search_string}\'".yellow
|
49
|
+
results = get_all_semesters
|
50
|
+
results.each do |x|
|
51
|
+
if x['Name'].downcase.include? search_string.downcase
|
52
|
+
semester_not_found = false
|
53
|
+
semester_results.push(x)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
if semester_not_found
|
57
|
+
puts '[-] No semesters could be found based upon the search string.'.yellow
|
58
|
+
end
|
59
|
+
semester_results
|
60
|
+
end
|
61
|
+
|
62
|
+
# This is simply a helper function that can assist in preformatting a path
|
63
|
+
# that conforms to the required 'Path' for updating semester data.
|
64
|
+
#
|
65
|
+
# returns: preformatted semester 'Path' string
|
66
|
+
def create_semester_formatted_path(org_id, code)
|
67
|
+
"/content/enforced/#{org_id}-#{code}/"
|
68
|
+
end
|
69
|
+
|
70
|
+
# Updates a semester's data via merging a preformatted payload with the new
|
71
|
+
# semester data. The 'path' is then initialized using a defined org_unit_id
|
72
|
+
# and the semester is then updated via the newly defined payload and the path.
|
73
|
+
def update_semester_data(org_unit_id, semester_data)
|
74
|
+
# Define a valid, empty payload and merge! with the semester_data. Print it.
|
75
|
+
payload = { # Can only update NAME, CODE, and PATH variables
|
76
|
+
'Identifier' => org_unit_id.to_s, # String: D2LID // DO NOT CHANGE
|
77
|
+
'Name' => 'NAME', # String
|
78
|
+
# String #YearNUM where NUM{sp:01,su:06,fl:08} | nil
|
79
|
+
'Code' => 'REQUIRED',
|
80
|
+
# String: /content/enforced/IDENTIFIER-CODE/
|
81
|
+
'Path' => create_semester_formatted_path(org_unit_id.to_s, 'YEAR01'),
|
82
|
+
'Type' => { # DO NOT CHANGE THESE
|
83
|
+
'Id' => 5, # <number:D2LID>
|
84
|
+
'Code' => 'Semester', # <string>
|
85
|
+
'Name' => 'Semester', # <string>
|
86
|
+
}
|
87
|
+
}.merge!(semester_data)
|
88
|
+
# print out the projected new data
|
89
|
+
#puts '[-] New Semester Data:'.yellow
|
90
|
+
#ap payload
|
91
|
+
# Define a path referencing the course data using the course_id
|
92
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/#{org_unit_id}"
|
93
|
+
puts '[-] Attempting put request (updating orgunit)...'
|
94
|
+
_put(path, payload)
|
95
|
+
puts '[+] Semester update completed successfully'.green
|
96
|
+
end
|
97
|
+
|
98
|
+
# This function provides the means to put the semester data into the recycling
|
99
|
+
# bin. A path is then created using the org_unit_id argument. Once this is done
|
100
|
+
# the post http method is then completed in order to officially recycle the data
|
101
|
+
def recycle_semester_data(org_unit_id)
|
102
|
+
# Define a path referencing the user data using the user_id
|
103
|
+
puts '[!] Attempting to recycle Semester data referenced by id: ' + org_unit_id.to_s
|
104
|
+
path = "/d2l/api/lp/#{$version}/orgstructure/recyclebin/" + org_unit_id.to_s + '/recycle' # setup user path
|
105
|
+
_post(path, {})
|
106
|
+
puts '[+] Semester data recycled successfully'.green
|
107
|
+
end
|
108
|
+
|
109
|
+
# Rather than recycling a semester by a specific id, this function can recycle
|
110
|
+
# all semesters that match a particular name. The names must be exactly the same
|
111
|
+
# as the "name" argument. Each name that is the exact same as this argument is
|
112
|
+
# then recycled, iteratively.
|
113
|
+
def recycle_semester_by_name(name)
|
114
|
+
results = get_semester_by_name(name)
|
115
|
+
results.each do |semester_match|
|
116
|
+
if semester_match["Name"] == name
|
117
|
+
recycle_semester_data(semester_match["Identifier"])
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|