swalidate 0.1.0 → 0.1.1

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: bfe97d384e09f73d2de99aa29853d792656a67e1
4
- data.tar.gz: 450d059e60539ad1930f3065522cce1443605e12
3
+ metadata.gz: c3459b3c0c2f919ba4c550703f8398277a7b3869
4
+ data.tar.gz: 1d4bc1e86843aaf3f69874f97df329c4519b0785
5
5
  SHA512:
6
- metadata.gz: d124d24c33f76db15a62c2ee6cc9104d8bfeedfea39cd4fead045caab74fbe567abe14bc53b69750dee62b0749e6c6147990fba00d4f394dc5f802ff42da2224
7
- data.tar.gz: 19aaacc3e0fe2a4ce13f286f7ab1b838a996b8ab69b66a224b5de4e0b40eac6f360092245706de7aa8da6a7f1a1af541ef498ad328de563a755040d34bca832d
6
+ metadata.gz: cd7b44bf8a7ad42527403122cb12cbe38c9340a433e5ba92efbad604b606e38d458b89e11f5fa243e014c83a04a43fa18c3b221f8c663800e294df7777333134
7
+ data.tar.gz: aa91c4ad4bf33c4c220c000202f774c23fe6c46a3919954e6fd0cdc6d933551a34b2002a13d0e2f5d594378f502ff4060beeef06347c366165c2e2d9d0e84bc1
data/.rubocop.yml ADDED
@@ -0,0 +1,7 @@
1
+ # require: rubocop-rspec
2
+
3
+ Metrics/LineLength:
4
+ Max: 100
5
+
6
+ Style/Documentation:
7
+ Enabled: false
data/.travis.yml CHANGED
@@ -3,3 +3,5 @@ language: ruby
3
3
  rvm:
4
4
  - 2.2.1
5
5
  before_install: gem install bundler -v 1.14.3
6
+ script:
7
+ rake spec rubocop
data/README.md CHANGED
@@ -22,7 +22,14 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
25
+ ```ruby
26
+ swalidate_config = {
27
+ file_path: 'path.yaml', # swagger config file. example of app root
28
+ subdomain: 'api', # validation applies only to this subdomain
29
+ path_prefix: '/v1' # validation applies only to the paths starting with path_prefix
30
+ }
31
+ config.middleware.insert_after ActionDispatch::ParamsParser, Swalidate::Middleware, swalidate_config
32
+ ```
26
33
 
27
34
  ## Development
28
35
 
data/Rakefile CHANGED
@@ -1,6 +1,9 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ require 'rubocop/rake_task'
7
+ RuboCop::RakeTask.new
8
+
9
+ task default: :spec
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "swalidate"
3
+ require 'bundler/setup'
4
+ require 'swalidate'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "swalidate"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start(__FILE__)
@@ -0,0 +1,13 @@
1
+ module Swalidate
2
+ class Endpoint
3
+ attr_reader :parameters
4
+
5
+ def initialize(detail)
6
+ @parameters = Array(detail && detail['parameters'])
7
+ end
8
+
9
+ def should_validate?
10
+ @parameters.any?
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,51 @@
1
+ module Swalidate
2
+ class Middleware
3
+ def initialize(app, options = {})
4
+ @app = app
5
+ @schema = Swalidate::Schema.new(options[:file_path])
6
+ # TODO: puts a log message when not found and dont try to validate
7
+
8
+ @subdomain = options[:subdomain]
9
+ @path_prefix = options[:path_prefix]
10
+ end
11
+
12
+ def call(env)
13
+ @request = ActionDispatch::Request.new(env)
14
+ @endpoint = @schema.endpoint(@request.method, @request.path.gsub(@path_prefix.to_s, '').sub(/\.[^.]+\z/, ''))
15
+
16
+ if should_validate?
17
+ validator = Swalidate::Validator::Main.new(@endpoint, @request.params)
18
+ validator.call
19
+ return error_response(validator.errors) unless validator.valid?
20
+ end
21
+
22
+ @app.call(env)
23
+ end
24
+
25
+ private
26
+
27
+ def error_response(errors)
28
+ [
29
+ 400,
30
+ { 'Content-Type' => 'application/vnd.api+json' },
31
+ [{ errors: errors }.to_json]
32
+ ]
33
+ end
34
+
35
+ def should_validate?
36
+ valid_subdomain? && valid_path_prefix? && valid_path?
37
+ end
38
+
39
+ def valid_subdomain?
40
+ @subdomain.to_s == @request.subdomain.to_s
41
+ end
42
+
43
+ def valid_path_prefix?
44
+ @request.path =~ Regexp.new(@path_prefix.to_s)
45
+ end
46
+
47
+ def valid_path?
48
+ @endpoint.should_validate?
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,17 @@
1
+ module Swalidate
2
+ class Schema
3
+ attr_reader :paths, :definitions
4
+
5
+ def initialize(file_path)
6
+ swagger = Swagger.load(file_path)
7
+ # TODO: error handling for files
8
+
9
+ @paths = swagger.paths
10
+ @definitions = swagger.definitions
11
+ end
12
+
13
+ def endpoint(method, path)
14
+ Swalidate::Endpoint.new(paths[path] && paths[path][method.downcase])
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,94 @@
1
+ # https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types
2
+ # https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#fixed-fields-8
3
+
4
+ require 'date'
5
+
6
+ module Swalidate
7
+ module Types
8
+ class Main
9
+ attr_reader :param, :casted_value, :errors
10
+
11
+ def initialize(param, value)
12
+ @param = param
13
+ @errors = []
14
+ @casted_value = cast_value(value)
15
+ end
16
+
17
+ def valid?
18
+ return true if casted_value == 'NilObject.new'
19
+
20
+ # TODO:
21
+ # errors << {
22
+ # parameter: param['name'],
23
+ # message: "'#{param['name']}' can be minimum #{param['minimum']}"
24
+ # }
25
+
26
+ case casted_value
27
+ when Numeric
28
+ if param['minimum'] && casted_value < param['minimum']
29
+ @errors << {
30
+ 'message' => "'#{param['name']}' can be minimum #{param['minimum']}"
31
+ }
32
+ end
33
+ if param['maximum'] && casted_value > param['maximum']
34
+ @errors << {
35
+ 'message' => "'#{param['name']}' can be maximum #{param['maximum']}"
36
+ }
37
+ end
38
+ when String
39
+ if param['minLength'] && casted_value.length < param['minLength']
40
+ @errors << {
41
+ 'message' => "Length of '#{param['name']}' can be minimum #{param['minLength']}"
42
+ }
43
+ end
44
+ if param['maxLength'] && casted_value.length > param['maxLength']
45
+ @errors << {
46
+ 'message' => "Length of '#{param['name']}' can be maximum #{param['maxLength']}"
47
+ }
48
+ end
49
+ if param['pattern'] && !(casted_value =~ Regexp.new(param['pattern']))
50
+ @errors << {
51
+ 'message' => "'#{param['name']}' is not fit to pattern #{param['pattern']}"
52
+ }
53
+ end
54
+ end
55
+
56
+ errors.empty?
57
+ end
58
+
59
+ private
60
+
61
+ def cast_value(value)
62
+ return 'NilObject.new' unless value # TODO: create a NilObject class
63
+
64
+ begin
65
+ case param['type']
66
+ when 'integer' then Integer(value)
67
+ when 'number' then Float(value)
68
+ when 'string'
69
+ case param['format']
70
+ # TODO: date parsing: https://xml2rfc.tools.ietf.org/public/rfc/html/rfc3339.html#anchor14
71
+ # 2015-02-01T00:00:00+00:00
72
+ # Date.rfc3339(value)
73
+ # DateTime.rfc3339(value)
74
+ when 'date' then Date.parse(value)
75
+ when 'date-time' then DateTime.parse(value)
76
+ else String(value)
77
+ end
78
+ when 'boolean' then %w(true false).include?(value.to_s) ? value : raise(ArgumentError)
79
+ else fail 'type is not valid' # TODO: handle this
80
+ end
81
+ rescue ArgumentError, TypeError => error
82
+ @errors << {
83
+ 'message' => "'#{value}' is not a valid #{param['type']}"
84
+ }
85
+ nil
86
+ rescue StandardError => error
87
+ fail error
88
+ nil
89
+ # TODO: handle
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,31 @@
1
+ module Swalidate
2
+ module Validator
3
+ class Main
4
+ attr_reader :endpoint_params, :request_params, :errors
5
+
6
+ def initialize(endpoint, request_params)
7
+ @endpoint_params = endpoint.parameters
8
+ @request_params = request_params
9
+ @errors = []
10
+ end
11
+
12
+ def call
13
+ # TODO: allow extra parameters?
14
+ endpoint_params.each do |param|
15
+ parameter = Swalidate::Validator::Parameter.new(param, request_params[param['name']])
16
+ if parameter.invalid?
17
+ @errors += parameter.errors
18
+ end
19
+ end
20
+ end
21
+
22
+ def valid?
23
+ errors.empty?
24
+ end
25
+
26
+ def invalid?
27
+ !valid?
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,43 @@
1
+ module Swalidate
2
+ module Validator
3
+ class Parameter
4
+ attr_reader :param, :value, :type
5
+
6
+ def initialize(param, value)
7
+ @param = param
8
+ @value = value
9
+ @type = Swalidate::Types::Main.new(param, value)
10
+ end
11
+
12
+ def valid?
13
+ return false if required? && !exists?
14
+
15
+ if exists?
16
+ type.valid?
17
+ else
18
+ !required?
19
+ end
20
+ end
21
+
22
+ def errors
23
+ if exists?
24
+ type.errors
25
+ else
26
+ required? ? ["'#{param['name']}' can't be blank."] : []
27
+ end
28
+ end
29
+
30
+ def invalid?
31
+ !valid?
32
+ end
33
+
34
+ def required?
35
+ param['required']
36
+ end
37
+
38
+ def exists?
39
+ !!value
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,3 +1,3 @@
1
1
  module Swalidate
2
- VERSION = "0.1.0"
2
+ VERSION = '0.1.1'.freeze
3
3
  end
data/lib/swalidate.rb CHANGED
@@ -1,4 +1,13 @@
1
- require "swalidate/version"
1
+ require 'forwardable'
2
+ require 'swagger'
3
+ require 'action_dispatch'
4
+ require 'swalidate/version'
5
+ require 'swalidate/schema'
6
+ require 'swalidate/endpoint'
7
+ require 'swalidate/types/main'
8
+ require 'swalidate/validator/parameter'
9
+ require 'swalidate/validator/main'
10
+ require 'swalidate/middleware'
2
11
 
3
12
  module Swalidate
4
13
  # Your code goes here...
Binary file
data/swalidate.gemspec CHANGED
@@ -4,15 +4,15 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'swalidate/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "swalidate"
7
+ spec.name = 'swalidate'
8
8
  spec.version = Swalidate::VERSION
9
- spec.authors = ["Furkan Ayhan"]
10
- spec.email = ["furkanayhn@gmail.com"]
9
+ spec.authors = ['Furkan Ayhan']
10
+ spec.email = ['furkanayhn@gmail.com']
11
11
 
12
- spec.summary = "Rack validation middleware using Swagger"
13
- spec.description = "Rack validation middleware using Swagger"
14
- spec.homepage = "https://github.com/furkanayhan/swalidate"
15
- spec.license = "MIT"
12
+ spec.summary = 'Rack validation middleware using Swagger'
13
+ spec.description = 'Rack validation middleware using Swagger'
14
+ spec.homepage = 'https://github.com/furkanayhan/swalidate'
15
+ spec.license = 'MIT'
16
16
 
17
17
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
18
  # to allow pushing to a single host or delete this section to allow pushing to any host.
@@ -26,11 +26,16 @@ Gem::Specification.new do |spec|
26
26
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
27
27
  f.match(%r{^(test|spec|features)/})
28
28
  end
29
- spec.bindir = "exe"
29
+ spec.bindir = 'exe'
30
30
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
- spec.require_paths = ["lib"]
31
+ spec.require_paths = ['lib']
32
32
 
33
- spec.add_development_dependency "bundler", "~> 1.14"
34
- spec.add_development_dependency "rake", "~> 10.0"
35
- spec.add_development_dependency "rspec", "~> 3.0"
33
+ spec.add_dependency 'actionpack'
34
+ spec.add_dependency 'swagger-core'
35
+
36
+ spec.add_development_dependency 'bundler', '~> 1.14'
37
+ spec.add_development_dependency 'rake', '~> 10.0'
38
+ spec.add_development_dependency 'rspec', '~> 3.0'
39
+ spec.add_development_dependency 'rubocop'
40
+ spec.add_development_dependency 'pry'
36
41
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: swalidate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Furkan Ayhan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-01-26 00:00:00.000000000 Z
11
+ date: 2017-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionpack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: swagger-core
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: bundler
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +80,34 @@ dependencies:
52
80
  - - "~>"
53
81
  - !ruby/object:Gem::Version
54
82
  version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
55
111
  description: Rack validation middleware using Swagger
56
112
  email:
57
113
  - furkanayhn@gmail.com
@@ -61,6 +117,7 @@ extra_rdoc_files: []
61
117
  files:
62
118
  - ".gitignore"
63
119
  - ".rspec"
120
+ - ".rubocop.yml"
64
121
  - ".travis.yml"
65
122
  - Gemfile
66
123
  - LICENSE.txt
@@ -69,7 +126,14 @@ files:
69
126
  - bin/console
70
127
  - bin/setup
71
128
  - lib/swalidate.rb
129
+ - lib/swalidate/endpoint.rb
130
+ - lib/swalidate/middleware.rb
131
+ - lib/swalidate/schema.rb
132
+ - lib/swalidate/types/main.rb
133
+ - lib/swalidate/validator/main.rb
134
+ - lib/swalidate/validator/parameter.rb
72
135
  - lib/swalidate/version.rb
136
+ - swalidate-0.1.0.gem
73
137
  - swalidate.gemspec
74
138
  homepage: https://github.com/furkanayhan/swalidate
75
139
  licenses: