openstax_api 8.1.1 → 8.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aeefa4b58e29cb1960801da52f27d4cfc2959c70
4
- data.tar.gz: 0cbdbded9beb84362074744d95168defa1e4f000
3
+ metadata.gz: a3da970c8b505007a77d4c22af9f93f02598a7ac
4
+ data.tar.gz: 5550c22216fd6b3792b04b182995f4b97a23edfd
5
5
  SHA512:
6
- metadata.gz: 0915a7de958c62ae641ff20b14381ce26781f660cc03a050da2444c2bd1ecfc3a00c41b4c105d049852c5960b381f02ddb343a1b824d0573f670b1dc12dca801
7
- data.tar.gz: 28fde8f8c2a57657fa08882cca2037f28fc6ccd3618480edbbc5fa16776e45b56cafdc9df60dcc79534a0f86d69d44dbc66a0c925e567f4386df7c38541f9f43
6
+ metadata.gz: 3beef5dc60cc89ca7eef3af6056973ca999a24c998ac017595d4d2c6141bce3a5e7c88fa78ec368caf994dbec04a63245b915e7ab5f6942208ff59c1139221df
7
+ data.tar.gz: a9887c1adbdbc5bc1b66ebb244c8b1069864613bf7ed34d1e7f024fe23383fc85f43deceda938eefa1885c77abc3f31c7cdee66b7fa22cc5fa1454153aab4845
@@ -6,6 +6,7 @@ require 'openstax_utilities'
6
6
  require 'openstax/api/roar'
7
7
  require 'openstax/api/apipie'
8
8
  require 'openstax/api/responder_with_put_patch_delete_content'
9
+ require 'openstax/api/params'
9
10
 
10
11
  module OpenStax
11
12
  module Api
@@ -0,0 +1,92 @@
1
+ module OpenStax
2
+ module Api
3
+ module Params
4
+
5
+ extend self
6
+
7
+ def sign(params:, secret:, algorithm: 'sha256')
8
+ raise "`secret` cannot be blank" if secret.blank?
9
+ local_params = params.merge(timestamp: Time.now.to_i)
10
+
11
+ stringified_params = normalize(local_params)
12
+ signature = OpenSSL::HMAC.hexdigest(algorithm, secret, stringified_params)
13
+
14
+ local_params.merge!(signature: signature)
15
+ end
16
+
17
+ def signature_and_timestamp_valid?(params:, secret:, algorithm: 'sha256', timestamp_window_width: 2.minutes)
18
+ local_params = params.dup
19
+ incoming_signature = local_params.delete(:signature)
20
+
21
+ return false if incoming_signature.blank?
22
+
23
+ stringified_params = normalize(local_params)
24
+ expected_signature = OpenSSL::HMAC.hexdigest(algorithm, secret, stringified_params)
25
+
26
+ return false if expected_signature != incoming_signature
27
+
28
+ timestamp_window = timestamp_window_width.ago..timestamp_window_width.from_now
29
+ return false if !timestamp_window.cover?(Time.at(params[:timestamp].to_i))
30
+
31
+ return true
32
+ end
33
+
34
+ # Below is borrowed from https://github.com/oauth-xx/oauth-ruby/blob/e397b3e2f540faaebd7912aeb2768835d151f795/lib/oauth/helper.rb
35
+ # so we can call `normalize` on some params without adding dependence on full oauth gem
36
+
37
+ RESERVED_CHARACTERS = /[^a-zA-Z0-9\-\.\_\~]/
38
+
39
+ # Escape +value+ by URL encoding all non-reserved character.
40
+ def escape(value)
41
+ _escape(value.to_s.to_str)
42
+ rescue ArgumentError
43
+ _escape(value.to_s.to_str.force_encoding(Encoding::UTF_8))
44
+ end
45
+
46
+ def _escape(string)
47
+ URI.escape(string, RESERVED_CHARACTERS)
48
+ end
49
+
50
+ # Normalize a +Hash+ of parameter values. Parameters are sorted by name, using lexicographical
51
+ # byte value ordering. If two or more parameters share the same name, they are sorted by their value.
52
+ # Parameters are concatenated in their sorted order into a single string. For each parameter, the name
53
+ # is separated from the corresponding value by an "=" character, even if the value is empty. Each
54
+ # name-value pair is separated by an "&" character.
55
+ def normalize(params)
56
+ params.sort.map do |k, values|
57
+ if values.is_a?(Array)
58
+ # make sure the array has an element so we don't lose the key
59
+ values << nil if values.empty?
60
+ # multiple values were provided for a single key
61
+ values.sort.collect do |v|
62
+ [escape(k),escape(v)] * "="
63
+ end
64
+ elsif values.is_a?(Hash)
65
+ normalize_nested_query(values, k)
66
+ else
67
+ [escape(k),escape(values)] * "="
68
+ end
69
+ end * "&"
70
+ end
71
+
72
+ #Returns a string representation of the Hash like in URL query string
73
+ # build_nested_query({:level_1 => {:level_2 => ['value_1','value_2']}}, 'prefix'))
74
+ # #=> ["prefix%5Blevel_1%5D%5Blevel_2%5D%5B%5D=value_1", "prefix%5Blevel_1%5D%5Blevel_2%5D%5B%5D=value_2"]
75
+ def normalize_nested_query(value, prefix = nil)
76
+ case value
77
+ when Array
78
+ value.map do |v|
79
+ normalize_nested_query(v, "#{prefix}[]")
80
+ end.flatten.sort
81
+ when Hash
82
+ value.map do |k, v|
83
+ normalize_nested_query(v, prefix ? "#{prefix}[#{k}]" : k)
84
+ end.flatten.sort
85
+ else
86
+ [escape(prefix), escape(value)] * "="
87
+ end
88
+ end
89
+
90
+ end
91
+ end
92
+ end
@@ -44,7 +44,9 @@ module OpenStax
44
44
 
45
45
  representer.representable_attrs.each do |attr|
46
46
  # Handle some common attributes (as, schema_info, required)
47
- name = attr[:as].blank? ? attr[:name] : attr[:as].evaluate(representer) rescue attr[:name]
47
+ name = attr[:as].blank? ?
48
+ attr[:name] :
49
+ attr[:as].evaluate(representer) rescue attr[:as].call rescue attr[:name]
48
50
  schema_info = attr[:schema_info] || {}
49
51
 
50
52
  schema[:required].push(name.to_sym) if schema_info[:required]
@@ -1,5 +1,5 @@
1
1
  module OpenStax
2
2
  module Api
3
- VERSION = "8.1.1"
3
+ VERSION = "8.2.0"
4
4
  end
5
5
  end
Binary file