files.com 1.0.90
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/CONTRIBUTORS +4 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +82 -0
- data/LICENSE +21 -0
- data/README.md +119 -0
- data/Rakefile +12 -0
- data/SECURITY.md +24 -0
- data/_VERSION +1 -0
- data/bin/files +8 -0
- data/bin/files-console +16 -0
- data/docs/account_line_item.md +41 -0
- data/docs/action.md +37 -0
- data/docs/api_key.md +202 -0
- data/docs/app.md +57 -0
- data/docs/as2_key.md +133 -0
- data/docs/auto.md +11 -0
- data/docs/automation.md +190 -0
- data/docs/behavior.md +208 -0
- data/docs/bundle.md +252 -0
- data/docs/bundle_download.md +35 -0
- data/docs/clickwrap.md +143 -0
- data/docs/dns_record.md +35 -0
- data/docs/errors.md +17 -0
- data/docs/file.md +204 -0
- data/docs/file_action.md +126 -0
- data/docs/file_comment.md +116 -0
- data/docs/file_comment_reaction.md +62 -0
- data/docs/file_part_upload.md +37 -0
- data/docs/file_utils.md +4 -0
- data/docs/folder.md +90 -0
- data/docs/group.md +153 -0
- data/docs/group_user.md +124 -0
- data/docs/history.md +171 -0
- data/docs/history_export.md +174 -0
- data/docs/image.md +13 -0
- data/docs/invoice.md +72 -0
- data/docs/invoice_line_item.md +27 -0
- data/docs/ip_address.md +55 -0
- data/docs/lock.md +98 -0
- data/docs/message.md +147 -0
- data/docs/message_comment.md +132 -0
- data/docs/message_comment_reaction.md +94 -0
- data/docs/message_reaction.md +94 -0
- data/docs/notification.md +177 -0
- data/docs/payment.md +72 -0
- data/docs/payment_line_item.md +19 -0
- data/docs/permission.md +95 -0
- data/docs/preview.md +19 -0
- data/docs/project.md +121 -0
- data/docs/public_ip_address.md +13 -0
- data/docs/public_key.md +133 -0
- data/docs/remote_server.md +356 -0
- data/docs/request.md +100 -0
- data/docs/session.md +78 -0
- data/docs/site.md +448 -0
- data/docs/sso_strategy.md +114 -0
- data/docs/status.md +21 -0
- data/docs/style.md +93 -0
- data/docs/usage_daily_snapshot.md +45 -0
- data/docs/usage_snapshot.md +53 -0
- data/docs/user.md +535 -0
- data/docs/user_cipher_use.md +41 -0
- data/docs/user_request.md +93 -0
- data/files.com.gemspec +22 -0
- data/lib/files.com.rb +184 -0
- data/lib/files.com/api.rb +38 -0
- data/lib/files.com/api_client.rb +340 -0
- data/lib/files.com/errors.rb +41 -0
- data/lib/files.com/list.rb +95 -0
- data/lib/files.com/models/account_line_item.rb +82 -0
- data/lib/files.com/models/action.rb +77 -0
- data/lib/files.com/models/api_key.rb +270 -0
- data/lib/files.com/models/app.rb +101 -0
- data/lib/files.com/models/as2_key.rb +179 -0
- data/lib/files.com/models/auto.rb +17 -0
- data/lib/files.com/models/automation.rb +304 -0
- data/lib/files.com/models/behavior.rb +266 -0
- data/lib/files.com/models/bundle.rb +371 -0
- data/lib/files.com/models/bundle_download.rb +49 -0
- data/lib/files.com/models/clickwrap.rb +197 -0
- data/lib/files.com/models/dir.rb +3 -0
- data/lib/files.com/models/dns_record.rb +51 -0
- data/lib/files.com/models/errors.rb +22 -0
- data/lib/files.com/models/file.rb +968 -0
- data/lib/files.com/models/file_action.rb +126 -0
- data/lib/files.com/models/file_comment.rb +146 -0
- data/lib/files.com/models/file_comment_reaction.rb +100 -0
- data/lib/files.com/models/file_part_upload.rb +82 -0
- data/lib/files.com/models/file_utils.rb +118 -0
- data/lib/files.com/models/folder.rb +357 -0
- data/lib/files.com/models/group.rb +208 -0
- data/lib/files.com/models/group_user.rb +171 -0
- data/lib/files.com/models/history.rb +228 -0
- data/lib/files.com/models/history_export.rb +353 -0
- data/lib/files.com/models/image.rb +22 -0
- data/lib/files.com/models/invoice.rb +117 -0
- data/lib/files.com/models/invoice_line_item.rb +57 -0
- data/lib/files.com/models/ip_address.rb +66 -0
- data/lib/files.com/models/lock.rb +173 -0
- data/lib/files.com/models/message.rb +201 -0
- data/lib/files.com/models/message_comment.rb +165 -0
- data/lib/files.com/models/message_comment_reaction.rb +128 -0
- data/lib/files.com/models/message_reaction.rb +128 -0
- data/lib/files.com/models/notification.rb +263 -0
- data/lib/files.com/models/payment.rb +117 -0
- data/lib/files.com/models/payment_line_item.rb +37 -0
- data/lib/files.com/models/permission.rb +172 -0
- data/lib/files.com/models/preview.rb +37 -0
- data/lib/files.com/models/project.rb +140 -0
- data/lib/files.com/models/public_ip_address.rb +22 -0
- data/lib/files.com/models/public_key.rb +179 -0
- data/lib/files.com/models/remote_server.rb +680 -0
- data/lib/files.com/models/request.rb +179 -0
- data/lib/files.com/models/session.rb +247 -0
- data/lib/files.com/models/site.rb +733 -0
- data/lib/files.com/models/sso_strategy.rb +227 -0
- data/lib/files.com/models/status.rb +37 -0
- data/lib/files.com/models/style.rb +131 -0
- data/lib/files.com/models/usage_daily_snapshot.rb +66 -0
- data/lib/files.com/models/usage_snapshot.rb +96 -0
- data/lib/files.com/models/user.rb +876 -0
- data/lib/files.com/models/user_cipher_use.rb +63 -0
- data/lib/files.com/models/user_request.rb +127 -0
- data/lib/files.com/response.rb +25 -0
- data/lib/files.com/sizable_io.rb +32 -0
- data/lib/files.com/system_profiler.rb +56 -0
- data/lib/files.com/util.rb +106 -0
- data/lib/files.com/version.rb +5 -0
- data/spec/list_spec.rb +214 -0
- data/spec/models/file_spec.rb +68 -0
- data/spec/models/folder_spec.rb +40 -0
- data/spec/spec_helper.rb +36 -0
- data/test.sh +8 -0
- data/test/test.rb +75 -0
- metadata +235 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Files
|
4
|
+
class UserCipherUse
|
5
|
+
attr_reader :options, :attributes
|
6
|
+
|
7
|
+
def initialize(attributes = {}, options = {})
|
8
|
+
@attributes = attributes || {}
|
9
|
+
@options = options || {}
|
10
|
+
end
|
11
|
+
|
12
|
+
# int64 - UserCipherUse ID
|
13
|
+
def id
|
14
|
+
@attributes[:id]
|
15
|
+
end
|
16
|
+
|
17
|
+
# string - The protocol and cipher employed
|
18
|
+
def protocol_cipher
|
19
|
+
@attributes[:protocol_cipher]
|
20
|
+
end
|
21
|
+
|
22
|
+
# date-time - The earliest recorded use of this combination of interface and protocol and cipher (for this user)
|
23
|
+
def created_at
|
24
|
+
@attributes[:created_at]
|
25
|
+
end
|
26
|
+
|
27
|
+
# string - The interface accessed
|
28
|
+
def interface
|
29
|
+
@attributes[:interface]
|
30
|
+
end
|
31
|
+
|
32
|
+
# date-time - The most recent use of this combination of interface and protocol and cipher (for this user)
|
33
|
+
def updated_at
|
34
|
+
@attributes[:updated_at]
|
35
|
+
end
|
36
|
+
|
37
|
+
# int64 - ID of the user who performed this access
|
38
|
+
def user_id
|
39
|
+
@attributes[:user_id]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Parameters:
|
43
|
+
# user_id - int64 - User ID. Provide a value of `0` to operate the current session's user.
|
44
|
+
# page - int64 - Current page number.
|
45
|
+
# per_page - int64 - Number of records to show per page. (Max: 10,000, 1,000 or less is recommended).
|
46
|
+
# action - string - Deprecated: If set to `count` returns a count of matching records rather than the records themselves.
|
47
|
+
def self.list(params = {}, options = {})
|
48
|
+
raise InvalidParameterError.new("Bad parameter: user_id must be an Integer") if params.dig(:user_id) and !params.dig(:user_id).is_a?(Integer)
|
49
|
+
raise InvalidParameterError.new("Bad parameter: page must be an Integer") if params.dig(:page) and !params.dig(:page).is_a?(Integer)
|
50
|
+
raise InvalidParameterError.new("Bad parameter: per_page must be an Integer") if params.dig(:per_page) and !params.dig(:per_page).is_a?(Integer)
|
51
|
+
raise InvalidParameterError.new("Bad parameter: action must be an String") if params.dig(:action) and !params.dig(:action).is_a?(String)
|
52
|
+
|
53
|
+
response, options = Api.send_request("/user_cipher_uses", :get, params, options)
|
54
|
+
response.data.map do |entity_data|
|
55
|
+
UserCipherUse.new(entity_data, options)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.all(params = {}, options = {})
|
60
|
+
list(params, options)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Files
|
4
|
+
class UserRequest
|
5
|
+
attr_reader :options, :attributes
|
6
|
+
|
7
|
+
def initialize(attributes = {}, options = {})
|
8
|
+
@attributes = attributes || {}
|
9
|
+
@options = options || {}
|
10
|
+
end
|
11
|
+
|
12
|
+
# string - User's full name
|
13
|
+
def name
|
14
|
+
@attributes[:name]
|
15
|
+
end
|
16
|
+
|
17
|
+
def name=(value)
|
18
|
+
@attributes[:name] = value
|
19
|
+
end
|
20
|
+
|
21
|
+
# email - User email address
|
22
|
+
def email
|
23
|
+
@attributes[:email]
|
24
|
+
end
|
25
|
+
|
26
|
+
def email=(value)
|
27
|
+
@attributes[:email] = value
|
28
|
+
end
|
29
|
+
|
30
|
+
# string - Details of the user's request
|
31
|
+
def details
|
32
|
+
@attributes[:details]
|
33
|
+
end
|
34
|
+
|
35
|
+
def details=(value)
|
36
|
+
@attributes[:details] = value
|
37
|
+
end
|
38
|
+
|
39
|
+
def delete(params = {})
|
40
|
+
params ||= {}
|
41
|
+
params[:id] = @attributes[:id]
|
42
|
+
raise MissingParameterError.new("Current object doesn't have a id") unless @attributes[:id]
|
43
|
+
raise InvalidParameterError.new("Bad parameter: id must be an Integer") if params.dig(:id) and !params.dig(:id).is_a?(Integer)
|
44
|
+
raise MissingParameterError.new("Parameter missing: id") unless params.dig(:id)
|
45
|
+
|
46
|
+
Api.send_request("/user_requests/#{@attributes[:id]}", :delete, params, @options)
|
47
|
+
end
|
48
|
+
|
49
|
+
def destroy(params = {})
|
50
|
+
delete(params)
|
51
|
+
end
|
52
|
+
|
53
|
+
def save
|
54
|
+
if @attributes[:id]
|
55
|
+
raise NotImplementedError.new("The UserRequest object doesn't support updates.")
|
56
|
+
else
|
57
|
+
new_obj = UserRequest.create(@attributes, @options)
|
58
|
+
@attributes = new_obj.attributes
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Parameters:
|
63
|
+
# page - int64 - Current page number.
|
64
|
+
# per_page - int64 - Number of records to show per page. (Max: 10,000, 1,000 or less is recommended).
|
65
|
+
# action - string - Deprecated: If set to `count` returns a count of matching records rather than the records themselves.
|
66
|
+
def self.list(params = {}, options = {})
|
67
|
+
raise InvalidParameterError.new("Bad parameter: page must be an Integer") if params.dig(:page) and !params.dig(:page).is_a?(Integer)
|
68
|
+
raise InvalidParameterError.new("Bad parameter: per_page must be an Integer") if params.dig(:per_page) and !params.dig(:per_page).is_a?(Integer)
|
69
|
+
raise InvalidParameterError.new("Bad parameter: action must be an String") if params.dig(:action) and !params.dig(:action).is_a?(String)
|
70
|
+
|
71
|
+
response, options = Api.send_request("/user_requests", :get, params, options)
|
72
|
+
response.data.map do |entity_data|
|
73
|
+
UserRequest.new(entity_data, options)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.all(params = {}, options = {})
|
78
|
+
list(params, options)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Parameters:
|
82
|
+
# id (required) - int64 - User Request ID.
|
83
|
+
def self.find(id, params = {}, options = {})
|
84
|
+
params ||= {}
|
85
|
+
params[:id] = id
|
86
|
+
raise InvalidParameterError.new("Bad parameter: id must be an Integer") if params.dig(:id) and !params.dig(:id).is_a?(Integer)
|
87
|
+
raise MissingParameterError.new("Parameter missing: id") unless params.dig(:id)
|
88
|
+
|
89
|
+
response, options = Api.send_request("/user_requests/#{params[:id]}", :get, params, options)
|
90
|
+
UserRequest.new(response.data, options)
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.get(id, params = {}, options = {})
|
94
|
+
find(id, params, options)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Parameters:
|
98
|
+
# name (required) - string - Name of user requested
|
99
|
+
# email (required) - string - Email of user requested
|
100
|
+
# details (required) - string - Details of the user request
|
101
|
+
def self.create(params = {}, options = {})
|
102
|
+
raise InvalidParameterError.new("Bad parameter: name must be an String") if params.dig(:name) and !params.dig(:name).is_a?(String)
|
103
|
+
raise InvalidParameterError.new("Bad parameter: email must be an String") if params.dig(:email) and !params.dig(:email).is_a?(String)
|
104
|
+
raise InvalidParameterError.new("Bad parameter: details must be an String") if params.dig(:details) and !params.dig(:details).is_a?(String)
|
105
|
+
raise MissingParameterError.new("Parameter missing: name") unless params.dig(:name)
|
106
|
+
raise MissingParameterError.new("Parameter missing: email") unless params.dig(:email)
|
107
|
+
raise MissingParameterError.new("Parameter missing: details") unless params.dig(:details)
|
108
|
+
|
109
|
+
response, options = Api.send_request("/user_requests", :post, params, options)
|
110
|
+
UserRequest.new(response.data, options)
|
111
|
+
end
|
112
|
+
|
113
|
+
def self.delete(id, params = {}, options = {})
|
114
|
+
params ||= {}
|
115
|
+
params[:id] = id
|
116
|
+
raise InvalidParameterError.new("Bad parameter: id must be an Integer") if params.dig(:id) and !params.dig(:id).is_a?(Integer)
|
117
|
+
raise MissingParameterError.new("Parameter missing: id") unless params.dig(:id)
|
118
|
+
|
119
|
+
response, _options = Api.send_request("/user_requests/#{params[:id]}", :delete, params, options)
|
120
|
+
response.data
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.destroy(id, params = {}, options = {})
|
124
|
+
delete(id, params, options)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Files
|
4
|
+
class Response
|
5
|
+
attr_accessor :data, :http_body, :http_headers, :http_status
|
6
|
+
|
7
|
+
def self.from_faraday_hash(http_resp)
|
8
|
+
resp = new
|
9
|
+
resp.data = JSON.parse(http_resp[:body], symbolize_names: true) if http_resp[:status] != 204
|
10
|
+
resp.http_body = http_resp[:body]
|
11
|
+
resp.http_headers = http_resp[:headers]
|
12
|
+
resp.http_status = http_resp[:status]
|
13
|
+
resp
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.from_faraday_response(http_resp)
|
17
|
+
resp = new
|
18
|
+
resp.data = JSON.parse(http_resp.body, symbolize_names: true) if http_resp.status != 204
|
19
|
+
resp.http_body = http_resp.body
|
20
|
+
resp.http_headers = http_resp.headers
|
21
|
+
resp.http_status = http_resp.status
|
22
|
+
resp
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Files
|
2
|
+
class SizableIO < IO
|
3
|
+
def self.pipe
|
4
|
+
r, w = super
|
5
|
+
|
6
|
+
w.instance_variable_set(:@read_io, r)
|
7
|
+
|
8
|
+
[ r, w ]
|
9
|
+
end
|
10
|
+
|
11
|
+
def size
|
12
|
+
read_io.content_length_promise.wait.value
|
13
|
+
end
|
14
|
+
|
15
|
+
def fulfill_content_length(length)
|
16
|
+
read_io.content_length = length
|
17
|
+
read_io.content_length_promise.execute
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
attr_accessor :content_length
|
23
|
+
|
24
|
+
def content_length_promise
|
25
|
+
@content_length_promise ||= Concurrent::Promise.new { content_length }
|
26
|
+
end
|
27
|
+
|
28
|
+
def read_io
|
29
|
+
@read_io || self
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Files
|
4
|
+
class SystemProfiler
|
5
|
+
def self.uname
|
6
|
+
if ::File.exist?("/proc/version")
|
7
|
+
::File.read("/proc/version").strip
|
8
|
+
else
|
9
|
+
case RbConfig::CONFIG["host_os"]
|
10
|
+
when /linux|darwin|bsd|sunos|solaris|cygwin/i
|
11
|
+
uname_from_system
|
12
|
+
when /mswin|mingw/i
|
13
|
+
uname_from_system_ver
|
14
|
+
else
|
15
|
+
"unknown platform"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.uname_from_system
|
21
|
+
(`uname -a 2>/dev/null` || "").strip
|
22
|
+
rescue Errno::ENOENT
|
23
|
+
"uname executable not found"
|
24
|
+
rescue Errno::ENOMEM # couldn't create subprocess
|
25
|
+
"uname lookup failed"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.uname_from_system_ver
|
29
|
+
(`ver` || "").strip
|
30
|
+
rescue Errno::ENOENT
|
31
|
+
"ver executable not found"
|
32
|
+
rescue Errno::ENOMEM # couldn't create subprocess
|
33
|
+
"uname lookup failed"
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize
|
37
|
+
@uname = self.class.uname
|
38
|
+
end
|
39
|
+
|
40
|
+
def user_agent
|
41
|
+
lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
|
42
|
+
|
43
|
+
{
|
44
|
+
application: Files.app_info,
|
45
|
+
bindings_version: Files::VERSION,
|
46
|
+
lang: "ruby",
|
47
|
+
lang_version: lang_version,
|
48
|
+
platform: RUBY_PLATFORM,
|
49
|
+
engine: defined?(RUBY_ENGINE) ? RUBY_ENGINE : "",
|
50
|
+
publisher: "Action Verb LLC",
|
51
|
+
uname: @uname,
|
52
|
+
hostname: Socket.gethostname,
|
53
|
+
}.delete_if { |_k, v| v.nil? }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Files
|
4
|
+
module Util
|
5
|
+
OPTS = Set[:api_key, :client, :session_id].freeze
|
6
|
+
COLOR_CODES = {
|
7
|
+
black: 0, light_black: 60,
|
8
|
+
red: 1, light_red: 61,
|
9
|
+
green: 2, light_green: 62,
|
10
|
+
yellow: 3, light_yellow: 63,
|
11
|
+
blue: 4, light_blue: 64,
|
12
|
+
magenta: 5, light_magenta: 65,
|
13
|
+
cyan: 6, light_cyan: 66,
|
14
|
+
white: 7, light_white: 67,
|
15
|
+
default: 9,
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
def self.colorize(val, color, isatty)
|
19
|
+
return val unless isatty
|
20
|
+
|
21
|
+
mode = 0 # default
|
22
|
+
foreground = 30 + COLOR_CODES.fetch(color)
|
23
|
+
background = 40 + COLOR_CODES.fetch(:default)
|
24
|
+
|
25
|
+
"\033[#{mode};#{foreground};#{background}m#{val}\033[0m"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.level_name(level)
|
29
|
+
case level
|
30
|
+
when LEVEL_DEBUG then "debug"
|
31
|
+
when LEVEL_ERROR then "error"
|
32
|
+
when LEVEL_INFO then "info"
|
33
|
+
else level
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.log_error(message, data = {})
|
38
|
+
if !Files.logger.nil? ||
|
39
|
+
!Files.log_level.nil? && Files.log_level <= Files::LEVEL_ERROR
|
40
|
+
log_internal(message, data, color: :cyan, level: Files::LEVEL_ERROR,
|
41
|
+
logger: Files.logger, out: $stderr
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.log_info(message, data = {})
|
47
|
+
if !Files.logger.nil? ||
|
48
|
+
!Files.log_level.nil? && Files.log_level <= Files::LEVEL_INFO
|
49
|
+
log_internal(message, data, color: :cyan, level: Files::LEVEL_INFO,
|
50
|
+
logger: Files.logger, out: $stdout
|
51
|
+
)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.log_debug(message, data = {})
|
56
|
+
if !Files.logger.nil? ||
|
57
|
+
!Files.log_level.nil? && Files.log_level <= Files::LEVEL_DEBUG
|
58
|
+
log_internal(message, data, color: :blue, level: Files::LEVEL_DEBUG,
|
59
|
+
logger: Files.logger, out: $stdout
|
60
|
+
)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.log_internal(message, data = {}, color: nil, level: nil,
|
65
|
+
logger: nil, out: nil)
|
66
|
+
data_str = data.reject { |_k, v| v.nil? }
|
67
|
+
.map do |(k, v)|
|
68
|
+
format("%<key>s=%<value>s",
|
69
|
+
key: colorize(k, color, logger.nil? && !out.nil? && out.isatty),
|
70
|
+
value: v
|
71
|
+
)
|
72
|
+
end.join(" ")
|
73
|
+
|
74
|
+
if !logger.nil?
|
75
|
+
# the library's log levels are mapped to the same values as the
|
76
|
+
# standard library's logger
|
77
|
+
logger.log(level,
|
78
|
+
format("message=%<message>s %<data_str>s",
|
79
|
+
message: message,
|
80
|
+
data_str: data_str
|
81
|
+
)
|
82
|
+
)
|
83
|
+
elsif out.isatty
|
84
|
+
out.puts format("%<level>s %<message>s %<data_str>s",
|
85
|
+
level: colorize(level_name(level)[0, 4].upcase,
|
86
|
+
color, out.isatty
|
87
|
+
),
|
88
|
+
message: message,
|
89
|
+
data_str: data_str
|
90
|
+
)
|
91
|
+
else
|
92
|
+
out.puts format("message=%<message>s level=%<level>s %<data_str>s",
|
93
|
+
message: message,
|
94
|
+
level: level_name(level),
|
95
|
+
data_str: data_str
|
96
|
+
)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.check_api_key!(key)
|
101
|
+
raise TypeError, "api_key must be a string" unless key.is_a?(String)
|
102
|
+
|
103
|
+
key
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/spec/list_spec.rb
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe Files::List do
|
4
|
+
ResourceWrapper = Struct.new(:object, :options)
|
5
|
+
let(:options) { { client: client } }
|
6
|
+
let(:client) { instance_double(Files::ApiClient, cursor: nil) }
|
7
|
+
let(:params) { {} }
|
8
|
+
|
9
|
+
describe "#auto_paging_each" do
|
10
|
+
context "when per_page is set" do
|
11
|
+
let(:params) { { per_page: per_page } }
|
12
|
+
let(:per_page) { 3 }
|
13
|
+
|
14
|
+
context "when response includes a cursor" do
|
15
|
+
let(:client) { instance_double(Files::ApiClient) }
|
16
|
+
let(:stubbed_cursors) {
|
17
|
+
[
|
18
|
+
'3',
|
19
|
+
'6',
|
20
|
+
nil
|
21
|
+
]
|
22
|
+
}
|
23
|
+
|
24
|
+
before do
|
25
|
+
allow(client).to receive(:cursor).and_return(*stubbed_cursors)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "does not call the API until out of responses" do
|
29
|
+
server_results = ('a'..'h').to_a
|
30
|
+
times_block_yielded = 0
|
31
|
+
request_cursor = nil
|
32
|
+
response_cursor = nil
|
33
|
+
|
34
|
+
list = described_class.new(ResourceWrapper, params) {
|
35
|
+
times_block_yielded += 1
|
36
|
+
request_cursor = params[:cursor]
|
37
|
+
range_start = params[:cursor] ? params[:cursor].to_i : 0
|
38
|
+
|
39
|
+
response_data = server_results[range_start, per_page]
|
40
|
+
response_cursor = (range_start + per_page).to_s
|
41
|
+
[
|
42
|
+
instance_double(Files::Response, data: response_data, http_status: 200, http_headers: { "x-files-cursor" => response_cursor }),
|
43
|
+
options
|
44
|
+
]
|
45
|
+
}
|
46
|
+
results = list.auto_paging_each
|
47
|
+
expect(results.class).to eq(Enumerator::Lazy)
|
48
|
+
expect(times_block_yielded).to eq(0)
|
49
|
+
expect(results.next.object).to eq('a')
|
50
|
+
expect(times_block_yielded).to eq(1)
|
51
|
+
expect(request_cursor).to eq(nil)
|
52
|
+
expect(results.next.object).to eq('b')
|
53
|
+
expect(results.next.object).to eq('c')
|
54
|
+
expect(results.next.object).to eq('d')
|
55
|
+
expect(times_block_yielded).to eq(2)
|
56
|
+
expect(request_cursor).to eq("3")
|
57
|
+
expect(results.next.object).to eq('e')
|
58
|
+
expect(results.next.object).to eq('f')
|
59
|
+
expect(results.next.object).to eq('g')
|
60
|
+
expect(results.next.object).to eq('h')
|
61
|
+
expect(times_block_yielded).to eq(3)
|
62
|
+
expect(request_cursor).to eq("6")
|
63
|
+
end
|
64
|
+
|
65
|
+
it "stops calling the API once there is an error" do
|
66
|
+
server_results = ('a'..'h').to_a
|
67
|
+
times_block_yielded = 0
|
68
|
+
list = described_class.new(ResourceWrapper, params) {
|
69
|
+
times_block_yielded += 1
|
70
|
+
[
|
71
|
+
instance_double(Files::Response, data: server_results.shift(per_page), http_status: 400),
|
72
|
+
options
|
73
|
+
]
|
74
|
+
}
|
75
|
+
results = list.auto_paging_each
|
76
|
+
expect(results.count).to eq(0)
|
77
|
+
expect(times_block_yielded).to eq(1)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "when response does not include a cursor" do
|
82
|
+
let(:client) { instance_double(Files::ApiClient, cursor: nil) }
|
83
|
+
|
84
|
+
it "stops requesting any more results after the first try" do
|
85
|
+
server_results = ('a'..'h').to_a
|
86
|
+
times_block_yielded = 0
|
87
|
+
list = described_class.new(ResourceWrapper, params) {
|
88
|
+
times_block_yielded += 1
|
89
|
+
[
|
90
|
+
instance_double(Files::Response, data: server_results.shift(per_page), http_status: 200),
|
91
|
+
options
|
92
|
+
]
|
93
|
+
}
|
94
|
+
results = list.auto_paging_each
|
95
|
+
expect(results.count).to eq(3)
|
96
|
+
expect(times_block_yielded).to eq(1)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
it "returns all results at once" do
|
102
|
+
server_results = ('a'..'h').to_a
|
103
|
+
times_block_yielded = 0
|
104
|
+
list = described_class.new(ResourceWrapper, params) {
|
105
|
+
times_block_yielded += 1
|
106
|
+
[
|
107
|
+
instance_double(Files::Response, data: server_results, http_status: 200),
|
108
|
+
options
|
109
|
+
]
|
110
|
+
}
|
111
|
+
results = list.auto_paging_each
|
112
|
+
expect(results.count).to eq(8)
|
113
|
+
expect(times_block_yielded).to eq(1)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#each" do
|
118
|
+
it "returns all results at once" do
|
119
|
+
server_results = ('a'..'h').to_a
|
120
|
+
times_block_yielded = 0
|
121
|
+
results = described_class.new(ResourceWrapper, params) {
|
122
|
+
times_block_yielded += 1
|
123
|
+
[
|
124
|
+
instance_double(Files::Response, data: server_results, http_status: 200),
|
125
|
+
options
|
126
|
+
]
|
127
|
+
}
|
128
|
+
expect(results.count).to eq(8)
|
129
|
+
expect(times_block_yielded).to eq(1)
|
130
|
+
end
|
131
|
+
|
132
|
+
context "when per_page is set" do
|
133
|
+
let(:params) { { per_page: per_page } }
|
134
|
+
let(:per_page) { 3 }
|
135
|
+
|
136
|
+
context "when response includes a cursor" do
|
137
|
+
let(:client) { instance_double(Files::ApiClient, cursor: "XXX-XXX") }
|
138
|
+
|
139
|
+
it "does not call the API until out of responses" do
|
140
|
+
server_results = ('a'..'h').to_a
|
141
|
+
times_block_yielded = 0
|
142
|
+
list = described_class.new(ResourceWrapper, params) {
|
143
|
+
times_block_yielded += 1
|
144
|
+
[
|
145
|
+
instance_double(Files::Response, data: server_results.shift(per_page), http_status: 200),
|
146
|
+
options
|
147
|
+
]
|
148
|
+
}
|
149
|
+
results = list.enum_for(:each)
|
150
|
+
expect(times_block_yielded).to eq(0)
|
151
|
+
expect(results.next.object).to eq('a')
|
152
|
+
expect(times_block_yielded).to eq(1)
|
153
|
+
expect(results.next.object).to eq('b')
|
154
|
+
expect(results.next.object).to eq('c')
|
155
|
+
next_results = list.next_page.enum_for(:each)
|
156
|
+
expect(times_block_yielded).to eq(2)
|
157
|
+
expect(next_results.next.object).to eq('d')
|
158
|
+
expect(next_results.next.object).to eq('e')
|
159
|
+
expect(next_results.next.object).to eq('f')
|
160
|
+
next_results = list.next_page.enum_for(:each)
|
161
|
+
expect(times_block_yielded).to eq(3)
|
162
|
+
expect(next_results.next.object).to eq('g')
|
163
|
+
expect(next_results.next.object).to eq('h')
|
164
|
+
next_results = list.next_page.enum_for(:each)
|
165
|
+
expect(next_results.count).to eq(0)
|
166
|
+
end
|
167
|
+
|
168
|
+
it "return the same data when call more than once" do
|
169
|
+
server_results = ('a'..'h').to_a
|
170
|
+
list = described_class.new(ResourceWrapper, params) {
|
171
|
+
[
|
172
|
+
instance_double(Files::Response, data: server_results.shift(per_page), http_status: 200),
|
173
|
+
options
|
174
|
+
]
|
175
|
+
}
|
176
|
+
expect(list.to_a).to eq(list.to_a)
|
177
|
+
end
|
178
|
+
|
179
|
+
it "stops calling the API once there is an error" do
|
180
|
+
server_results = ('a'..'h').to_a
|
181
|
+
times_block_yielded = 0
|
182
|
+
results = described_class.new(ResourceWrapper, params) {
|
183
|
+
times_block_yielded += 1
|
184
|
+
[
|
185
|
+
instance_double(Files::Response, data: server_results, http_status: 400),
|
186
|
+
options
|
187
|
+
]
|
188
|
+
}
|
189
|
+
expect(results.count).to eq(0)
|
190
|
+
expect(times_block_yielded).to eq(1)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context "when response does not include a cursor" do
|
195
|
+
let(:client) { instance_double(Files::ApiClient, cursor: nil) }
|
196
|
+
|
197
|
+
it "stops requesting any more results after the first try" do
|
198
|
+
server_results = ('a'..'h').to_a
|
199
|
+
times_block_yielded = 0
|
200
|
+
list = described_class.new(ResourceWrapper, params) {
|
201
|
+
times_block_yielded += 1
|
202
|
+
[
|
203
|
+
instance_double(Files::Response, data: server_results, http_status: 200),
|
204
|
+
options
|
205
|
+
]
|
206
|
+
}
|
207
|
+
results = list.enum_for(:each)
|
208
|
+
expect(results.count).to eq(8)
|
209
|
+
expect(times_block_yielded).to eq(1)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|