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 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 = Proctorcam::Proctorserv::ProctorservApi.new("our_customer_identifier", "our_shared_secret")
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 = Proctorcam::Proctorserv::ProctorservApi.new("our_customer_identifier", "our_shared_secret")
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)
@@ -29,7 +29,7 @@ module ProctorCam
29
29
  module Proctorserv
30
30
  class ProctorservApi
31
31
 
32
- VERSION = "1.0.5"
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.map{|k,v| "#{k}=#{v}" }.join('&') + shared_secret
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.to_json, :accept => :json, :content_type => :json do |response, request, result, &block|
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
- 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'}
88
- response = @proctorserv_api.make_reservation options
89
- response.should == -1
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 => 427, :event_type => "completed", :proctor_id => "foo", :severity => 2}
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.5
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-09-03 00:00:00.000000000 Z
12
+ date: 2013-11-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client