web-connect 0.4.10 → 0.4.11

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 993a6beae2974b8c68863a8de079026471cf22a5
4
- data.tar.gz: a9eaf838e7f5a5d3e3392d80734f64f776513c08
3
+ metadata.gz: 57e9bb59d41e8a0c01c87c705f8025d1d232f4ac
4
+ data.tar.gz: 519a6611cddde1f5c82be9e983d4236eaaa028a3
5
5
  SHA512:
6
- metadata.gz: 5a65c0e7fd57301c39cdd57d344fb00658120c0908f6819ec65651fd529c161f3dd6b1b882a2852d9125bbe27aacf80d9c727fade464c973124e0451ebb443eb
7
- data.tar.gz: e2c02ad0fdbc4ac90208bcc026e68bfca2eb230a81ca876acaf24e73958d8486a131b9b443681a61ee04febdd9477d897bf2d03b9fa82ea896295f6b0551fac9
6
+ metadata.gz: 44e149eb63bb57f314fdd9b5a530aa969d2910aa506c6f719aef1c6f3e40d8c95214127a0d3f795a60025cdb5c41f3a3f2dcfa62bb914f86a4fa37993bf7ffe5
7
+ data.tar.gz: 62ec603899fc3a43d0c83424c0ff94b7b0c5c3420c92ac18fc2f681ccb63a6facd4230cf9a665cdd3e13b017f771f2e6b50f61b1154b336a04be0f614ddaae56
@@ -23,6 +23,20 @@ module Netfira::WebConnect
23
23
  ]
24
24
  rescue Exceptions::HttpException => e
25
25
  make_response e.code, e.body, e.headers, e.code
26
+ rescue => e
27
+ # TODO: provide a way to silence these (i.e. for prod environments)
28
+ # TODO: log errors
29
+ raise e if defined? DONT_CATCH_ALL_EXCEPTIONS
30
+ body = {
31
+ errorCode: 1,
32
+ errorMessage: 'Uncaught Exception',
33
+ exception: {
34
+ class: e.class.name,
35
+ message: e.message,
36
+ backtrace: e.backtrace
37
+ }
38
+ }
39
+ make_response 500, body
26
40
  end
27
41
  end
28
42
 
@@ -45,7 +59,11 @@ module Netfira::WebConnect
45
59
  end
46
60
 
47
61
  def make_response(status, body = {}, headers = {}, error_code = 0)
48
- body_string = {errorCode: error_code}.merge(body).to_json
62
+ begin
63
+ body_string = {errorCode: error_code}.merge(body).to_json
64
+ rescue Encoding::UndefinedConversionError
65
+ body_string = {errorCode: error_code}.merge(sanitize_for_json body).to_json
66
+ end
49
67
  [
50
68
  status,
51
69
  {
@@ -57,6 +75,15 @@ module Netfira::WebConnect
57
75
  ]
58
76
  end
59
77
 
78
+ def sanitize_for_json(data)
79
+ case data
80
+ when String then data.encode Encoding::UTF_8 rescue '<Invalid UTF-8>'
81
+ when Hash then data.map { |k, v| [k, sanitize_for_json(v)] }.to_h
82
+ when Array then data.map { |v| sanitize_for_json v }
83
+ else data
84
+ end
85
+ end
86
+
60
87
  end
61
88
  end
62
89
 
@@ -1,5 +1,8 @@
1
1
  module Netfira::WebConnect
2
2
  class RackApp::Action
3
+ include RackApp::Exceptions::HttpExceptions
4
+
5
+ VALID_BASE64 = %r`^([a-z\d+/]{4})*([a-z\d+/]{4}|[a-z\d+/]{3}=|[a-z\d+/]{2}==)$`i
3
6
 
4
7
  def import_env(env)
5
8
  @env = env
@@ -78,8 +81,20 @@ module Netfira::WebConnect
78
81
  # Input
79
82
  if put? or post?
80
83
  @input = request.body
81
- @input = StringIO.new(@input.read.unpack('m').first) if env['CONTENT_ENCODING'] == 'base64'
82
- @input = JSON.parse @input.read if request.media_type == 'application/json'
84
+
85
+ # Decode base64
86
+ if (env['HTTP_CONTENT_ENCODING'] || env['CONTENT_ENCODING'] || '').downcase == 'base64'
87
+ input = @input.read.gsub(/\s+/, '')
88
+ raise BadRequest, 'Invalid base64 in request body' unless input.length % 4 == 0 && input =~ VALID_BASE64
89
+ @input = StringIO.new(input.unpack('m').first)
90
+ end
91
+
92
+ # Unserialize JSON
93
+ begin
94
+ @input = JSON.parse @input.read, quirks_mode: true if request.media_type == 'application/json'
95
+ rescue JSON::ParserError => error
96
+ raise BadRequest.new('Invalid JSON in request body', details: error.message.sub(/^\d+:\s*/, ''))
97
+ end
83
98
  end
84
99
 
85
100
  end
@@ -18,6 +18,21 @@ module Netfira::WebConnect
18
18
  define_method(:"#{verb}?") { self.verb.to_s == verb }
19
19
  end
20
20
 
21
+ # This method restricts request verbs (symbols) and input types (classes)
22
+ def allow(*args)
23
+
24
+ # Restrict verbs
25
+ verbs = args.select { |x| Symbol === x }
26
+ unless verbs.empty? || verbs.include?(verb)
27
+ raise MethodNotAllowed.new("The #{verb.to_s.upcase} verb is not allowed", allowed: verbs.map{ |v| v.to_s.upcase })
28
+ end
29
+
30
+ # Restrict input type
31
+ types = args.select { |x| Class === x }
32
+ unless types.empty? || types.find { |t| t === input }
33
+ raise BadRequest.new('Unexpected request body type', allowed: types.map { |t| t.name })
34
+ end
35
+ end
21
36
 
22
37
  end
23
38
  end
@@ -2,7 +2,7 @@ class Netfira::WebConnect::RackApp
2
2
  module Action::Version8
3
3
  class Checksums < Action
4
4
  def call
5
- raise MethodNotAllowed unless get?
5
+ allow :get
6
6
 
7
7
  klass = class_for_record_type(query_string['type'])
8
8
  checksums = klass.where(shop_id: shop.id).map{ |record| [record.origin_id, record.digest]}.to_h
@@ -3,7 +3,7 @@ class Netfira::WebConnect::RackApp
3
3
  class Commit < Action
4
4
 
5
5
  def call
6
- raise MethodNotAllowed unless verb == :put
6
+ allow :put, Hash
7
7
  dispatch_event :before, :commit, shop
8
8
  dispatch_event :around, :commit, shop do
9
9
  commit_records input['records'] if input['records']
@@ -2,7 +2,7 @@ class Netfira::WebConnect::RackApp
2
2
  module Action::Version8
3
3
  class Files < Action
4
4
  def call
5
- raise MethodNotAllowed unless post?
5
+ allow :post
6
6
  klass = class_for_record_type(path[0])
7
7
  raise BadRequest, "You can't upload files for that data type" unless klass < Netfira::WebConnect::Model::Record::FileRecord
8
8
 
@@ -4,10 +4,8 @@ module Netfira::WebConnect
4
4
  class Records < Action
5
5
 
6
6
  def call
7
- case verb
8
- when :delete then purge!
9
- else raise MethodNotAllowed
10
- end
7
+ allow :delete
8
+ purge!
11
9
  end
12
10
 
13
11
  private
@@ -2,6 +2,7 @@ class Netfira::WebConnect::RackApp
2
2
  module Action::Version8
3
3
  class Settings < Action
4
4
  def call
5
+ allow :put, :post, :get, :delete
5
6
  key = path && path.first
6
7
  if key
7
8
  handle_single key
@@ -55,6 +56,7 @@ class Netfira::WebConnect::RackApp
55
56
  end
56
57
 
57
58
  def update_multiple
59
+ allow Hash
58
60
  input.each do |key, value|
59
61
  shop.settings[key] = value.unpack('m').first
60
62
  end
@@ -6,6 +6,7 @@ class Netfira::WebConnect::RackApp
6
6
  SEARCH_PATH = [:public, :protected].map { |x| [x, WEB_BASE + x.to_s] }.to_h
7
7
 
8
8
  def call
9
+ allow :get
9
10
  raise NotFound unless path
10
11
  path = self.path.join '/'
11
12
  options = SEARCH_PATH.map do |access, dir|
@@ -14,7 +14,7 @@ module Netfira::WebConnect::RackApp::Exceptions
14
14
  def_delegators :'self.class', :status, :code, :category
15
15
 
16
16
  def initialize(message = nil, details = nil)
17
- super message
17
+ super message || self.class.name.demodulize.underscore.humanize
18
18
  @headers = self.class.headers.dup
19
19
  @details = details
20
20
  end
@@ -1,6 +1,6 @@
1
1
  module Netfira
2
2
  module WebConnect
3
- VERSION = '0.4.10'
3
+ VERSION = '0.4.11'
4
4
  PLATFORM_AND_VERSION = 'Rack/' << VERSION
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: web-connect
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.10
4
+ version: 0.4.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neil E. Pearson
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-08-18 00:00:00.000000000 Z
12
+ date: 2014-08-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord