openstax_api 8.1.1 → 8.2.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.
- checksums.yaml +4 -4
- data/lib/openstax/api/engine.rb +1 -0
- data/lib/openstax/api/params.rb +92 -0
- data/lib/openstax/api/representable_schema_printer.rb +3 -1
- data/lib/openstax/api/version.rb +1 -1
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/test.log +2253 -9380
- data/spec/lib/openstax/api/params_spec.rb +78 -0
- metadata +20 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3da970c8b505007a77d4c22af9f93f02598a7ac
|
4
|
+
data.tar.gz: 5550c22216fd6b3792b04b182995f4b97a23edfd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3beef5dc60cc89ca7eef3af6056973ca999a24c998ac017595d4d2c6141bce3a5e7c88fa78ec368caf994dbec04a63245b915e7ab5f6942208ff59c1139221df
|
7
|
+
data.tar.gz: a9887c1adbdbc5bc1b66ebb244c8b1069864613bf7ed34d1e7f024fe23383fc85f43deceda938eefa1885c77abc3f31c7cdee66b7fa22cc5fa1454153aab4845
|
data/lib/openstax/api/engine.rb
CHANGED
@@ -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? ?
|
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]
|
data/lib/openstax/api/version.rb
CHANGED
data/spec/dummy/db/test.sqlite3
CHANGED
Binary file
|