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 +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
|