Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 30 additions & 25 deletions lib/canvas-api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

module Canvas
class API
def initialize(args={})
def initialize(args={})
@host = args[:host] && args[:host].to_s
@token = args[:token] && args[:token].to_s
@client_id = args[:client_id] && args[:client_id].to_s
Expand All @@ -18,28 +18,28 @@ def initialize(args={})
raise "token or client_id required" if !@token && !@client_id
raise "secret required for client_id configuration" if @client_id && !@secret
end

attr_accessor :host
attr_accessor :token
attr_accessor :client_id

def masquerade_as(user_id)
@as_user_id = user_id && user_id.to_s
end

def stop_masquerading
@as_user_id = nil
end

def self.encode_id(prefix, id)
return nil unless prefix && id
"hex:#{prefix}:" + id.to_s.unpack("H*")[0]
end

def encode_id(prefix, id)
Canvas::API.encode_id(prefix, id)
end

def oauth_url(callback_url, scopes="")
raise "client_id required for oauth flow" unless @client_id
raise "secret required for oauth flow" unless @secret
Expand All @@ -49,11 +49,11 @@ def oauth_url(callback_url, scopes="")
scopes = scopes.length > 0 ? "&scopes=#{CGI.escape(scopes)}" : ""
"#{@host}/login/oauth2/auth?client_id=#{@client_id}&response_type=code&redirect_uri=#{CGI.escape(callback_url)}#{scopes}"
end

def login_url(callback_url)
oauth_url(callback_url, "/auth/userinfo")
end

def retrieve_access_token(code, callback_url)
raise "client_id required for oauth flow" unless @client_id
raise "secret required for oauth flow" unless @secret
Expand All @@ -67,11 +67,11 @@ def retrieve_access_token(code, callback_url)
end
res
end

def logout
!!delete("/login/oauth2/token")['logged_out']
end

def validate_call(endpoint)
raise "token required for api calls" unless @token
raise "missing host" unless @host
Expand All @@ -80,7 +80,7 @@ def validate_call(endpoint)
raise "invalid endpoint" unless endpoint.match(/^\/api\/v\d+\//) unless @token == 'ignore'
raise "invalid endpoint" unless (URI.parse(endpoint) rescue nil)
end

def generate_uri(endpoint, params=nil)
validate_call(endpoint)
unless @token == "ignore"
Expand All @@ -102,7 +102,7 @@ def generate_uri(endpoint, params=nil)
@http.use_ssl = @uri.scheme == 'https'
@uri
end

def retrieve_response(request)
request.options[:headers]['User-Agent'] = "CanvasAPI Ruby"
if @insecure
Expand All @@ -116,13 +116,18 @@ def retrieve_response(request)
end
raise ApiError.new("unexpected redirect to #{response.headers['Location']}") if response.code.to_s.match(/3\d\d/)
json = JSON.parse(response.body) rescue {'error' => 'invalid JSON'}

if json.is_a?(Hash) && json.size == 1 && json[json.keys[0]].is_a?(Array)
json = json[json.keys[0]].to_a
end

if !json.is_a?(Array)
raise ApiError.new(json['error']) if json['error']
raise ApiError.new(json['errors']) if json['errors']
if !response.code.to_s.match(/2\d\d/)
json['message'] ||= "unexpected error"
json['status'] ||= response.code.to_s
raise ApiError.new("#{json['status']} #{json['message']}")
raise ApiError.new("#{json['status']} #{json['message']}")
end
else
json = ResultSet.new(self, json)
Expand All @@ -133,12 +138,12 @@ def retrieve_response(request)
end
json
end

# Semi-hack so I can write better specs
def get_request(endpoint)
Typhoeus::Request.new(@uri.to_s, method: :get)
end

def get(endpoint, params=nil)
generate_uri(endpoint, params)
request = get_request(endpoint)
Expand All @@ -151,14 +156,14 @@ def delete(endpoint, params={})
request.options[:body] = clean_params(params)
retrieve_response(request)
end

def put(endpoint, params={})
generate_uri(endpoint, params['query_parameters'] || params[:query_parameters])
request = Typhoeus::Request.new(@uri.to_s, method: :put)
request.options[:body] = clean_params(params)
retrieve_response(request)
end

def post(endpoint, params={})
generate_uri(endpoint, params['query_parameters'] || params[:query_parameters])
request = Typhoeus::Request.new(@uri.to_s, method: :post)
Expand Down Expand Up @@ -194,7 +199,7 @@ def clean_params(params, prefix=nil)
end
res
end

def upload_file_from_local(endpoint, file, opts={})
raise "Missing File object" unless file.is_a?(File)
params = {
Expand All @@ -208,7 +213,7 @@ def upload_file_from_local(endpoint, file, opts={})
elsif opts[:parent_folder_path] || opts['parent_folder_path']
params[:parent_folder_path] = opts[:parent_folder_path] || opts['parent_folder_path']
end

res = post(endpoint, params)
if !res['upload_url']
raise ApiError.new("Unexpected error: #{res['message'] || 'no upload URL returned'}")
Expand All @@ -218,7 +223,7 @@ def upload_file_from_local(endpoint, file, opts={})
res = get(status_path)
res
end

def multipart_upload(url, upload_params, params, file)
req = Typhoeus::Request.new(url, method: :post)
upload_params.each do |k, v|
Expand All @@ -231,7 +236,7 @@ def multipart_upload(url, upload_params, params, file)
raise ApiError.new("Unexpected error: #{res.body}") if !res.headers['Location']
res.headers['Location']
end

def upload_file_from_url(endpoint, opts)
asynch = opts.delete('asynch') || opts.delete(:asynch)
['url', 'name', 'size'].each do |k|
Expand Down Expand Up @@ -273,11 +278,11 @@ def initialize(api, arr)
end
attr_accessor :next_endpoint
attr_accessor :link

def more?
!!next_endpoint
end

def next_page!
ResultSet.new(@api, []) unless next_endpoint
more = @api.get(next_endpoint)
Expand Down Expand Up @@ -317,4 +322,4 @@ def recursively_generate_pairs(h, prefix, pairs)
end
end
end
end
end