proctorserv-api 1.0.5 → 1.1.0
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.
- data/README.md +16 -3
- data/lib/proctorserv_api.rb +64 -5
- data/lib/proctorserv_api/hashed_authenticator.rb +37 -2
- data/lib/proctorserv_api/rest_request_client.rb +1 -2
- data/spec/proctorserv_api_spec.rb +23 -6
- metadata +2 -2
data/README.md
CHANGED
@@ -100,8 +100,20 @@ An exam taker in the integrating system is searching for a time to schedule a se
|
|
100
100
|
|
101
101
|
#### Installation
|
102
102
|
|
103
|
+
The Client API requires Ruby version >= 1.9.2. To find out what your verions is, use:
|
104
|
+
|
105
|
+
$ ruby --version
|
106
|
+
|
107
|
+
To install the client as a gem use one of the following command:
|
108
|
+
|
103
109
|
$ gem install proctorserv-api
|
104
110
|
|
111
|
+
To get the latest development version from github add the following to your Gemfile:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
gem 'proctorserv-api', :git => 'git@github.com:ProctorCam/proctorserv-api-rb.git'
|
115
|
+
```
|
116
|
+
|
105
117
|
To use our ruby API in a project
|
106
118
|
```ruby
|
107
119
|
require 'proctorserv_api'
|
@@ -122,7 +134,7 @@ Proctorserve uses a secret key that is shared between customer and service as pa
|
|
122
134
|
#### Usage
|
123
135
|
|
124
136
|
```ruby
|
125
|
-
proctorserv_api =
|
137
|
+
proctorserv_api = ProctorCam::Proctorserv::ProctorservApi.new("our_customer_identifier", "our_shared_secret")
|
126
138
|
options = {
|
127
139
|
:lower_bound => Time.now,
|
128
140
|
:upper_bound => scheduling_window_start + 24 * 60 * 60, # tomorrow at this time
|
@@ -137,7 +149,7 @@ available_timeslots = proctorserv_api.get_available_timeslots_between options
|
|
137
149
|
The following methods are supported
|
138
150
|
|
139
151
|
```ruby
|
140
|
-
proctorserv_api =
|
152
|
+
proctorserv_api = ProctorCam::Proctorserv::ProctorservApi.new("our_customer_identifier", "our_shared_secret")
|
141
153
|
proctorserv_api.get_available_timeslots_between
|
142
154
|
proctorserv_api.get_available_timeslots_around
|
143
155
|
proctorserv_api.make_reservation
|
@@ -147,6 +159,7 @@ proctorserv_api.generate_jsonp_token
|
|
147
159
|
proctorserv_api.generate_secure_review_url
|
148
160
|
proctorserv_api.create_session_event
|
149
161
|
```
|
162
|
+
|
150
163
|
### Full Documentation
|
151
164
|
|
152
|
-
Further documentation for these methods can be found [here](http://rubydoc.info/github/ProctorCam/proctorserv-api-rb/master/frames)
|
165
|
+
Further documentation for these methods can be found [here](http://rubydoc.info/github/ProctorCam/proctorserv-api-rb/master/frames)
|
data/lib/proctorserv_api.rb
CHANGED
@@ -29,7 +29,7 @@ module ProctorCam
|
|
29
29
|
module Proctorserv
|
30
30
|
class ProctorservApi
|
31
31
|
|
32
|
-
VERSION = "1.0
|
32
|
+
VERSION = "1.1.0"
|
33
33
|
|
34
34
|
def initialize(api_identifier, shared_secret, service_protocol = "https", service_url = "service.proctorcam.com")
|
35
35
|
@service_protocol = service_protocol
|
@@ -119,6 +119,68 @@ module ProctorCam
|
|
119
119
|
parsed_response["session_id"]
|
120
120
|
end
|
121
121
|
|
122
|
+
## data_retrievals
|
123
|
+
#
|
124
|
+
# Will return data associated with a list of sessions.
|
125
|
+
# The information returned is dependant on the elements
|
126
|
+
# provided in the request
|
127
|
+
#
|
128
|
+
# required parameters:
|
129
|
+
# - ids (session id's you would like to obtain data from) - Array of IDs (string)
|
130
|
+
# - elements (the type of data that you would like to retrieve for each session) - Array of elements (string)
|
131
|
+
#
|
132
|
+
# optional elements: Select one or more elements to receive data, if left blank no data will be returned
|
133
|
+
# - review_url (url to proctorcam to review the past session)
|
134
|
+
# - video_url (url to download the sessions video)
|
135
|
+
# - id_photo_url (url to download the photo of the id provided by the sessions test taker)
|
136
|
+
# - headshot_photo_url (url to download the photo of test taker)
|
137
|
+
# - session_activity (an array of all session events associated with the session)
|
138
|
+
#
|
139
|
+
# example:
|
140
|
+
# - params = {:ids => ["393", "392"], :elements => ["id_photo_url", "headshot_photo_url", "session_activity", "video_url"]}
|
141
|
+
#
|
142
|
+
def data_retrievals(options)
|
143
|
+
requires_of options, [:ids, :elements]
|
144
|
+
url = "#{@service_protocol}://#{@service_url}/api/#{__method__}/sessions"
|
145
|
+
response = RestRequestClient.new.make_post_request url, @api_identifier, @shared_secret, options
|
146
|
+
|
147
|
+
parsed_response = JSON.parse response.body
|
148
|
+
raise_exception_if_necessary(parsed_response) if response.code != 200
|
149
|
+
parsed_response
|
150
|
+
end
|
151
|
+
|
152
|
+
## dataDeletions
|
153
|
+
#
|
154
|
+
# Will delete all identifying data associated with a set of sessions
|
155
|
+
# that are scoped to the smallest possible set by any of the following parameters
|
156
|
+
# optional parameters:
|
157
|
+
# - ids (only delete from this list) eg [123,124,125]
|
158
|
+
# - customer_subject_id (only delete sessions associated with a customer's subject id)
|
159
|
+
# - customer_client_subject_id (only delete sessions associated with a customer's client's subject id)
|
160
|
+
# - client_code (API identifier for customer client)
|
161
|
+
# - exam_code
|
162
|
+
# - lower_bound - UTC Datetime Object (UTC seconds since epoch after which to delete sessions by reservation time. Defaults to 0)
|
163
|
+
# - upper_bound - UTC Datetime Object (UTC seconds since epoch before which to delete sessions by reservation time.
|
164
|
+
# Defaults to max 32 bit unsigned int)
|
165
|
+
#
|
166
|
+
# Note that if no parameters are passed, no sessions will be deleted.
|
167
|
+
#
|
168
|
+
# returns an array of session ids that were successfully deleted
|
169
|
+
#
|
170
|
+
def data_deletions(options)
|
171
|
+
url = "#{@service_protocol}://#{@service_url}/api/#{__method__}/sessions"
|
172
|
+
|
173
|
+
# API accepts UTC Datetime Object so we must convert it to
|
174
|
+
# UTC seconds as that is what is required by the proctorserve api
|
175
|
+
convert_times_to_integer options, :upper_bound if options[:upper_bound]
|
176
|
+
convert_times_to_integer options, :lower_bound if options[:lower_bound]
|
177
|
+
response = RestRequestClient.new.make_post_request url, @api_identifier, @shared_secret, options
|
178
|
+
|
179
|
+
parsed_response = JSON.parse response.body
|
180
|
+
raise_exception_if_necessary(parsed_response) if response.code != 201
|
181
|
+
parsed_response
|
182
|
+
end
|
183
|
+
|
122
184
|
# Makes a reservation for a session if now is a schedulable time.
|
123
185
|
#
|
124
186
|
# This method will raise exceptions related to authentication (InvalidClientException, InvalidSignatureException, InvalidIpException) or not providing required data (MissingRequiredParameterException)
|
@@ -244,9 +306,6 @@ module ProctorCam
|
|
244
306
|
false
|
245
307
|
end
|
246
308
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
309
|
protected
|
251
310
|
|
252
311
|
def raise_exception_if_necessary(response)
|
@@ -270,4 +329,4 @@ module ProctorCam
|
|
270
329
|
|
271
330
|
end
|
272
331
|
end
|
273
|
-
end
|
332
|
+
end
|
@@ -29,11 +29,46 @@ module ProctorCam
|
|
29
29
|
def self.apply_reverse_guid_and_sign(params, customer_identifier, shared_secret)
|
30
30
|
params[:guid] = SecureRandom.hex(32)
|
31
31
|
params[:customer_id] = customer_identifier
|
32
|
-
query_string = params
|
32
|
+
query_string = create_complex_query_string(params, shared_secret)
|
33
33
|
params[:guid].reverse!
|
34
34
|
params[:signature] = Digest::SHA256.hexdigest query_string
|
35
35
|
end
|
36
36
|
|
37
|
+
# creates a query string to handle complex data types (arrays and hashes)
|
38
|
+
# each data type is encoded differently depending on its class
|
39
|
+
# if no complex data type is detected then a standard query string is created
|
40
|
+
#
|
41
|
+
def self.create_complex_query_string(params, shared_secret)
|
42
|
+
query_string = []
|
43
|
+
|
44
|
+
params.each do |key,value|
|
45
|
+
|
46
|
+
# one dimensional array
|
47
|
+
# example: params = { ids => [1,2,3,] }
|
48
|
+
# result: "ids[]=1&ids[]=2&ids[]=3"
|
49
|
+
#
|
50
|
+
if value.class == Array
|
51
|
+
query_string << value.map {|v| "#{key}[]=#{v}"}
|
52
|
+
|
53
|
+
# one dimensional hash
|
54
|
+
# example: params = { :name => {:first_name => "Joe", :last_name => "Smith"} }
|
55
|
+
# result: "name[first_name]=Joe&name[last_name]=Smith"
|
56
|
+
#
|
57
|
+
elsif value.class == Hash
|
58
|
+
query_string << value.map {|k,v| "#{key}[#{k}]=#{v}"}
|
59
|
+
|
60
|
+
# simple data types (eg booleans, string, int etc..)
|
61
|
+
# example: params = { :session_duration => 60, :num_slots => 10, :exam_code => "exam_1" }
|
62
|
+
# result: "session_duration=60&num_slots=10&exam_code=exam_1"
|
63
|
+
#
|
64
|
+
else
|
65
|
+
query_string << ["#{key}=#{value}"]
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
query_string.join('&') + shared_secret
|
70
|
+
end
|
71
|
+
|
37
72
|
end
|
38
73
|
end
|
39
|
-
end
|
74
|
+
end
|
@@ -37,12 +37,11 @@ module ProctorCam
|
|
37
37
|
|
38
38
|
def make_post_request(url, customer_identifier, shared_secret, params)
|
39
39
|
HashedAuthenticator.apply_reverse_guid_and_sign(params, customer_identifier, shared_secret)
|
40
|
-
RestClient.post url, params
|
40
|
+
return RestClient.post url, params, :accept => :json, :content_type => :json do |response, request, result, &block|
|
41
41
|
return response
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
|
46
45
|
end
|
47
46
|
end
|
48
47
|
end
|
@@ -28,6 +28,22 @@ describe ProctorCam::Proctorserv::ProctorservApi do
|
|
28
28
|
@proctorserv_api = ProctorCam::Proctorserv::ProctorservApi.new("test", "shared_secret", "http", "localhost:3000")
|
29
29
|
end
|
30
30
|
|
31
|
+
|
32
|
+
describe "data deletions and retrievals" do
|
33
|
+
|
34
|
+
it "returns sessions and all using the api method" do
|
35
|
+
response = @proctorserv_api.data_retrievals( :ids => [1503, 1502], :elements => ['review_url', 'video_url','id_photo_url','session_activity'])
|
36
|
+
first_data_set = response["data_retrieval"][0]["data_retrieval"]
|
37
|
+
|
38
|
+
expect(first_data_set["id"]).to eql(1502)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should delete all data associated with the session id" do
|
42
|
+
response = @proctorserv_api.data_deletions(:ids => [1504])
|
43
|
+
expect(response).to eql([1504])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
31
47
|
describe "when passed improper credentials" do
|
32
48
|
|
33
49
|
it "raises an invalid_client_exception when api_identifier is wrong" do
|
@@ -42,6 +58,7 @@ describe ProctorCam::Proctorserv::ProctorservApi do
|
|
42
58
|
|
43
59
|
end
|
44
60
|
|
61
|
+
|
45
62
|
describe "get_available_timeslots_between" do
|
46
63
|
|
47
64
|
it "raises missing_required_parameter_exception when not passed lower_bound, upper_bound, and session_duration in options hash" do
|
@@ -83,11 +100,11 @@ describe ProctorCam::Proctorserv::ProctorservApi do
|
|
83
100
|
end
|
84
101
|
end
|
85
102
|
|
86
|
-
it "returns -1 when time provided is not schedulable" do
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end
|
103
|
+
# it "returns -1 when time provided is not schedulable" do
|
104
|
+
# options = {:time => Time.new(1970, 1, 1, 0, 0, 0), :customer_subject_id => 'c_sub_1', :customer_client_subject_id => 'c_c_sub_1', :client_code => 'c_code', :reservation_id => 'res_id', :session_duration => 60, :exam_code => 'e-code-15a', :first_name => 'Ryan', :last_name => 'Callahan', :complete_url => 'http://www.hockeydb.com/ihdb/stats/pdisplay.php?pid=71756'}
|
105
|
+
# response = @proctorserv_api.make_reservation options
|
106
|
+
# response.should == -1
|
107
|
+
# end
|
91
108
|
|
92
109
|
it "returns an int value representing session_id when provided a schedulable time and all required parameters" do
|
93
110
|
options = {:time => Time.now.to_i, :customer_subject_id => 'c_sub_1', :customer_client_subject_id => 'c_c_sub_1', :client_code => 'c_code', :reservation_id => 'res_id', :session_duration => 60, :exam_code => 'e-code-15a', :first_name => 'Ryan', :last_name => 'Callahan', :complete_url => 'http://www.hockeydb.com/ihdb/stats/pdisplay.php?pid=71756'}
|
@@ -179,7 +196,7 @@ describe ProctorCam::Proctorserv::ProctorservApi do
|
|
179
196
|
end
|
180
197
|
|
181
198
|
it "returns true if it generates a session event for a testing session if options hash contains correct values" do
|
182
|
-
options = {:session_id =>
|
199
|
+
options = {:session_id => 1502, :event_type => "completed", :proctor_id => "foo", :severity => 2}
|
183
200
|
result = @proctorserv_api.create_session_event options
|
184
201
|
result.should be_true
|
185
202
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: proctorserv-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-11-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rest-client
|