lms-api 1.19.0 → 1.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/canvas_api/builder.rb +76 -44
- data/lib/canvas_api/go_helpers.rb +604 -0
- data/lib/canvas_api/helpers.rb +17 -0
- data/lib/canvas_api/js_graphql_helpers.rb +8 -1
- data/lib/canvas_api/rb_graphql_helpers.rb +10 -24
- data/lib/canvas_api/render.rb +13 -2
- data/lib/canvas_api/templates/go_action.erb +241 -0
- data/lib/canvas_api/templates/go_struct.erb +44 -0
- data/lib/canvas_api/templates/rb_graphql_field.erb +2 -2
- data/lib/canvas_api/templates/rb_graphql_input_type.erb +1 -1
- data/lib/canvas_api/templates/rb_graphql_resolver.erb +1 -1
- data/lib/canvas_api/templates/rb_graphql_type.erb +1 -1
- data/lib/lms/canvas_urls.rb +93 -56
- data/lib/lms/course_ids_required.rb +17 -5
- data/lib/lms/version.rb +1 -1
- data/lib/tasks/canvas_api.rake +5 -1
- metadata +10 -6
@@ -9,7 +9,7 @@ module CanvasApi
|
|
9
9
|
if property["$ref"]
|
10
10
|
canvas_name(property['$ref'], input_type)
|
11
11
|
elsif property["allowableValues"]
|
12
|
-
enum_class_name(model, name)
|
12
|
+
enum_class_name(model, name, input_type)
|
13
13
|
else
|
14
14
|
type = property["type"].downcase
|
15
15
|
case type
|
@@ -41,11 +41,13 @@ module CanvasApi
|
|
41
41
|
"[#{canvas_name(property["items"]["$ref"], input_type)}]"
|
42
42
|
end
|
43
43
|
else
|
44
|
-
graphql_primitive(name, property["items"]["type"].downcase, property["items"]["format"])
|
44
|
+
array_type = graphql_primitive(name, property["items"]["type"].downcase, property["items"]["format"])
|
45
|
+
array_type = "[#{array_type}]" if array_type != "[ID]"
|
46
|
+
array_type
|
45
47
|
end
|
46
48
|
rescue
|
47
49
|
puts "Unable to discover list type for '#{name}' ('#{property}'). Defaulting to String"
|
48
|
-
type = "String"
|
50
|
+
type = "[String]"
|
49
51
|
end
|
50
52
|
type
|
51
53
|
when "object"
|
@@ -104,11 +106,11 @@ module CanvasApi
|
|
104
106
|
end
|
105
107
|
end
|
106
108
|
|
107
|
-
def enum_class_name(model, field_name)
|
108
|
-
"#{model['id'].classify}#{field_name.classify}Enum"
|
109
|
+
def enum_class_name(model, field_name, input_type)
|
110
|
+
"#{model['id'].classify}#{input_type ? 'Input' : ''}#{field_name.classify}Enum"
|
109
111
|
end
|
110
112
|
|
111
|
-
def graphql_field_enums(model)
|
113
|
+
def graphql_field_enums(model, input_type = false)
|
112
114
|
return unless model["properties"]
|
113
115
|
enums = model["properties"].map do |name, property|
|
114
116
|
if property["allowableValues"]
|
@@ -116,7 +118,7 @@ module CanvasApi
|
|
116
118
|
"value \"#{value}\""
|
117
119
|
end.join("\n ")
|
118
120
|
<<-CODE
|
119
|
-
class #{enum_class_name(model, name)} < ::GraphQL::Schema::Enum
|
121
|
+
class #{enum_class_name(model, name, input_type)} < ::GraphQL::Schema::Enum
|
120
122
|
#{values}
|
121
123
|
end
|
122
124
|
CODE
|
@@ -198,7 +200,7 @@ field :#{name.underscore}, #{type}, "#{description}", resolver_method: :resolve_
|
|
198
200
|
end
|
199
201
|
|
200
202
|
def make_file_name(str)
|
201
|
-
str.underscore.split("/").last.split("|").first.gsub(
|
203
|
+
str.underscore.split("/").last.split("|").first.gsub(/^canvas_?/, "").gsub(" ", "_").strip.singularize
|
202
204
|
end
|
203
205
|
|
204
206
|
def require_from_operation(operation)
|
@@ -230,22 +232,6 @@ field :#{name.underscore}, #{type}, "#{description}", resolver_method: :resolve_
|
|
230
232
|
str.gsub('"', "'")
|
231
233
|
end
|
232
234
|
|
233
|
-
def nested_arg(str)
|
234
|
-
# TODO/HACK we are replacing values from the string here to get things to work for now.
|
235
|
-
# However, removing these symbols means that the methods that use the arguments
|
236
|
-
# generated herein will have bugs and be unusable.
|
237
|
-
str.gsub("[", "_").
|
238
|
-
gsub("]", "").
|
239
|
-
gsub("*", "star").
|
240
|
-
gsub("<", "_").
|
241
|
-
gsub(">", "_").
|
242
|
-
gsub("`", "").
|
243
|
-
gsub("https://canvas.instructure.com/lti/", "").
|
244
|
-
gsub("https://www.instructure.com/", "").
|
245
|
-
gsub("https://purl.imsglobal.org/spec/lti/claim/", "").
|
246
|
-
gsub(".", "")
|
247
|
-
end
|
248
|
-
|
249
235
|
def params_as_string(parameters, paramTypes)
|
250
236
|
filtered = parameters.select{ |p| paramTypes.include?(p["paramType"]) }
|
251
237
|
if filtered && !filtered.empty?
|
data/lib/canvas_api/render.rb
CHANGED
@@ -1,20 +1,26 @@
|
|
1
|
+
require "canvas_api/helpers"
|
1
2
|
require "canvas_api/js_graphql_helpers"
|
2
3
|
require "canvas_api/js_helpers"
|
3
4
|
require "canvas_api/ruby_helpers"
|
4
5
|
require "canvas_api/rb_graphql_helpers"
|
6
|
+
require "canvas_api/go_helpers"
|
5
7
|
require "byebug"
|
8
|
+
|
6
9
|
module CanvasApi
|
7
10
|
|
8
11
|
class Render
|
12
|
+
include CanvasApi
|
9
13
|
include CanvasApi::GraphQLHelpers
|
10
14
|
include CanvasApi::JsHelpers
|
11
15
|
include CanvasApi::RubyHelpers
|
16
|
+
include CanvasApi::GoHelpers
|
12
17
|
attr_accessor :template, :description, :resource, :api_url, :operation,
|
13
18
|
:args, :method, :api, :name, :resource_name, :resource_api,
|
14
19
|
:nickname, :notes, :content, :summary, :model, :model_name
|
15
20
|
|
16
|
-
def initialize(template, api, resource, resource_api, operation, parameters, content, model)
|
21
|
+
def initialize(template, api, resource, resource_api, operation, parameters, content, model, api_path)
|
17
22
|
@template = File.read(File.expand_path(template, __dir__))
|
23
|
+
@api_path = api_path
|
18
24
|
if api
|
19
25
|
@api = api
|
20
26
|
@name = @api["path"].gsub("/", "").gsub(".json", "")
|
@@ -47,7 +53,12 @@ module CanvasApi
|
|
47
53
|
@summary = operation["summary"]
|
48
54
|
end
|
49
55
|
if parameters
|
50
|
-
|
56
|
+
# Keep a copy of full parameters for code that will include the description
|
57
|
+
@full_parameters = Marshal.load Marshal::dump(parameters)
|
58
|
+
# Strip description from parameters so that canvas_urls.rb
|
59
|
+
# doesn't error out on bad chars in the descriptions
|
60
|
+
tmp_params = Marshal.load Marshal::dump(parameters)
|
61
|
+
@parameters = tmp_params.map { |p| p.delete("description"); p }
|
51
62
|
end
|
52
63
|
@content = content
|
53
64
|
@model = model
|
@@ -0,0 +1,241 @@
|
|
1
|
+
<% string_utils_required = @parameters.any?{|p| p["enum"] && !is_x_param?(p["name"]) } -%>
|
2
|
+
<% errors_required = @parameters.any?{|p| p["enum"] || is_required_field(p) }-%>
|
3
|
+
<% query_params = go_query_params(@parameters) -%>
|
4
|
+
<% path_params = go_path_params(@parameters) -%>
|
5
|
+
<% form_params = go_form_params(@parameters) -%>
|
6
|
+
<% return_type = go_return_type(operation) -%>
|
7
|
+
package requests
|
8
|
+
|
9
|
+
import (
|
10
|
+
<% if return_type && return_type != "bool" && return_type != "string" || @nickname == "assign_unassigned_members" || form_params -%>
|
11
|
+
"encoding/json"
|
12
|
+
<% end -%>
|
13
|
+
<% if path_params || errors_required -%>
|
14
|
+
"fmt"
|
15
|
+
<% end -%>
|
16
|
+
<% if !!return_type -%>
|
17
|
+
"io/ioutil"
|
18
|
+
<% end -%>
|
19
|
+
<% if is_paged?(@operation) -%>
|
20
|
+
"net/http"
|
21
|
+
<% end -%>
|
22
|
+
"net/url"
|
23
|
+
<% if return_type == "int64" -%>
|
24
|
+
"strconv"
|
25
|
+
<% end -%>
|
26
|
+
<% if errors_required || path_params -%>
|
27
|
+
"strings"
|
28
|
+
<% end -%>
|
29
|
+
<% if time_required?(@parameters) -%>
|
30
|
+
"time"
|
31
|
+
<% end -%>
|
32
|
+
|
33
|
+
<% if query_params || go_form_params(@parameters) -%>
|
34
|
+
"github.com/google/go-querystring/query"
|
35
|
+
<% end -%>
|
36
|
+
|
37
|
+
"github.com/atomicjolt/canvasapi"
|
38
|
+
<% if go_require_models(@parameters, @nickname, return_type)-%>
|
39
|
+
"github.com/atomicjolt/canvasapi/models"
|
40
|
+
<% end -%>
|
41
|
+
<% if string_utils_required -%>
|
42
|
+
"github.com/atomicjolt/string_utils"
|
43
|
+
<% end -%>
|
44
|
+
)
|
45
|
+
|
46
|
+
// <%= go_name(@nickname) %> <%= @notes %>
|
47
|
+
// https://canvas.instructure.com/doc/api<%=@api_path.gsub(".json", ".html")%>
|
48
|
+
<% if params = go_path_params(@full_parameters)-%>
|
49
|
+
//
|
50
|
+
// Path Parameters:
|
51
|
+
// <%= params.map { |p| go_parameter_doc(p) }.join("\n// ") %>
|
52
|
+
<% end -%>
|
53
|
+
<% if params = go_query_params(@full_parameters) -%>
|
54
|
+
//
|
55
|
+
// Query Parameters:
|
56
|
+
// <%= params.map { |p| go_parameter_doc(p) }.join("\n// ") %>
|
57
|
+
<% end -%>
|
58
|
+
<% if params = go_form_params(@full_parameters) -%>
|
59
|
+
//
|
60
|
+
// Form Parameters:
|
61
|
+
// <%= params.map { |p| go_parameter_doc(p) }.join("\n// ") %>
|
62
|
+
<% end -%>
|
63
|
+
//
|
64
|
+
type <%= struct_name(@nickname) %> struct {
|
65
|
+
<% if params = go_path_params(@parameters) -%>
|
66
|
+
Path struct {
|
67
|
+
<%= go_struct_fields(@nickname, params) %>
|
68
|
+
} `json:"path"`
|
69
|
+
<% end -%>
|
70
|
+
|
71
|
+
<% if query_params -%>
|
72
|
+
Query struct {
|
73
|
+
<%= go_struct_fields(@nickname, query_params) %>
|
74
|
+
} `json:"query"`
|
75
|
+
<% end -%>
|
76
|
+
|
77
|
+
<% if form_params -%>
|
78
|
+
Form struct {
|
79
|
+
<%= go_struct_fields(@nickname, form_params) %>
|
80
|
+
} `json:"form"`
|
81
|
+
<% end -%>
|
82
|
+
}
|
83
|
+
|
84
|
+
func (t *<%= struct_name(@nickname) %>) GetMethod() string {
|
85
|
+
return "<%=@method%>"
|
86
|
+
}
|
87
|
+
|
88
|
+
func (t *<%= struct_name(@nickname) %>) GetURLPath() string {
|
89
|
+
<% if params = go_path_params(@parameters) -%>
|
90
|
+
path := "<%= go_api_url %>"
|
91
|
+
<% params.each do |p| -%>
|
92
|
+
path = strings.ReplaceAll(path, "{<%=p["name"]%>}", fmt.Sprintf("%v", t.Path.<%=go_name(p["name"])%>))
|
93
|
+
<% end -%>
|
94
|
+
return path
|
95
|
+
<% else -%>
|
96
|
+
return ""
|
97
|
+
<% end -%>
|
98
|
+
}
|
99
|
+
|
100
|
+
func (t *<%= struct_name(@nickname) %>) GetQuery()(string, error) {
|
101
|
+
<% if query_params -%>
|
102
|
+
v, err := query.Values(t.Query)
|
103
|
+
if err != nil {
|
104
|
+
return "", err
|
105
|
+
}
|
106
|
+
return v.Encode(), nil
|
107
|
+
<% else -%>
|
108
|
+
return "", nil
|
109
|
+
<% end -%>
|
110
|
+
}
|
111
|
+
|
112
|
+
func (t *<%= struct_name(@nickname) %>) GetBody() (url.Values, error) {
|
113
|
+
<% if form_params -%>
|
114
|
+
return query.Values(t.Form)
|
115
|
+
<% else -%>
|
116
|
+
return nil, nil
|
117
|
+
<% end -%>
|
118
|
+
}
|
119
|
+
|
120
|
+
func (t *<%= struct_name(@nickname) %>) GetJSON() ([]byte, error) {
|
121
|
+
<% if form_params -%>
|
122
|
+
j, err := json.Marshal(t.Form)
|
123
|
+
if err != nil {
|
124
|
+
return nil, nil
|
125
|
+
}
|
126
|
+
return j, nil
|
127
|
+
<% else -%>
|
128
|
+
return nil, nil
|
129
|
+
<% end -%>
|
130
|
+
}
|
131
|
+
|
132
|
+
func (t *<%= struct_name(@nickname) %>) HasErrors() error {
|
133
|
+
<% if errors_required -%>
|
134
|
+
errs := []string{}
|
135
|
+
<% end -%>
|
136
|
+
<% @parameters.each do |p| -%>
|
137
|
+
<% type = go_type(p["name"], p) -%>
|
138
|
+
<% if is_required_field(p) -%>
|
139
|
+
<% if type == "time.Time" -%>
|
140
|
+
if t.<%=go_param_path(p)%>.IsZero() {
|
141
|
+
errs = append(errs, "'<%=go_param_path(p)%>' is required")
|
142
|
+
}
|
143
|
+
<% else -%>
|
144
|
+
if t.<%=go_param_path(p)%> == <%=go_param_empty_value(p)%> {
|
145
|
+
errs = append(errs, "'<%=go_param_path(p)%>' is required")
|
146
|
+
}
|
147
|
+
<% end -%>
|
148
|
+
<% end -%>
|
149
|
+
<% if p["enum"] && ["string", "[]string"].include?(type) -%>
|
150
|
+
<% if p["type"] == "array" || type == "[]string" -%>
|
151
|
+
for _, v := range t.<%=go_param_path(p)%> {
|
152
|
+
if v != "" && !string_utils.Include([]string{"<%= p["enum"].join("\", \"") %>"}, v) {
|
153
|
+
errs = append(errs, "<%=go_name(p["name"])%> must be one of <%= p["enum"].join(", ") %>")
|
154
|
+
}
|
155
|
+
}
|
156
|
+
<% elsif !is_x_param?(p["name"]) -%>
|
157
|
+
if t.<%=go_param_path(p)%> != "" && !string_utils.Include([]string{"<%= p["enum"].join("\", \"") %>"}, t.<%=go_param_path(p)%>) {
|
158
|
+
errs = append(errs, "<%=go_name(p["name"])%> must be one of <%= p["enum"].join(", ") %>")
|
159
|
+
}
|
160
|
+
<% end -%>
|
161
|
+
<% end -%>
|
162
|
+
<% end -%>
|
163
|
+
<% if errors_required -%>
|
164
|
+
if len(errs) > 0 {
|
165
|
+
return fmt.Errorf(strings.Join(errs, ", "))
|
166
|
+
}
|
167
|
+
<% end -%>
|
168
|
+
return nil
|
169
|
+
}
|
170
|
+
|
171
|
+
func (t *<%= struct_name(@nickname) %>) Do(c *canvasapi.Canvas<%=next_param(@operation)%>) <%=go_do_return_value(@operation, @nickname)%> {
|
172
|
+
<% ret_type = go_return_type(@operation, true) -%>
|
173
|
+
<% if ret_type -%>
|
174
|
+
<% if is_paged?(@operation) -%>
|
175
|
+
var err error
|
176
|
+
var response *http.Response
|
177
|
+
if next != nil {
|
178
|
+
response, err = c.Send(next, t.GetMethod(), nil)
|
179
|
+
} else {
|
180
|
+
response, err = c.SendRequest(t)
|
181
|
+
}
|
182
|
+
|
183
|
+
if err != nil {
|
184
|
+
return nil, nil, err
|
185
|
+
}
|
186
|
+
<% else -%>
|
187
|
+
response, err := c.SendRequest(t)
|
188
|
+
<% end -%>
|
189
|
+
<% else -%>
|
190
|
+
_, err := c.SendRequest(t)
|
191
|
+
<% end -%>
|
192
|
+
if err != nil {
|
193
|
+
<%= go_do_return_statement(operation, @nickname) %>
|
194
|
+
}
|
195
|
+
|
196
|
+
<% if ret_type -%>
|
197
|
+
body, err := ioutil.ReadAll(response.Body)
|
198
|
+
response.Body.Close()
|
199
|
+
if err != nil {
|
200
|
+
<%= go_do_return_statement(operation, @nickname) %>
|
201
|
+
}
|
202
|
+
<% if @nickname == "assign_unassigned_members" -%>
|
203
|
+
groupMembership := models.GroupMembership{}
|
204
|
+
progress := models.Progress{}
|
205
|
+
if t.Form.Sync {
|
206
|
+
err = json.Unmarshal(body, &groupMembership)
|
207
|
+
if err != nil {
|
208
|
+
return nil, nil, err
|
209
|
+
}
|
210
|
+
} else {
|
211
|
+
err = json.Unmarshal(body, &progress)
|
212
|
+
if err != nil {
|
213
|
+
return nil, nil, err
|
214
|
+
}
|
215
|
+
}
|
216
|
+
<% elsif ret_type == "bool" -%>
|
217
|
+
ret := string(body) == "true"
|
218
|
+
<% elsif ret_type == "string" -%>
|
219
|
+
ret := string(body)
|
220
|
+
<% elsif ret_type == "int64" -%>
|
221
|
+
ret := strconv.ParseInt(string(body), 10, 64)
|
222
|
+
<% else -%>
|
223
|
+
ret := <%=ret_type%>
|
224
|
+
err = json.Unmarshal(body, &ret)
|
225
|
+
if err != nil {
|
226
|
+
<%= go_do_return_statement(operation, @nickname) %>
|
227
|
+
}
|
228
|
+
<% end -%>
|
229
|
+
<% end -%>
|
230
|
+
|
231
|
+
<% if @operation["type"] == "array" -%>
|
232
|
+
pagedResource, err := canvasapi.ExtractPagedResource(response.Header)
|
233
|
+
if err != nil {
|
234
|
+
return nil, nil, err
|
235
|
+
}
|
236
|
+
<% end -%>
|
237
|
+
|
238
|
+
<%= go_do_final_return_statement(operation, @nickname) %>
|
239
|
+
}
|
240
|
+
|
241
|
+
<%= go_render_child_structs %>
|
@@ -0,0 +1,44 @@
|
|
1
|
+
<%
|
2
|
+
fields, time_required = struct_fields(@model, @resource_name)
|
3
|
+
field_validations = go_field_validation(@model)
|
4
|
+
-%>
|
5
|
+
package models
|
6
|
+
|
7
|
+
<% if time_required || field_validations -%>
|
8
|
+
import (
|
9
|
+
<% if time_required -%>
|
10
|
+
"time"
|
11
|
+
<% end -%>
|
12
|
+
<% if (field_validations && field_validations.length > 0) -%>
|
13
|
+
"fmt"
|
14
|
+
|
15
|
+
"github.com/atomicjolt/string_utils"
|
16
|
+
<% end -%>
|
17
|
+
)
|
18
|
+
<% end -%>
|
19
|
+
|
20
|
+
type <%=struct_name(@model['id'])%> struct {
|
21
|
+
<%=fields&.join("\n ")%>
|
22
|
+
}
|
23
|
+
|
24
|
+
func (t *<%=struct_name(@model['id'])%>) HasErrors() error {
|
25
|
+
<% if field_validations && field_validations.length > 0 -%>
|
26
|
+
var s []string
|
27
|
+
errs := []string{}
|
28
|
+
<%field_validations.each do |name, prop|-%>
|
29
|
+
s = []string{<%=prop[:values].join(",")%>}
|
30
|
+
<% if prop[:type] == "array" %>
|
31
|
+
for _, v := range t.<%=go_name(name)%> {
|
32
|
+
if v != "" && !string_utils.Include(s, v) {
|
33
|
+
errs = append(errs, fmt.Sprintf("expected '<%=go_name(name)%>' to be one of %v", s))
|
34
|
+
}
|
35
|
+
}
|
36
|
+
<% else -%>
|
37
|
+
if t.<%=go_name(name)%> != "" && !string_utils.Include(s, t.<%=go_name(name)%>) {
|
38
|
+
errs = append(errs, fmt.Sprintf("expected '<%=go_name(name)%>' to be one of %v", s))
|
39
|
+
}
|
40
|
+
<% end -%>
|
41
|
+
<% end -%>
|
42
|
+
<% end -%>
|
43
|
+
return nil
|
44
|
+
}
|
@@ -1,3 +1,3 @@
|
|
1
1
|
field :<%= @nickname %>,
|
2
|
-
resolver: LMSGraphQL::Resolvers::Canvas::<%= @nickname
|
3
|
-
description: "<%= @summary %>. <%= @notes.gsub(/\n+/, " ").gsub("//", " ").gsub('"', "'") %>"
|
2
|
+
resolver: LMSGraphQL::Resolvers::Canvas::<%= graphql_resolver_class(@nickname) %>,
|
3
|
+
description: "<%= @summary %>. <%= @notes.gsub(/\n+/, " ").gsub("//", " ").gsub('"', "'") %>"
|
@@ -4,8 +4,8 @@ require_relative "../canvas_base_input_type"
|
|
4
4
|
module LMSGraphQL
|
5
5
|
module Types
|
6
6
|
module Canvas
|
7
|
-
<%=graphql_field_enums(@model)-%>
|
8
7
|
class Canvas<%=@model['id'].singularize%>Input < BaseInputObject
|
8
|
+
<%=graphql_field_enums(@model, true)-%>
|
9
9
|
description "<%=@description%>. API Docs: https://canvas.instructure.com/doc/api/<%=@name%>.html"
|
10
10
|
<%=graphql_fields(@model, @resource_name, true, true).join(" ")%>
|
11
11
|
end
|
@@ -4,7 +4,7 @@ require_relative "../canvas_base_resolver"
|
|
4
4
|
module LMSGraphQL
|
5
5
|
module Resolvers
|
6
6
|
module Canvas
|
7
|
-
class <%= @nickname
|
7
|
+
class <%= graphql_resolver_class(@nickname) %> < CanvasBaseResolver
|
8
8
|
type <%= type_from_operation(operation) %>, null: false
|
9
9
|
<% if operation["type"] == "array"
|
10
10
|
%> argument :get_all, Boolean, required: false
|
@@ -4,8 +4,8 @@ require_relative "../canvas_base_type"
|
|
4
4
|
module LMSGraphQL
|
5
5
|
module Types
|
6
6
|
module Canvas
|
7
|
-
<%=graphql_field_enums(@model)-%>
|
8
7
|
class Canvas<%=@model['id'].singularize%> < BaseType
|
8
|
+
<%=graphql_field_enums(@model)-%>
|
9
9
|
description "<%=@description%>. API Docs: https://canvas.instructure.com/doc/api/<%=@name%>.html"
|
10
10
|
<%=graphql_fields(@model, @resource_name).join(" ")%>
|
11
11
|
end
|