panoptes-client 0.2.7 → 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.hound.yml +2 -0
- data/.ruby-style.yml +206 -0
- data/CHANGELOG.md +8 -0
- data/data/doorkeeper-jwt-production.pub +14 -0
- data/data/doorkeeper-jwt-staging.pub +14 -0
- data/lib/panoptes/client.rb +53 -67
- data/lib/panoptes/client/cellect.rb +22 -0
- data/lib/panoptes/client/comments.rb +16 -0
- data/lib/panoptes/client/discussions.rb +1 -1
- data/lib/panoptes/client/me.rb +4 -1
- data/lib/panoptes/client/projects.rb +6 -6
- data/lib/panoptes/client/subject_sets.rb +5 -5
- data/lib/panoptes/client/subjects.rb +2 -2
- data/lib/panoptes/client/user_groups.rb +6 -6
- data/lib/panoptes/client/version.rb +1 -1
- data/lib/panoptes/client/workflows.rb +2 -2
- data/lib/panoptes/endpoints/base_endpoint.rb +102 -0
- data/lib/panoptes/endpoints/json_api_endpoint.rb +26 -0
- data/lib/panoptes/endpoints/json_endpoint.rb +18 -0
- data/lib/panoptes/session.rb +6 -0
- data/lib/panoptes/talk_client.rb +2 -22
- data/panoptes-client.gemspec +2 -0
- metadata +40 -3
- data/lib/panoptes/concerns/common_client.rb +0 -77
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3621f283592595fbf4099b4bfc445e5114b0e18e
|
4
|
+
data.tar.gz: 3a54d9787e2b0db82594ccd408376696161a780c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 516d1f3d47837241e73c0a30cc21ea3691c367b290a39284f088d98873d1c4aa8b2c63ba8b97ce2325dfc8befbedd170d4e473ca3497e2ca8cc0ec2dc8eeae43
|
7
|
+
data.tar.gz: 5d3f8289862edb747d826bce689ad3f3eff82ab310c7e7ff29d13998bfc807671982ae68baf3f8658cf0a5b793614da7c8b98cb45cc791d941556a4462c5b194
|
data/.hound.yml
ADDED
data/.ruby-style.yml
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
Exclude:
|
5
|
+
- "vendor/**/*"
|
6
|
+
- "db/schema.rb"
|
7
|
+
UseCache: false
|
8
|
+
|
9
|
+
Style/DotPosition:
|
10
|
+
Description: Checks the position of the dot in multi-line method calls.
|
11
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-multi-line-chains
|
12
|
+
Enabled: true
|
13
|
+
EnforcedStyle: leading
|
14
|
+
SupportedStyles:
|
15
|
+
- leading
|
16
|
+
- trailing
|
17
|
+
Style/FileName:
|
18
|
+
Description: Use snake_case for source file names.
|
19
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#snake-case-files
|
20
|
+
Enabled: true
|
21
|
+
Exclude: []
|
22
|
+
Style/GuardClause:
|
23
|
+
Description: Check for conditionals that can be replaced with guard clauses
|
24
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals
|
25
|
+
Enabled: false
|
26
|
+
MinBodyLength: 1
|
27
|
+
Style/IfUnlessModifier:
|
28
|
+
Description: Favor modifier if/unless usage when you have a single-line body.
|
29
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier
|
30
|
+
Enabled: false
|
31
|
+
MaxLineLength: 80
|
32
|
+
Style/OptionHash:
|
33
|
+
Description: Don't use option hashes when you can use keyword arguments.
|
34
|
+
Enabled: false
|
35
|
+
Style/ParallelAssignment:
|
36
|
+
Enabled: false
|
37
|
+
Style/PercentLiteralDelimiters:
|
38
|
+
Description: Use `%`-literal delimiters consistently
|
39
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-literal-braces
|
40
|
+
Enabled: false
|
41
|
+
PreferredDelimiters:
|
42
|
+
"%": "()"
|
43
|
+
"%i": "()"
|
44
|
+
"%q": "()"
|
45
|
+
"%Q": "()"
|
46
|
+
"%r": "{}"
|
47
|
+
"%s": "()"
|
48
|
+
"%w": "()"
|
49
|
+
"%W": "()"
|
50
|
+
"%x": "()"
|
51
|
+
Style/PredicateName:
|
52
|
+
Description: Check the names of predicate methods.
|
53
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark
|
54
|
+
Enabled: true
|
55
|
+
NamePrefix:
|
56
|
+
- is_
|
57
|
+
- has_
|
58
|
+
- have_
|
59
|
+
NamePrefixBlacklist:
|
60
|
+
- is_
|
61
|
+
Exclude:
|
62
|
+
- spec/**/*
|
63
|
+
Style/RaiseArgs:
|
64
|
+
Description: Checks the arguments passed to raise/fail.
|
65
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#exception-class-messages
|
66
|
+
Enabled: false
|
67
|
+
EnforcedStyle: exploded
|
68
|
+
SupportedStyles:
|
69
|
+
- compact
|
70
|
+
- exploded
|
71
|
+
Style/SignalException:
|
72
|
+
Description: Checks for proper usage of fail and raise.
|
73
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#fail-method
|
74
|
+
Enabled: false
|
75
|
+
EnforcedStyle: semantic
|
76
|
+
SupportedStyles:
|
77
|
+
- only_raise
|
78
|
+
- only_fail
|
79
|
+
- semantic
|
80
|
+
Style/SingleLineBlockParams:
|
81
|
+
Description: Enforces the names of some block params.
|
82
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#reduce-blocks
|
83
|
+
Enabled: false
|
84
|
+
Methods:
|
85
|
+
- reduce:
|
86
|
+
- a
|
87
|
+
- e
|
88
|
+
- inject:
|
89
|
+
- a
|
90
|
+
- e
|
91
|
+
Style/SingleLineMethods:
|
92
|
+
Description: Avoid single-line methods.
|
93
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-single-line-methods
|
94
|
+
Enabled: false
|
95
|
+
AllowIfMethodIsEmpty: true
|
96
|
+
Metrics/AbcSize:
|
97
|
+
Description: A calculated magnitude based on number of assignments, branches, and
|
98
|
+
conditions.
|
99
|
+
Enabled: false
|
100
|
+
Max: 15
|
101
|
+
Metrics/ClassLength:
|
102
|
+
Description: Avoid classes longer than 100 lines of code.
|
103
|
+
Enabled: false
|
104
|
+
CountComments: false
|
105
|
+
Max: 100
|
106
|
+
Metrics/LineLength:
|
107
|
+
Enabled: false
|
108
|
+
Metrics/ModuleLength:
|
109
|
+
CountComments: false
|
110
|
+
Max: 100
|
111
|
+
Description: Avoid modules longer than 100 lines of code.
|
112
|
+
Enabled: false
|
113
|
+
Metrics/CyclomaticComplexity:
|
114
|
+
Description: A complexity metric that is strongly correlated to the number of test
|
115
|
+
cases needed to validate a method.
|
116
|
+
Enabled: false
|
117
|
+
Max: 6
|
118
|
+
Metrics/MethodLength:
|
119
|
+
Description: Avoid methods longer than 10 lines of code.
|
120
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#short-methods
|
121
|
+
Enabled: false
|
122
|
+
CountComments: false
|
123
|
+
Max: 10
|
124
|
+
Metrics/ParameterLists:
|
125
|
+
Description: Avoid parameter lists longer than three or four parameters.
|
126
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#too-many-params
|
127
|
+
Enabled: false
|
128
|
+
Max: 5
|
129
|
+
CountKeywordArgs: true
|
130
|
+
Metrics/PerceivedComplexity:
|
131
|
+
Description: A complexity metric geared towards measuring complexity for a human
|
132
|
+
reader.
|
133
|
+
Enabled: false
|
134
|
+
Max: 7
|
135
|
+
Lint/AssignmentInCondition:
|
136
|
+
Description: Don't use assignment in conditions.
|
137
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition
|
138
|
+
Enabled: false
|
139
|
+
AllowSafeAssignment: true
|
140
|
+
Style/InlineComment:
|
141
|
+
Description: Avoid inline comments.
|
142
|
+
Enabled: false
|
143
|
+
Style/AccessorMethodName:
|
144
|
+
Description: Check the naming of accessor methods for get_/set_.
|
145
|
+
Enabled: false
|
146
|
+
Style/Alias:
|
147
|
+
Description: Use alias_method instead of alias.
|
148
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#alias-method
|
149
|
+
Enabled: false
|
150
|
+
Style/Documentation:
|
151
|
+
Description: Document classes and non-namespace modules.
|
152
|
+
Enabled: false
|
153
|
+
Style/DoubleNegation:
|
154
|
+
Description: Checks for uses of double negation (!!).
|
155
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-bang-bang
|
156
|
+
Enabled: false
|
157
|
+
Style/EachWithObject:
|
158
|
+
Description: Prefer `each_with_object` over `inject` or `reduce`.
|
159
|
+
Enabled: false
|
160
|
+
Style/EmptyLiteral:
|
161
|
+
Description: Prefer literals to Array.new/Hash.new/String.new.
|
162
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#literal-array-hash
|
163
|
+
Enabled: false
|
164
|
+
Style/ModuleFunction:
|
165
|
+
Description: Checks for usage of `extend self` in modules.
|
166
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#module-function
|
167
|
+
Enabled: false
|
168
|
+
Style/OneLineConditional:
|
169
|
+
Description: Favor the ternary operator(?:) over if/then/else/end constructs.
|
170
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#ternary-operator
|
171
|
+
Enabled: false
|
172
|
+
Style/PerlBackrefs:
|
173
|
+
Description: Avoid Perl-style regex back references.
|
174
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers
|
175
|
+
Enabled: false
|
176
|
+
Style/Send:
|
177
|
+
Description: Prefer `Object#__send__` or `Object#public_send` to `send`, as `send`
|
178
|
+
may overlap with existing methods.
|
179
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#prefer-public-send
|
180
|
+
Enabled: false
|
181
|
+
Style/SpecialGlobalVars:
|
182
|
+
Description: Avoid Perl-style global variables.
|
183
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms
|
184
|
+
Enabled: false
|
185
|
+
Style/VariableInterpolation:
|
186
|
+
Description: Don't interpolate global, instance and class variables directly in
|
187
|
+
strings.
|
188
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#curlies-interpolate
|
189
|
+
Enabled: false
|
190
|
+
Style/WhenThen:
|
191
|
+
Description: Use when x then ... for one-line cases.
|
192
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#one-line-cases
|
193
|
+
Enabled: false
|
194
|
+
Lint/EachWithObjectArgument:
|
195
|
+
Description: Check for immutable argument given to each_with_object.
|
196
|
+
Enabled: true
|
197
|
+
Lint/HandleExceptions:
|
198
|
+
Description: Don't suppress exception.
|
199
|
+
StyleGuide: https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions
|
200
|
+
Enabled: false
|
201
|
+
Lint/LiteralInCondition:
|
202
|
+
Description: Checks of literals used in conditions.
|
203
|
+
Enabled: false
|
204
|
+
Lint/LiteralInInterpolation:
|
205
|
+
Description: Checks for literals used in interpolation.
|
206
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
# 0.2.8
|
2
|
+
|
3
|
+
* Merged Client and TalkClient: `client.discussions` is now just on Client. TalkClient is still present as an alias for Client
|
4
|
+
* Add `client.create_comment` to post a comment in a talk discussions
|
5
|
+
* Add `client.current_user` to get information contained in the authentication token, if given
|
6
|
+
* Add `client.cellect_workflows` to get information on workflows using the cellect services
|
7
|
+
* Add `client.cellect_subjects` to get subject information for a given cellect workflow
|
8
|
+
|
1
9
|
# 0.2.7
|
2
10
|
|
3
11
|
* Add `TalkClient` to interact with the talk api.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
-----BEGIN PUBLIC KEY-----
|
2
|
+
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvbmZ42QexoMJ1J9z47Y2
|
3
|
+
7q5qvtE1mblpOnN7g4ItumcnoCv8xfdbhnzkHj/YBtqVoHhAVNwxSJKyQ4tZBehg
|
4
|
+
yYMRzLzBeWO8vG8V/NqM/tmUXca3rvPqt8I7zMoesSggawwz3/Gsa6KFC0OLjDh+
|
5
|
+
vE1HlqNX6usKiGmt6fv3KVU9cjtfREIieXgr36nkJDtIVJ2/hX1LY/v0+AEjZaFj
|
6
|
+
IzXSihNkjPnq2ymdm0YtV0Mmy1sK4qBY8c/zCWQ9lisILu+/Ix2YwVlDXeV9CErE
|
7
|
+
31b2jkPUVfLbCyeGPEIbYJw2pSiFWkuDR2VZaq+qeUbAwDfeu1OwueMZMt54vSYF
|
8
|
+
AKOxqMJtkrf8hxLSBZepk9sTS20T7gaEUyBhyeycarQqY34+VwG6UqLSy2H/Mq7r
|
9
|
+
5J8x7fnZPAtkFizcu/YDsELmD7Rw8SQ389NzApLi1jx8eSTZT+nqetU4FPs4CGCd
|
10
|
+
A/XMj2kAz/IA7LbV4hhbx1tTwTo88Xzk9knTknFv1/sE/j+KeUTeA9dE7EniIgOg
|
11
|
+
V01zobEXAP5Eyf3+OwYv+Qvq3cV2BvRZfEBhzj1RezVEh187hfCtCaSVf3YrEeL2
|
12
|
+
MM74OPotMaVyaJFxj/GxhrahOgSv4TbMYk93d+vcIa0clO7wXrJJXoWwi3XpQvk7
|
13
|
+
SwgqmRqSTqDuxJqlJAuVhmMCAwEAAQ==
|
14
|
+
-----END PUBLIC KEY-----
|
@@ -0,0 +1,14 @@
|
|
1
|
+
-----BEGIN PUBLIC KEY-----
|
2
|
+
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArqLiWfs+Nm3BBMu9bcma
|
3
|
+
JaFhfSpKoHwsFjzRzkdFO0uKXPkS5nJq3UD/ZORr31XKYmwlbhGBzvpBUSoTmsjj
|
4
|
+
AXXP9cOlX/opoojuII2JXoUPjZH+YDl4y4M7YzXLyVKYW0FYR2pBXyhtEL9Lx0Ny
|
5
|
+
Nw2DW6p7Z9RwoU46WkapjMWor2wAlpnUM4ngDM/7ysEg8oi9KExrXlI4MCH1sVqj
|
6
|
+
U++8zkIXarqyDnyVk94ZoGA8EEqjeK3s3HonGG/DZyoj7OMcRa81fm94Sage5PWd
|
7
|
+
sJfgUw8bcj3/h/boRIJSMwRv1IJVQxz2o44es6dN+12q3hpXBhCfVZWz3MgoJFpt
|
8
|
+
t3e+KHB3UDBEIo55aPgbUAeuWV1IrBqZIQWLZcce4pzgS+A+0JgeetwbzubjHfZu
|
9
|
+
8FQ/d+29M8N+R+TOS2WzVXCKzEZtw1BZ8V595X1Rf9FcklnA6CH32LybQD4/4ALz
|
10
|
+
JGx2WaCa2246pgJzT7fIo/L/bgRuEsBfwMR+wcOVr7yroFrndEyw1eGv2RuFsLNH
|
11
|
+
JwOjF+MTg/wtvaI8AXSTCSeKfoljUndNsiPTO8gJmiAq4yWFiMP1fKm/uczN6PKy
|
12
|
+
rYdQDSMt3a8UXZbw+9DocHDD0VvDHg6zuaa75tZrb7WvGrO7kbhUrJYwNCAbD2kN
|
13
|
+
Ca6VZnNmmy57yB/+jhBSNkECAwEAAQ==
|
14
|
+
-----END PUBLIC KEY-----
|
data/lib/panoptes/client.rb
CHANGED
@@ -1,19 +1,18 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
1
|
+
require 'panoptes/endpoints/json_api_endpoint'
|
2
|
+
require 'panoptes/endpoints/json_endpoint'
|
3
|
+
|
4
|
+
require 'panoptes/client/cellect'
|
5
|
+
require 'panoptes/client/comments'
|
6
|
+
require 'panoptes/client/discussions'
|
7
|
+
require 'panoptes/client/me'
|
8
|
+
require 'panoptes/client/projects'
|
9
|
+
require 'panoptes/client/subject_sets'
|
10
|
+
require 'panoptes/client/subjects'
|
11
|
+
require 'panoptes/client/user_groups'
|
12
|
+
require 'panoptes/client/workflows'
|
8
13
|
|
9
14
|
module Panoptes
|
10
15
|
class Client
|
11
|
-
class GenericError < StandardError; end
|
12
|
-
class ConnectionFailed < GenericError; end
|
13
|
-
class ResourceNotFound < GenericError; end
|
14
|
-
class ServerError < GenericError; end
|
15
|
-
|
16
|
-
include Panoptes::CommonClient
|
17
16
|
include Panoptes::Client::Me
|
18
17
|
include Panoptes::Client::Projects
|
19
18
|
include Panoptes::Client::Subjects
|
@@ -21,73 +20,60 @@ module Panoptes
|
|
21
20
|
include Panoptes::Client::UserGroups
|
22
21
|
include Panoptes::Client::Workflows
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
handle_response(response)
|
27
|
-
end
|
28
|
-
|
29
|
-
def post(path, body = {})
|
30
|
-
response = conn.post("/api" + path, body)
|
31
|
-
handle_response(response)
|
32
|
-
end
|
23
|
+
include Panoptes::Client::Discussions
|
24
|
+
include Panoptes::Client::Comments
|
33
25
|
|
34
|
-
|
35
|
-
headers = {}
|
36
|
-
headers["If-Match"] = etag if etag
|
26
|
+
include Panoptes::Client::Cellect
|
37
27
|
|
38
|
-
|
39
|
-
|
28
|
+
class GenericError < StandardError; end
|
29
|
+
class ConnectionFailed < GenericError; end
|
30
|
+
class ResourceNotFound < GenericError; end
|
31
|
+
class ServerError < GenericError; end
|
32
|
+
class NotLoggedIn < GenericError; end
|
33
|
+
|
34
|
+
attr_reader :env, :auth, :panoptes, :talk, :cellect
|
35
|
+
|
36
|
+
def initialize(env: :production, auth: {}, public_key_path: nil)
|
37
|
+
@env = env
|
38
|
+
@auth = auth
|
39
|
+
@public_key_path = public_key_path
|
40
|
+
@panoptes = Panoptes::Endpoints::JsonApiEndpoint.new(
|
41
|
+
auth: auth, url: panoptes_url, prefix: '/api'
|
42
|
+
)
|
43
|
+
@talk = Panoptes::Endpoints::JsonApiEndpoint.new(
|
44
|
+
auth: auth, url: talk_url
|
45
|
+
)
|
46
|
+
@cellect = Panoptes::Endpoints::JsonEndpoint.new(
|
47
|
+
url: panoptes_url, prefix: '/cellect'
|
48
|
+
)
|
40
49
|
end
|
41
50
|
|
42
|
-
def
|
43
|
-
|
44
|
-
headers["If-Match"] = etag if etag
|
51
|
+
def current_user
|
52
|
+
raise NotLoggedIn unless @auth[:token]
|
45
53
|
|
46
|
-
|
47
|
-
|
54
|
+
payload, = JWT.decode @auth[:token], jwt_signing_public_key, algorithm: 'RS512'
|
55
|
+
payload.fetch('data')
|
48
56
|
end
|
49
57
|
|
50
|
-
def
|
51
|
-
|
52
|
-
headers["If-Match"] = etag if etag
|
53
|
-
|
54
|
-
response = conn.delete("/api" + path, query, headers)
|
55
|
-
handle_response(response)
|
58
|
+
def jwt_signing_public_key
|
59
|
+
@jwt_signing_public_key ||= OpenSSL::PKey::RSA.new(File.read(@public_key_path))
|
56
60
|
end
|
57
61
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
last_response = get(next_path, query)
|
65
|
-
if block_given?
|
66
|
-
yield data, last_response
|
67
|
-
else
|
68
|
-
data[resource].concat(last_response[resource]) if data[resource].is_a?(Array)
|
69
|
-
data["meta"][resource].merge!(last_response["meta"][resource])
|
70
|
-
data["links"].merge!(last_response["links"])
|
71
|
-
end
|
62
|
+
def panoptes_url
|
63
|
+
case env
|
64
|
+
when :production, 'production'.freeze
|
65
|
+
'https://panoptes.zooniverse.org'.freeze
|
66
|
+
else
|
67
|
+
'https://panoptes-staging.zooniverse.org'.freeze
|
72
68
|
end
|
73
|
-
|
74
|
-
data
|
75
|
-
end
|
76
|
-
|
77
|
-
private
|
78
|
-
|
79
|
-
def conn
|
80
|
-
@conn
|
81
69
|
end
|
82
70
|
|
83
|
-
def
|
84
|
-
case
|
85
|
-
when
|
86
|
-
|
87
|
-
when 400..600
|
88
|
-
raise ServerError.new(response.body)
|
71
|
+
def talk_url
|
72
|
+
case env
|
73
|
+
when :production, 'production'.freeze
|
74
|
+
'https://talk.zooniverse.org'.freeze
|
89
75
|
else
|
90
|
-
|
76
|
+
'https://talk-staging.zooniverse.org'.freeze
|
91
77
|
end
|
92
78
|
end
|
93
79
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module Panoptes
|
4
|
+
class Client
|
5
|
+
module Cellect
|
6
|
+
# Fetches all cellect-enabled, launched workflows.
|
7
|
+
#
|
8
|
+
# @return [Hash] the list of workflows
|
9
|
+
def cellect_workflows
|
10
|
+
cellect.get '/workflows'
|
11
|
+
end
|
12
|
+
|
13
|
+
# Fetches all active subjects for a cellect-enabled workflow.
|
14
|
+
#
|
15
|
+
# @param workflow_id [Integer] the id of the workflow
|
16
|
+
# @return [Hash] the list of subjects
|
17
|
+
def cellect_subjects(workflow_id)
|
18
|
+
cellect.get '/subjects', workflow_id: workflow_id
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Panoptes
|
2
|
+
class Client
|
3
|
+
module Comments
|
4
|
+
# Post a comment to a talk discussion
|
5
|
+
#
|
6
|
+
# @param discussion_id [Integer] filter by focussable id
|
7
|
+
# @param focus_type [String] filter by focussable type
|
8
|
+
# @return list of discussions
|
9
|
+
def create_comment(discussion_id:, body:)
|
10
|
+
user_id = current_user["id"]
|
11
|
+
response = talk.post("/comments", comments: {discussion_id: discussion_id, body: body, user_id: user_id})
|
12
|
+
response.fetch("comments")[0]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/panoptes/client/me.rb
CHANGED
@@ -10,7 +10,7 @@ module Panoptes
|
|
10
10
|
params = {}
|
11
11
|
params[:search] = search if search
|
12
12
|
|
13
|
-
paginate("/projects", params)["projects"]
|
13
|
+
panoptes.paginate("/projects", params)["projects"]
|
14
14
|
end
|
15
15
|
|
16
16
|
# Starts a background process to generate a new CSV export of all the classifications in the project.
|
@@ -19,7 +19,7 @@ module Panoptes
|
|
19
19
|
# @return [Hash] the medium information where the export will be stored when it's generated
|
20
20
|
def create_classifications_export(project_id)
|
21
21
|
params = {media: {content_type: "text/csv", metadata: { recipients: []}}}
|
22
|
-
post("/projects/#{project_id}/classifications_export", params)["media"].first
|
22
|
+
panoptes.post("/projects/#{project_id}/classifications_export", params)["media"].first
|
23
23
|
end
|
24
24
|
|
25
25
|
# Starts a background process to generate a new CSV export of all the subjects in the project.
|
@@ -28,7 +28,7 @@ module Panoptes
|
|
28
28
|
# @return [Hash] the medium information where the export will be stored when it's generated
|
29
29
|
def create_subjects_export(project_id)
|
30
30
|
params = {media: {content_type: "text/csv", metadata: { recipients: []}}}
|
31
|
-
post("/projects/#{project_id}/subjects_export", params)["media"].first
|
31
|
+
panoptes.post("/projects/#{project_id}/subjects_export", params)["media"].first
|
32
32
|
end
|
33
33
|
|
34
34
|
# Starts a background process to generate a new CSV export of all the workflows in the project.
|
@@ -37,7 +37,7 @@ module Panoptes
|
|
37
37
|
# @return [Hash] the medium information where the export will be stored when it's generated
|
38
38
|
def create_workflows_export(project_id)
|
39
39
|
params = {media: {content_type: "text/csv", metadata: { recipients: []}}}
|
40
|
-
post("/projects/#{project_id}/workflows_export", params)["media"].first
|
40
|
+
panoptes.post("/projects/#{project_id}/workflows_export", params)["media"].first
|
41
41
|
end
|
42
42
|
|
43
43
|
# Starts a background process to generate a new CSV export of all the workflow_contents in the project.
|
@@ -46,7 +46,7 @@ module Panoptes
|
|
46
46
|
# @return [Hash] the medium information where the export will be stored when it's generated
|
47
47
|
def create_workflow_contents_export(project_id)
|
48
48
|
params = {media: {content_type: "text/csv", metadata: { recipients: []}}}
|
49
|
-
post("/projects/#{project_id}/workflow_contents_export", params)["media"].first
|
49
|
+
panoptes.post("/projects/#{project_id}/workflow_contents_export", params)["media"].first
|
50
50
|
end
|
51
51
|
|
52
52
|
# Starts a background process to generate a new CSV export of the aggretation results of the project.
|
@@ -55,7 +55,7 @@ module Panoptes
|
|
55
55
|
# @return [Hash] the medium information where the export will be stored when it's generated
|
56
56
|
def create_aggregations_export(project_id)
|
57
57
|
params = {media: {content_type: "application/x-gzip", metadata: { recipients: []}}}
|
58
|
-
post("/projects/#{project_id}/aggregations_export", params)["media"].first
|
58
|
+
panoptes.post("/projects/#{project_id}/aggregations_export", params)["media"].first
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
@@ -2,25 +2,25 @@ module Panoptes
|
|
2
2
|
class Client
|
3
3
|
module SubjectSets
|
4
4
|
def subject_set(subject_set_id)
|
5
|
-
response = get("/subject_sets/#{subject_set_id}")
|
5
|
+
response = panoptes.get("/subject_sets/#{subject_set_id}")
|
6
6
|
response.fetch("subject_sets").find {|i| i.fetch("id").to_s == subject_set_id.to_s }
|
7
7
|
end
|
8
8
|
|
9
9
|
def create_subject_set(attributes)
|
10
|
-
response = post("/subject_sets", subject_sets: attributes)
|
10
|
+
response = panoptes.post("/subject_sets", subject_sets: attributes)
|
11
11
|
response.fetch("subject_sets").first
|
12
12
|
end
|
13
13
|
|
14
14
|
def update_subject_set(subject_set_id, attributes)
|
15
|
-
response =
|
15
|
+
response = panoptes.connection.get("/api/subject_sets/#{subject_set_id}")
|
16
16
|
etag = response.headers["ETag"]
|
17
17
|
|
18
|
-
response = put("/subject_sets/#{subject_set_id}", {subject_sets: attributes}, etag: etag)
|
18
|
+
response = panoptes.put("/subject_sets/#{subject_set_id}", {subject_sets: attributes}, etag: etag)
|
19
19
|
response.fetch("subject_sets").first
|
20
20
|
end
|
21
21
|
|
22
22
|
def add_subjects_to_subject_set(subject_set_id, subject_ids)
|
23
|
-
response = post("/subject_sets/#{subject_set_id}/links/subjects", subjects: subject_ids)
|
23
|
+
response = panoptes.post("/subject_sets/#{subject_set_id}/links/subjects", subjects: subject_ids)
|
24
24
|
true
|
25
25
|
end
|
26
26
|
end
|
@@ -9,7 +9,7 @@ module Panoptes
|
|
9
9
|
query = {}
|
10
10
|
query[:subject_set_id] = subject_set_id
|
11
11
|
|
12
|
-
response = get("/subjects", query)
|
12
|
+
response = panoptes.get("/subjects", query)
|
13
13
|
response.fetch("subjects")
|
14
14
|
end
|
15
15
|
|
@@ -20,7 +20,7 @@ module Panoptes
|
|
20
20
|
# @param subject_id [Integer] the ID of a subject associated with that workflow (through one of the assigned subject_sets)
|
21
21
|
# @return nothing
|
22
22
|
def retire_subject(workflow_id, subject_id, reason: nil)
|
23
|
-
post("/workflows/#{workflow_id}/retired_subjects", {
|
23
|
+
panoptes.post("/workflows/#{workflow_id}/retired_subjects", {
|
24
24
|
admin: true,
|
25
25
|
subject_id: subject_id,
|
26
26
|
retirement_reason: reason
|
@@ -7,31 +7,31 @@ module Panoptes
|
|
7
7
|
# @param name [String] The name of the user group. Must be unique for the entirity of Zooniverse.
|
8
8
|
# @return [Hash] The created user group.
|
9
9
|
def create_user_group(name)
|
10
|
-
post("/user_groups", user_groups: {
|
10
|
+
panoptes.post("/user_groups", user_groups: {
|
11
11
|
name: name
|
12
12
|
})["user_groups"][0]
|
13
13
|
end
|
14
14
|
|
15
15
|
def user_groups
|
16
|
-
get("/user_groups")["user_groups"]
|
16
|
+
panoptes.get("/user_groups")["user_groups"]
|
17
17
|
end
|
18
18
|
|
19
19
|
def join_user_group(user_group_id, user_id, join_token:)
|
20
|
-
post("/memberships", memberships: {
|
20
|
+
panoptes.post("/memberships", memberships: {
|
21
21
|
join_token: join_token,
|
22
22
|
links: {user: user_id, user_group: user_group_id}
|
23
23
|
})["memberships"][0]
|
24
24
|
end
|
25
25
|
|
26
26
|
def remove_user_from_user_group(user_group_id, user_id)
|
27
|
-
delete("/user_groups/#{user_group_id}/links/users/#{user_id}")
|
27
|
+
panoptes.delete("/user_groups/#{user_group_id}/links/users/#{user_id}")
|
28
28
|
end
|
29
29
|
|
30
30
|
def delete_user_group(user_group_id)
|
31
|
-
response =
|
31
|
+
response = panoptes.connection.get("/api/user_groups/#{user_group_id}")
|
32
32
|
etag = response.headers["ETag"]
|
33
33
|
|
34
|
-
delete("/user_groups/#{user_group_id}", {}, etag: etag)
|
34
|
+
panoptes.delete("/user_groups/#{user_group_id}", {}, etag: etag)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -2,12 +2,12 @@ module Panoptes
|
|
2
2
|
class Client
|
3
3
|
module Workflows
|
4
4
|
def workflow(workflow_id)
|
5
|
-
response = get("/workflows/#{workflow_id}")
|
5
|
+
response = panoptes.get("/workflows/#{workflow_id}")
|
6
6
|
response.fetch("workflows").find {|i| i.fetch("id").to_s == workflow_id.to_s }
|
7
7
|
end
|
8
8
|
|
9
9
|
def create_workflow(attributes)
|
10
|
-
response = post("/workflows", workflows: attributes)
|
10
|
+
response = panoptes.post("/workflows", workflows: attributes)
|
11
11
|
response.fetch("workflows").first
|
12
12
|
end
|
13
13
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
require 'faraday/panoptes'
|
4
|
+
|
5
|
+
module Panoptes
|
6
|
+
module Endpoints
|
7
|
+
class BaseEndpoint
|
8
|
+
attr_reader :auth, :url, :prefix
|
9
|
+
|
10
|
+
# @param auth [Hash<token: String, client_id: String, client_secret: String>] Authentication details
|
11
|
+
# * either nothing,
|
12
|
+
# * a hash with +:token+ (an existing OAuth user token),
|
13
|
+
# * or a hash with +:client_id+ and +:client_secret+
|
14
|
+
# (a keypair for an OAuth Application).
|
15
|
+
# @param url [String] API location to use.
|
16
|
+
# @param prefix [String] An optional API url prefix
|
17
|
+
# @yield Allows an optional block to configure the faraday connection
|
18
|
+
# @yieldparam faraday [Faraday::Connection] The faraday connection
|
19
|
+
def initialize(auth: {}, url: nil, prefix: nil, &config)
|
20
|
+
@auth = auth
|
21
|
+
@url = url
|
22
|
+
@prefix = prefix
|
23
|
+
@config = config
|
24
|
+
end
|
25
|
+
|
26
|
+
def connection
|
27
|
+
@connection ||= Faraday.new(url) do |faraday|
|
28
|
+
auth_request faraday, auth
|
29
|
+
configure faraday
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def get(path, query = {})
|
34
|
+
request :get, path, query
|
35
|
+
end
|
36
|
+
|
37
|
+
def post(path, body = {})
|
38
|
+
request :post, path, body
|
39
|
+
end
|
40
|
+
|
41
|
+
def put(path, body = {}, etag: nil)
|
42
|
+
request :put, path, body, etag_header(etag)
|
43
|
+
end
|
44
|
+
|
45
|
+
def patch(path, body = {}, etag: nil)
|
46
|
+
request :patch, path, body, etag_header(etag)
|
47
|
+
end
|
48
|
+
|
49
|
+
def delete(path, query = {}, etag: nil)
|
50
|
+
request :delete, path, query, etag_header(etag)
|
51
|
+
end
|
52
|
+
|
53
|
+
def etag_header(etag)
|
54
|
+
{}.tap do |headers|
|
55
|
+
headers['If-Match'] = etag if etag
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def request(method, path, *args)
|
60
|
+
path = "#{prefix}/#{path}" if prefix
|
61
|
+
handle_response connection.send(method, path, *args)
|
62
|
+
end
|
63
|
+
|
64
|
+
def handle_response(response)
|
65
|
+
case response.status
|
66
|
+
when 404
|
67
|
+
raise ResourceNotFound, status: response.status, body: response.body
|
68
|
+
when 400..600
|
69
|
+
raise ServerError.new, response.body
|
70
|
+
else
|
71
|
+
response.body
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
|
77
|
+
def configure(faraday)
|
78
|
+
if @config
|
79
|
+
@config.call faraday
|
80
|
+
else
|
81
|
+
faraday.request :panoptes_api_v1
|
82
|
+
faraday.request :json
|
83
|
+
faraday.response :json
|
84
|
+
faraday.adapter Faraday.default_adapter
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def auth_request(faraday, auth)
|
89
|
+
if auth[:token]
|
90
|
+
faraday.request :panoptes_access_token,
|
91
|
+
url: url,
|
92
|
+
access_token: auth[:token]
|
93
|
+
elsif auth[:client_id] && auth[:client_secret]
|
94
|
+
faraday.request :panoptes_client_credentials,
|
95
|
+
url: url,
|
96
|
+
client_id: auth[:client_id],
|
97
|
+
client_secret: auth[:client_secret]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'base_endpoint'
|
2
|
+
|
3
|
+
module Panoptes
|
4
|
+
module Endpoints
|
5
|
+
class JsonApiEndpoint < BaseEndpoint
|
6
|
+
# Get a path and perform automatic depagination
|
7
|
+
def paginate(path, query, resource: nil)
|
8
|
+
resource = path.split('/').last if resource.nil?
|
9
|
+
data = last_response = get(path, query)
|
10
|
+
|
11
|
+
while next_path = last_response['meta'][resource]['next_href']
|
12
|
+
last_response = get(next_path, query)
|
13
|
+
if block_given?
|
14
|
+
yield data, last_response
|
15
|
+
else
|
16
|
+
data[resource].concat(last_response[resource]) if data[resource].is_a?(Array)
|
17
|
+
data['meta'][resource].merge!(last_response['meta'][resource])
|
18
|
+
data['links'].merge!(last_response['links'])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
data
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'base_endpoint'
|
2
|
+
|
3
|
+
module Panoptes
|
4
|
+
module Endpoints
|
5
|
+
class JsonEndpoint < BaseEndpoint
|
6
|
+
# Automatically configured connection to use JSON requests/responses
|
7
|
+
# @see Panoptes::Endpoints::BaseEndpoint#initialize
|
8
|
+
def initialize(auth: {}, url: nil, prefix: nil, &config)
|
9
|
+
super auth: auth, url: url, prefix: prefix do |faraday|
|
10
|
+
config&.call faraday
|
11
|
+
faraday.request :json
|
12
|
+
faraday.response :json
|
13
|
+
faraday.adapter Faraday.default_adapter
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/panoptes/talk_client.rb
CHANGED
@@ -1,25 +1,5 @@
|
|
1
|
-
require "panoptes/concerns/common_client"
|
2
|
-
require "panoptes/client/discussions"
|
3
|
-
|
4
1
|
module Panoptes
|
5
|
-
|
6
|
-
|
7
|
-
include Panoptes::Client::Discussions
|
8
|
-
|
9
|
-
# @param auth [Hash] Authentication details
|
10
|
-
# * either nothing,
|
11
|
-
# * a hash with +:token+ (an existing OAuth user token),
|
12
|
-
# * or a hash with +:client_id+ and +:client_secret+ (a keypair for an OAuth Application).
|
13
|
-
# A client is the main interface to the talk v2 API.
|
14
|
-
# @param url [String] Optional override for the API location to use. Defaults to the official talk api production environment.
|
15
|
-
# @param auth_url [String] Optional override for the auth API location to use. Defaults to the official api production environment.
|
16
|
-
def initialize(auth: {}, url: PROD_TALK_API_URL, auth_url: PROD_API_URL)
|
17
|
-
super(auth: auth, url: url, auth_url: auth_url)
|
18
|
-
end
|
19
|
-
|
20
|
-
def get(path, query = {})
|
21
|
-
response = conn.get(path, query)
|
22
|
-
handle_response(response)
|
23
|
-
end
|
2
|
+
# Backwards compat
|
3
|
+
class TalkClient < Client
|
24
4
|
end
|
25
5
|
end
|
data/panoptes-client.gemspec
CHANGED
@@ -20,9 +20,11 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_dependency "faraday"
|
22
22
|
spec.add_dependency "faraday-panoptes", "~> 0.2.0"
|
23
|
+
spec.add_dependency "jwt", "~> 1.5.0"
|
23
24
|
|
24
25
|
spec.add_development_dependency "bundler", "~> 1.11"
|
25
26
|
spec.add_development_dependency "rake", "~> 10.0"
|
26
27
|
spec.add_development_dependency "rspec", "~> 3.0"
|
28
|
+
spec.add_development_dependency "timecop", "~> 0.8.0"
|
27
29
|
spec.add_development_dependency "yard"
|
28
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: panoptes-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marten Veldthuis
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.2.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: jwt
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.5.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.5.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: bundler
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +94,20 @@ dependencies:
|
|
80
94
|
- - "~>"
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '3.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: timecop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.8.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.8.0
|
83
111
|
- !ruby/object:Gem::Dependency
|
84
112
|
name: yard
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -102,7 +130,9 @@ extensions: []
|
|
102
130
|
extra_rdoc_files: []
|
103
131
|
files:
|
104
132
|
- ".gitignore"
|
133
|
+
- ".hound.yml"
|
105
134
|
- ".rspec"
|
135
|
+
- ".ruby-style.yml"
|
106
136
|
- ".travis.yml"
|
107
137
|
- CHANGELOG.md
|
108
138
|
- CODE_OF_CONDUCT.md
|
@@ -112,8 +142,12 @@ files:
|
|
112
142
|
- Rakefile
|
113
143
|
- bin/console
|
114
144
|
- bin/setup
|
145
|
+
- data/doorkeeper-jwt-production.pub
|
146
|
+
- data/doorkeeper-jwt-staging.pub
|
115
147
|
- lib/panoptes-client.rb
|
116
148
|
- lib/panoptes/client.rb
|
149
|
+
- lib/panoptes/client/cellect.rb
|
150
|
+
- lib/panoptes/client/comments.rb
|
117
151
|
- lib/panoptes/client/discussions.rb
|
118
152
|
- lib/panoptes/client/me.rb
|
119
153
|
- lib/panoptes/client/projects.rb
|
@@ -122,7 +156,10 @@ files:
|
|
122
156
|
- lib/panoptes/client/user_groups.rb
|
123
157
|
- lib/panoptes/client/version.rb
|
124
158
|
- lib/panoptes/client/workflows.rb
|
125
|
-
- lib/panoptes/
|
159
|
+
- lib/panoptes/endpoints/base_endpoint.rb
|
160
|
+
- lib/panoptes/endpoints/json_api_endpoint.rb
|
161
|
+
- lib/panoptes/endpoints/json_endpoint.rb
|
162
|
+
- lib/panoptes/session.rb
|
126
163
|
- lib/panoptes/talk_client.rb
|
127
164
|
- panoptes-client.gemspec
|
128
165
|
homepage: https://github.com/zooniverse/panoptes-client.rb
|
@@ -1,77 +0,0 @@
|
|
1
|
-
require 'faraday'
|
2
|
-
require 'faraday_middleware'
|
3
|
-
require 'faraday/panoptes'
|
4
|
-
|
5
|
-
require "panoptes/client/version"
|
6
|
-
|
7
|
-
module Panoptes
|
8
|
-
module CommonClient
|
9
|
-
PROD_API_URL = "https://panoptes.zooniverse.org".freeze
|
10
|
-
PROD_TALK_API_URL = "https://talk.zooniverse.org".freeze
|
11
|
-
|
12
|
-
# A client is the main interface to the API.
|
13
|
-
#
|
14
|
-
# @param auth [Hash] Authentication details
|
15
|
-
# * either nothing,
|
16
|
-
# * a hash with +:token+ (an existing OAuth user token),
|
17
|
-
# * or a hash with +:client_id+ and +:client_secret+ (a keypair for an OAuth Application).
|
18
|
-
# @param url [String] API location to use.
|
19
|
-
# @param auth_url [String] Auth API location to use.
|
20
|
-
def initialize(auth: {}, url: PROD_API_URL, auth_url: PROD_API_URL)
|
21
|
-
@conn = Faraday.new(url: url) do |faraday|
|
22
|
-
case
|
23
|
-
when auth[:token]
|
24
|
-
faraday.request :panoptes_access_token,
|
25
|
-
url: auth_url,
|
26
|
-
access_token: auth[:token]
|
27
|
-
when auth[:client_id] && auth[:client_secret]
|
28
|
-
faraday.request :panoptes_client_credentials,
|
29
|
-
url: auth_url,
|
30
|
-
client_id: auth[:client_id],
|
31
|
-
client_secret: auth[:client_secret]
|
32
|
-
end
|
33
|
-
|
34
|
-
faraday.request :panoptes_api_v1
|
35
|
-
faraday.request :json
|
36
|
-
faraday.response :json
|
37
|
-
faraday.adapter Faraday.default_adapter
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
# Get a path and perform automatic depagination
|
42
|
-
def paginate(path, query, resource: nil)
|
43
|
-
resource = path.split("/").last if resource.nil?
|
44
|
-
data = last_response = get(path, query)
|
45
|
-
|
46
|
-
while next_path = last_response["meta"][resource]["next_href"]
|
47
|
-
last_response = get(next_path, query)
|
48
|
-
if block_given?
|
49
|
-
yield data, last_response
|
50
|
-
else
|
51
|
-
data[resource].concat(last_response[resource]) if data[resource].is_a?(Array)
|
52
|
-
data["meta"][resource].merge!(last_response["meta"][resource])
|
53
|
-
data["links"].merge!(last_response["links"])
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
data
|
58
|
-
end
|
59
|
-
|
60
|
-
private
|
61
|
-
|
62
|
-
def conn
|
63
|
-
@conn
|
64
|
-
end
|
65
|
-
|
66
|
-
def handle_response(response)
|
67
|
-
case response.status
|
68
|
-
when 404
|
69
|
-
raise ResourceNotFound, status: response.status, body: response.body
|
70
|
-
when 400..600
|
71
|
-
raise ServerError.new(response.body)
|
72
|
-
else
|
73
|
-
response.body
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|