lti-ruby-box 1.14.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,181 @@
1
+ require 'time'
2
+ require 'addressable/uri'
3
+
4
+ module RubyBox
5
+ class Item
6
+
7
+ @@has_many = []
8
+ @@has_many_paginated = []
9
+
10
+ def initialize( session, raw_item )
11
+ @session = session
12
+ @raw_item = raw_item
13
+ end
14
+
15
+ def self.has_many(*keys)
16
+ keys.each {|key| @@has_many << key.to_s}
17
+ end
18
+
19
+ def self.has_many_paginated(*keys)
20
+ keys.each {|key| @@has_many_paginated << key.to_s}
21
+ end
22
+
23
+ def move_to( folder_id, name=nil )
24
+ # Allow either a folder_id or a folder object
25
+ # to be passed in.
26
+ folder_id = folder_id.id if folder_id.instance_of?(RubyBox::Folder)
27
+
28
+ self.name = name if name
29
+ self.parent = {"id" => folder_id}
30
+
31
+ update
32
+ end
33
+
34
+ def update
35
+ reload_meta unless etag
36
+
37
+ url = "#{RubyBox::API_URL}/#{resource_name}/#{id}"
38
+ uri = URI.parse(url)
39
+
40
+ request = Net::HTTP::Put.new(uri.path, {
41
+ "if-match" => etag,
42
+ "Content-Type" => 'application/json'
43
+ })
44
+ request.body = JSON.dump(serialize)
45
+
46
+ @raw_item = @session.request(uri, request)
47
+ self
48
+ end
49
+
50
+ def create
51
+ url = "#{RubyBox::API_URL}/#{resource_name}"
52
+ uri = URI.parse(url)
53
+ request = Net::HTTP::Post.new( uri.request_uri )
54
+ request.body = JSON.dump(@raw_item)
55
+ resp = @session.request(uri, request)
56
+ @raw_item = resp
57
+ self
58
+ end
59
+
60
+ def delete(opts={})
61
+ url = "#{RubyBox::API_URL}/#{resource_name}/#{id}"
62
+ url = "#{url}#{Addressable::URI.new(:query_values => opts).to_s}" unless opts.keys.empty?
63
+ resp = @session.delete( url )
64
+ end
65
+
66
+ def reload_meta
67
+ url = "#{RubyBox::API_URL}/#{resource_name}/#{@raw_item['id']}"
68
+ @raw_item = @session.get( url )
69
+ self
70
+ end
71
+
72
+ def method_missing(method, *args, &block)
73
+ key = method.to_s
74
+
75
+ # Support has many and paginated has many relationships.
76
+ return many(key) if @@has_many.include?(key)
77
+ return paginated(key, args[0] || 100, args[1] || 0, args[2]) if @@has_many_paginated.include?(key)
78
+
79
+ # update @raw_item hash if this appears to be a setter.
80
+ setter = method.to_s.end_with?('=')
81
+ key = key[0...-1] if setter
82
+ @raw_item[key] = args[0] if setter and update_fields.include?(key)
83
+
84
+ # we may have a mini version of the object loaded, fix this.
85
+ reload_meta if @raw_item[key].nil? and has_mini_format?
86
+
87
+ if @raw_item[key].kind_of?(Hash)
88
+ return RubyBox::Item.factory(@session, @raw_item[key])
89
+ elsif RubyBox::ISO_8601_TEST.match(@raw_item[key].to_s)
90
+ return Time.parse(@raw_item[key])
91
+ else
92
+ return @raw_item[key]
93
+ end
94
+ end
95
+
96
+ # see http://developers.box.com/docs/#folders-create-a-shared-link-for-a-folder
97
+ # for a list of valid options.
98
+ def create_shared_link(opts={})
99
+ raise UnshareableResource unless ['folder', 'file'].include?(type)
100
+
101
+ opts = {
102
+ access: 'open'
103
+ }.merge(opts) if opts
104
+
105
+ url = "#{RubyBox::API_URL}/#{resource_name}/#{id}"
106
+ uri = URI.parse(url)
107
+
108
+ request = Net::HTTP::Put.new(uri.path, {
109
+ "Content-Type" => 'application/json'
110
+ })
111
+
112
+ request.body = JSON.dump({
113
+ shared_link: opts
114
+ })
115
+
116
+ @raw_item = @session.request(uri, request)
117
+ self
118
+ end
119
+
120
+ def disable_shared_link(opts={})
121
+ create_shared_link(nil)
122
+ end
123
+
124
+ def shared_link
125
+ return nil unless @raw_item['shared_link']
126
+ RubyBox::Item.factory(@session, @raw_item['shared_link'].merge('type' => 'shared_link'))
127
+ end
128
+
129
+ def as_json(opts={})
130
+ @raw_item
131
+ end
132
+
133
+ protected
134
+
135
+ def self.factory(session, entry)
136
+ type = entry['type'] ? entry['type'].split('_').map(&:capitalize).join('').to_sym : nil
137
+ if RubyBox.constants.include? type
138
+ RubyBox.const_get(type).new(session, entry)
139
+ else
140
+ RubyBox::Item.new(session, entry)
141
+ end
142
+ end
143
+
144
+ def has_mini_format?
145
+ false
146
+ end
147
+
148
+ private
149
+
150
+ def many(key)
151
+ url = "#{RubyBox::API_URL}/#{resource_name}/#{id}/#{key}"
152
+ resp = @session.get( url )
153
+ resp['entries'].map {|i| RubyBox::Item.factory(@session, i)}
154
+ end
155
+
156
+ def paginated(key, item_limit=100, offset=0, fields=nil)
157
+ Enumerator.new do |yielder|
158
+ while true
159
+ url = "#{RubyBox::API_URL}/#{resource_name}/#{id}/#{key}?limit=#{item_limit}&offset=#{offset}"
160
+ url = "#{url}&fields=#{fields.map(&:to_s).join(',')}" if fields
161
+ resp = @session.get( url )
162
+ resp['entries'].each do |entry|
163
+ yielder.yield(RubyBox::Item.factory(@session, entry))
164
+ end
165
+ offset += resp['entries'].count
166
+ break if resp['offset'].to_i + resp['limit'].to_i >= resp['total_count'].to_i
167
+ end
168
+ end
169
+ end
170
+
171
+ def serialize
172
+ update_fields.inject({}) {|hash, field| hash[field] = @raw_item[field]; hash}
173
+ end
174
+
175
+ def update_fields
176
+ ['name', 'description', 'parent']
177
+ end
178
+
179
+
180
+ end
181
+ end
@@ -0,0 +1,9 @@
1
+ module RubyBox
2
+ class LoginToken < Item
3
+
4
+ def resource_name
5
+ 'login_tokens'
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,137 @@
1
+ require 'oauth2'
2
+
3
+ module RubyBox
4
+ class Session
5
+
6
+ OAUTH2_URLS = {
7
+ :site => 'https://www.box.com',
8
+ :authorize_url => "/api/oauth2/authorize",
9
+ :token_url => "/api/oauth2/token"
10
+ }
11
+
12
+ def initialize(opts={}, backoff=0.1)
13
+
14
+ @backoff = backoff # try not to excessively hammer API.
15
+
16
+ if opts[:client_id]
17
+ @oauth2_client = OAuth2::Client.new(opts[:client_id], opts[:client_secret], OAUTH2_URLS.dup)
18
+ @access_token = OAuth2::AccessToken.new(@oauth2_client, opts[:access_token]) if opts[:access_token]
19
+ @refresh_token = opts[:refresh_token]
20
+ @as_user = opts[:as_user]
21
+ else # Support legacy API for historical reasons.
22
+ @api_key = opts[:api_key]
23
+ @auth_token = opts[:auth_token]
24
+ end
25
+ end
26
+
27
+ def authorize_url(redirect_uri, state=nil)
28
+ opts = { :redirect_uri => redirect_uri }
29
+ opts[:state] = state if state
30
+
31
+ @oauth2_client.auth_code.authorize_url(opts)
32
+ end
33
+
34
+ def get_access_token(code)
35
+ @access_token = @oauth2_client.auth_code.get_token(code)
36
+ end
37
+
38
+ def refresh_token(refresh_token)
39
+ refresh_access_token_obj = OAuth2::AccessToken.new(@oauth2_client, @access_token.token, {'refresh_token' => refresh_token})
40
+ @access_token = refresh_access_token_obj.refresh!
41
+ end
42
+
43
+ def build_auth_header
44
+ "BoxAuth api_key=#{@api_key}&auth_token=#{@auth_token}"
45
+ end
46
+
47
+ def get(url, raw=false)
48
+ uri = URI.parse(url)
49
+ request = Net::HTTP::Get.new( uri.request_uri )
50
+ resp = request( uri, request, raw )
51
+ end
52
+
53
+ def delete(url, raw=false)
54
+ uri = URI.parse(url)
55
+ request = Net::HTTP::Delete.new( uri.request_uri )
56
+ resp = request( uri, request, raw )
57
+ end
58
+
59
+ def request(uri, request, raw=false, retries=0)
60
+
61
+ http = Net::HTTP.new(uri.host, uri.port)
62
+ http.use_ssl = true
63
+ http.ssl_version = :SSLv3
64
+ #http.set_debug_output($stdout)
65
+
66
+ if @access_token
67
+ request.add_field('Authorization', "Bearer #{@access_token.token}")
68
+ else
69
+ request.add_field('Authorization', build_auth_header)
70
+ end
71
+
72
+
73
+ request.add_field('As-User', "#{@as_user}") if @as_user
74
+
75
+ response = http.request(request)
76
+
77
+ if response.is_a? Net::HTTPNotFound
78
+ raise RubyBox::ObjectNotFound
79
+ end
80
+
81
+ # Got unauthorized (401) status, try to refresh the token
82
+ if response.code.to_i == 401 and @refresh_token and retries == 0
83
+ refresh_token(@refresh_token)
84
+ return request(uri, request, raw, retries + 1)
85
+ end
86
+
87
+ sleep(@backoff) # try not to excessively hammer API.
88
+
89
+ handle_errors( response, raw )
90
+ end
91
+
92
+ def do_stream(url, opts)
93
+ params = {
94
+ :content_length_proc => opts[:content_length_proc],
95
+ :progress_proc => opts[:progress_proc]
96
+ }
97
+
98
+ if @access_token
99
+ params['Authorization'] = "Bearer #{@access_token.token}"
100
+ else
101
+ params['Authorization'] = build_auth_header
102
+ end
103
+
104
+ params['As-User'] = @as_user if @as_user
105
+
106
+ open(url, params)
107
+ end
108
+
109
+ def handle_errors( response, raw )
110
+ status = response.code.to_i
111
+ body = response.body
112
+ begin
113
+ parsed_body = JSON.parse(body)
114
+ rescue
115
+ msg = body.nil? || body.empty? ? "no data returned" : body
116
+ parsed_body = { "message" => msg }
117
+ end
118
+
119
+ # status is used to determine whether
120
+ # we need to refresh the access token.
121
+ parsed_body["status"] = status
122
+
123
+ case status / 100
124
+ when 3
125
+ # 302 Found. We should return the url
126
+ parsed_body["location"] = response["Location"] if status == 302
127
+ when 4
128
+ raise(RubyBox::ItemNameInUse.new(parsed_body, status, body), parsed_body["message"]) if parsed_body["code"] == "item_name_in_use"
129
+ raise(RubyBox::AuthError.new(parsed_body, status, body), parsed_body["message"]) if parsed_body["code"] == "unauthorized" || status == 401
130
+ raise(RubyBox::RequestError.new(parsed_body, status, body), parsed_body["message"])
131
+ when 5
132
+ raise(RubyBox::ServerError.new(parsed_body, status, body), parsed_body["message"])
133
+ end
134
+ raw ? body : parsed_body
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,10 @@
1
+ module RubyBox
2
+ class SharedLink < Item
3
+
4
+ private
5
+
6
+ def has_mini_format?
7
+ false
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,16 @@
1
+ module RubyBox
2
+ class User < Item
3
+
4
+ def enterprise
5
+ resp = @session.get( "#{RubyBox::API_URL}/users/#{id}?fields=enterprise" )
6
+ resp["enterprise"]
7
+ end
8
+
9
+ private
10
+
11
+ def resource_name
12
+ 'users'
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ module RubyBox
2
+ class WebLink < Item
3
+ end
4
+ end
@@ -0,0 +1,101 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "lti-ruby-box"
8
+ s.version = "1.14.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Attachments.me", "wbhumphrey"]
12
+ s.date = "2014-04-08"
13
+ s.description = "ruby gem for box.com 2.0 api"
14
+ s.email = "brad@instructure.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".travis.yml",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "README.markdown",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "lib/ruby-box.rb",
29
+ "lib/ruby-box/client.rb",
30
+ "lib/ruby-box/collaboration.rb",
31
+ "lib/ruby-box/comment.rb",
32
+ "lib/ruby-box/discussion.rb",
33
+ "lib/ruby-box/event.rb",
34
+ "lib/ruby-box/event_response.rb",
35
+ "lib/ruby-box/exceptions.rb",
36
+ "lib/ruby-box/file.rb",
37
+ "lib/ruby-box/folder.rb",
38
+ "lib/ruby-box/item.rb",
39
+ "lib/ruby-box/session.rb",
40
+ "lib/ruby-box/shared_link.rb",
41
+ "lib/ruby-box/user.rb",
42
+ "lib/ruby-box/web_link.rb",
43
+ "lib/ruby-box/login_token.rb",
44
+ "lti-ruby-box.gemspec",
45
+ # "spec/client_spec.rb",
46
+ # "spec/event_spec.rb",
47
+ # "spec/file_spec.rb",
48
+ # "spec/fixtures/comment_create.json",
49
+ # "spec/fixtures/events.json",
50
+ # "spec/fixtures/me.json",
51
+ # "spec/fixtures/users.json",
52
+ # "spec/folder_spec.rb",
53
+ # "spec/helper/account.example",
54
+ # "spec/helper/account.rb",
55
+ # "spec/integration_spec.rb",
56
+ # "spec/item_spec.rb",
57
+ # "spec/me_spec.rb",
58
+ # "spec/session_spec.rb",
59
+ # "spec/spec_helper.rb",
60
+ # "spec/users_spec.rb"
61
+ ]
62
+ s.homepage = "https://github.com/wbhumphrey/ruby-box"
63
+ s.licenses = ["MIT"]
64
+ s.require_paths = ["lib"]
65
+ s.rubygems_version = "2.0.3"
66
+ s.summary = "ruby gem for box.com 2.0 api"
67
+
68
+ if s.respond_to? :specification_version then
69
+ s.specification_version = 4
70
+
71
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
72
+ s.add_runtime_dependency(%q<multipart-post>, [">= 0"])
73
+ s.add_runtime_dependency(%q<oauth2>, [">= 0"])
74
+ s.add_runtime_dependency(%q<json>, [">= 0"])
75
+ s.add_runtime_dependency(%q<addressable>, [">= 0"])
76
+ s.add_development_dependency(%q<rspec>, [">= 0"])
77
+ s.add_development_dependency(%q<bundler>, [">= 0"])
78
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
79
+ s.add_development_dependency(%q<webmock>, [">= 0"])
80
+ else
81
+ s.add_dependency(%q<multipart-post>, [">= 0"])
82
+ s.add_dependency(%q<oauth2>, [">= 0"])
83
+ s.add_dependency(%q<json>, [">= 0"])
84
+ s.add_dependency(%q<addressable>, [">= 0"])
85
+ s.add_dependency(%q<rspec>, [">= 0"])
86
+ s.add_dependency(%q<bundler>, [">= 0"])
87
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
88
+ s.add_dependency(%q<webmock>, [">= 0"])
89
+ end
90
+ else
91
+ s.add_dependency(%q<multipart-post>, [">= 0"])
92
+ s.add_dependency(%q<oauth2>, [">= 0"])
93
+ s.add_dependency(%q<json>, [">= 0"])
94
+ s.add_dependency(%q<addressable>, [">= 0"])
95
+ s.add_dependency(%q<rspec>, [">= 0"])
96
+ s.add_dependency(%q<bundler>, [">= 0"])
97
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
98
+ s.add_dependency(%q<webmock>, [">= 0"])
99
+ end
100
+ end
101
+