datadome 0.0.0 → 0.0.1

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: c0193ec317042795fc99d6514150da44711346b3
4
- data.tar.gz: f6f1f6e70ce36c5604989ebfaae97fdb85da4877
3
+ metadata.gz: fd4a9c24ac83994e1334eaa2464593739f364382
4
+ data.tar.gz: e3fa5a184303204530187e89ac09529950900ea2
5
5
  SHA512:
6
- metadata.gz: c65ada26774b82db0216b980386cab3872687951ba97b7918c0fd72055ac0ee37030d39d5b1a4580a4db2305e0cc69e67bd49446d81083b17e9fefd43702f03a
7
- data.tar.gz: 39ce5894e83b65507dbd7319c50dad7f9d0a3cb81e2946e3f5eef6761a0d4edc27f1818caa341674e222d6f4edc554982edf49eeddc30f91701dbf64a9043eb8
6
+ metadata.gz: 6a04aefc34becc8e081797effa886865b3962383d74a6f12aeab3b5cf1272b57ea6ffa648ef06f864859381675f7eca4feee3117ac0f42dfec3afb563ebfbde1
7
+ data.tar.gz: e01baa33dd83ca39299d2c9e214a77d0b5ec050d0d8f65adbe514b0ea8a924bb481c422cdac32fad410170148413360daf0d3b837150ac78ae77f349e04bbb55
data/.rspec.travis ADDED
@@ -0,0 +1,3 @@
1
+ --format progress
2
+ --color
3
+ --order rand
data/.rubocop.yml ADDED
@@ -0,0 +1,242 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'bin/*'
4
+ TargetRubyVersion: 2.3
5
+
6
+ Layout/AccessModifierIndentation:
7
+ EnforcedStyle: indent
8
+ SupportedStyles:
9
+ - outdent
10
+ - indent
11
+
12
+ Layout/AlignHash:
13
+ EnforcedHashRocketStyle: key
14
+ EnforcedColonStyle: key
15
+ EnforcedLastArgumentHashStyle: always_inspect
16
+
17
+ Layout/AlignParameters:
18
+ EnforcedStyle: with_fixed_indentation
19
+
20
+ Layout/EmptyLinesAroundClassBody:
21
+ EnforcedStyle: empty_lines_except_namespace
22
+
23
+ Layout/EmptyLinesAroundModuleBody:
24
+ EnforcedStyle: empty_lines_except_namespace
25
+
26
+ Layout/ExtraSpacing:
27
+ AllowForAlignment: false
28
+
29
+ Layout/FirstArrayElementLineBreak:
30
+ Enabled: true
31
+
32
+ Layout/FirstHashElementLineBreak:
33
+ Enabled: true
34
+
35
+ Layout/FirstMethodArgumentLineBreak:
36
+ Enabled: true
37
+
38
+ Layout/FirstParameterIndentation:
39
+ EnforcedStyle: consistent
40
+
41
+ Layout/IndentArray:
42
+ EnforcedStyle: consistent
43
+
44
+ Layout/IndentHash:
45
+ EnforcedStyle: consistent
46
+
47
+ Layout/MultilineAssignmentLayout:
48
+ Enabled: true
49
+ EnforcedStyle: new_line
50
+
51
+ Layout/MultilineMethodCallIndentation:
52
+ EnforcedStyle: indented
53
+
54
+ Layout/MultilineOperationIndentation:
55
+ EnforcedStyle: indented
56
+
57
+ Layout/SpaceAroundOperators:
58
+ AllowForAlignment: false
59
+
60
+ Layout/SpaceBeforeFirstArg:
61
+ AllowForAlignment: false
62
+
63
+ Lint/EndAlignment:
64
+ AutoCorrect: true
65
+
66
+ Lint/RedundantWithIndex:
67
+ Enabled: true
68
+
69
+ Lint/UnusedMethodArgument:
70
+ AllowUnusedKeywordArguments: true
71
+ IgnoreEmptyMethods: true
72
+
73
+ Metrics/AbcSize:
74
+ Enabled: false # todo
75
+ Max: 20 # default: 15
76
+
77
+ Metrics/BlockLength:
78
+ Enabled: false # todo
79
+ Exclude:
80
+ - "config/routes.rb"
81
+ - "config/routes/*"
82
+ - "lib/tasks/**/*"
83
+
84
+ Metrics/CyclomaticComplexity:
85
+ Enabled: false # todo
86
+ Max: 10 # default: 6
87
+
88
+ Metrics/LineLength:
89
+ Enabled: false # todo
90
+ Max: 100 # default: 80
91
+
92
+ Metrics/MethodLength:
93
+ Enabled: false # todo
94
+ Exclude:
95
+ - "db/migrate/*"
96
+ Max: 12 # default: 10
97
+
98
+ Metrics/PerceivedComplexity:
99
+ Enabled: false # todo
100
+ Max: 10 # default: 7
101
+
102
+ Naming/VariableNumber:
103
+ EnforcedStyle: snake_case
104
+
105
+ Performance/HashEachMethods:
106
+ Enabled: false
107
+
108
+ Style/AsciiComments:
109
+ Enabled: false
110
+
111
+ Style/AndOr:
112
+ Enabled: true
113
+ EnforcedStyle: conditionals
114
+
115
+ Style/BracesAroundHashParameters:
116
+ Enabled: false
117
+
118
+ Style/Dir:
119
+ Enabled: true
120
+
121
+ Style/Documentation:
122
+ Enabled: false
123
+
124
+ Style/FormatStringToken:
125
+ Exclude:
126
+ - "config/routes.rb"
127
+ - "config/routes/*"
128
+
129
+ Style/FrozenStringLiteralComment:
130
+ Enabled: false # we'll do later
131
+
132
+ Style/Lambda:
133
+ Enabled: false
134
+
135
+
136
+ Style/MethodCallWithArgsParentheses:
137
+ Enabled: true # false by default
138
+ Exclude:
139
+ - "Gemfile"
140
+ - "*.gemspec"
141
+ IgnoreMacros: true
142
+ IgnoredMethods:
143
+ - include
144
+ - load
145
+ - print
146
+ - private
147
+ - protected
148
+ - public
149
+ - puts
150
+ - raise
151
+ - require
152
+ - require_relative
153
+ # rake
154
+ - desc
155
+ - namespace
156
+ - task
157
+ # swagger
158
+ - key
159
+ - operation
160
+ - property
161
+ - response
162
+ - security_definition
163
+ - swagger_path
164
+ - swagger_schema
165
+
166
+ Style/ModuleFunction:
167
+ Enabled: false
168
+
169
+ Style/ReturnNil:
170
+ Enabled: true
171
+
172
+ Style/SignalException:
173
+ EnforcedStyle: only_raise
174
+
175
+ Style/StringLiterals:
176
+ Enabled: true
177
+ EnforcedStyle: double_quotes
178
+
179
+ Style/StringLiteralsInInterpolation:
180
+ Enabled: true
181
+ EnforcedStyle: double_quotes
182
+
183
+ Style/TrailingCommaInArguments:
184
+ EnforcedStyleForMultiline: no_comma
185
+
186
+ Style/TrailingCommaInLiteral:
187
+ EnforcedStyleForMultiline: comma
188
+
189
+ #
190
+ # Temporary disabled
191
+ #
192
+
193
+ Lint/IneffectiveAccessModifier:
194
+ Enabled: false
195
+
196
+ Lint/RescueException:
197
+ Enabled: false
198
+
199
+ Lint/RescueWithoutErrorClass:
200
+ Enabled: false
201
+
202
+ Lint/ShadowedException:
203
+ Enabled: false
204
+
205
+ Metrics/BlockNesting:
206
+ Enabled: false
207
+
208
+ Metrics/ClassLength:
209
+ Enabled: false
210
+
211
+ Metrics/ModuleLength:
212
+ Enabled: false
213
+
214
+ Metrics/ParameterLists:
215
+ Enabled: false
216
+
217
+ Naming/AccessorMethodName:
218
+ Enabled: false
219
+
220
+ Naming/PredicateName:
221
+ Enabled: false
222
+
223
+ Security/Eval:
224
+ Enabled: false
225
+
226
+ Style/ClassAndModuleChildren:
227
+ Enabled: false
228
+
229
+ Style/ClassVars:
230
+ Enabled: false
231
+
232
+ Style/GuardClause:
233
+ Enabled: false
234
+
235
+ Style/NumericPredicate:
236
+ Enabled: false
237
+
238
+ Style/SafeNavigation:
239
+ Enabled: false
240
+
241
+ Style/StructInheritance:
242
+ Enabled: false
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.5
data/.travis.yml CHANGED
@@ -1,5 +1,13 @@
1
- sudo: false
1
+ before_install:
2
+ - gem install bundler -v 1.15.4
3
+ before_script:
4
+ - cp -f .rspec.travis .rspec
5
+ bundler_args: --without local
6
+ dist: trusty
2
7
  language: ruby
3
8
  rvm:
4
- - 2.3.3
5
- before_install: gem install bundler -v 1.15.3
9
+ - 2.3.5
10
+ - 2.4.2
11
+ script:
12
+ - bundle exec rake ci
13
+ sudo: false
data/Gemfile CHANGED
@@ -1,6 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source "https://rubygems.org"
2
4
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
6
 
5
7
  # Specify your gem's dependencies in datadome.gemspec
6
8
  gemspec
9
+
10
+ group :local do
11
+ # Guard
12
+ gem "guard-rspec", require: false
13
+ gem "terminal-notifier-guard", require: false # OS X
14
+ end
data/Guardfile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ guard(:rspec, cmd: "bundle exec rspec") do
4
+ require "guard/rspec/dsl"
5
+ dsl = Guard::RSpec::Dsl.new(self)
6
+
7
+ # RSpec files
8
+ rspec = dsl.rspec
9
+ watch(rspec.spec_helper) { rspec.spec_dir }
10
+ watch(rspec.spec_support) { rspec.spec_dir }
11
+ watch(rspec.spec_files)
12
+
13
+ # Ruby files
14
+ ruby = dsl.ruby
15
+ dsl.watch_spec_files_for(ruby.lib_files)
16
+ end
data/README.md CHANGED
@@ -1,7 +1,11 @@
1
1
  # Datadome
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/datadome.svg)](https://badge.fury.io/rb/datadome) [![Build Status](https://travis-ci.org/shopmium/datadome.svg?branch=master)](https://travis-ci.org/shopmium/datadome)
4
+
3
5
  Rack middleware for Datadome. https://datadome.co/
4
6
 
7
+ This is still an early version.
8
+
5
9
  ## Installation
6
10
 
7
11
  Add this line to your application's Gemfile:
@@ -18,9 +22,30 @@ Or install it yourself as:
18
22
 
19
23
  $ gem install datadome
20
24
 
21
- ## Usage
25
+ ## Usage with Rails
26
+
27
+ Create a `config/initializers/datadome.rb` file:
28
+
29
+ ```ruby
30
+ require "datadome"
31
+
32
+ Datadome.configure do |config|
33
+ # Set the Datadome API key
34
+ config.api_key = "my-api-key"
35
+ # or use an environment variable (better)
36
+ # config.api_key = ENV["DATADOME_API_KEY"]
37
+
38
+ # Choose the closest Datadome API endpoint
39
+ # More info at https://docs.datadome.co/docs/api-server
40
+ config.api_server = "api-us-east-1.datadome.co"
41
+ end
42
+
43
+ Datadome.logger = Logger.new(STDOUT, level: :debug)
44
+
45
+ Rails.configuration.middleware.insert_after(ActionDispatch::RemoteIp, ::Datadome::Rack)
46
+ ```
22
47
 
23
- TODO: Write usage instructions here
48
+ For the Javascript snippet, insert it directly in your layout file.
24
49
 
25
50
  ## Development
26
51
 
data/Rakefile CHANGED
@@ -1,6 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rspec/core/rake_task"
5
+ require "rubocop/rake_task"
3
6
 
4
7
  RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new
9
+
10
+ task default: :spec
5
11
 
6
- task :default => :spec
12
+ task ci: %i[spec rubocop]
data/datadome.gemspec CHANGED
@@ -1,27 +1,36 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  lib = File.expand_path("../lib", __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require "datadome/version"
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "datadome"
8
- spec.version = Datadome::VERSION
9
- spec.authors = ["Maxime Garcia"]
10
- spec.email = ["maxime.garcia@shopmium.com"]
8
+ spec.name = "datadome"
9
+ spec.version = Datadome::VERSION
10
+ spec.authors = ["Maxime Garcia"]
11
+ spec.email = ["maxime.garcia@shopmium.com"]
11
12
 
12
- spec.summary = "Rack middleware for Datadome."
13
- spec.description = "Rack middleware for Datadome."
14
- spec.homepage = "https://github.com/shopmium/datadome"
13
+ spec.summary = "Rack middleware for Datadome."
14
+ spec.description = "Rack middleware for Datadome."
15
+ spec.homepage = "https://github.com/shopmium/datadome"
15
16
  spec.license = "MIT"
16
17
 
17
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
- f.match(%r{^(test|spec|features)/})
19
- end
20
- spec.bindir = "exe"
21
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.files =
19
+ `git ls-files -z`.split("\x0").reject do |f|
20
+ f.match(%r{^(test|spec|features)/})
21
+ end
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
24
  spec.require_paths = ["lib"]
23
25
 
26
+ spec.required_ruby_version = ">= 2.3.0"
27
+
28
+ spec.add_runtime_dependency "rack"
29
+ spec.add_runtime_dependency "faraday", ">= 0.9.2"
30
+
24
31
  spec.add_development_dependency "bundler", "~> 1.15"
25
32
  spec.add_development_dependency "rake", "~> 10.0"
26
33
  spec.add_development_dependency "rspec", "~> 3.0"
34
+ spec.add_development_dependency "rubocop", "0.50.0"
35
+ spec.add_development_dependency "timecop", "~> 0.9.1"
27
36
  end
data/lib/datadome.rb CHANGED
@@ -1,5 +1,35 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "datadome/version"
4
+ require "datadome/client"
5
+ require "datadome/configuration"
6
+ require "datadome/inquirer"
7
+ require "datadome/validation_request"
8
+ require "datadome/validation_response"
9
+ require "datadome/rack"
2
10
 
3
11
  module Datadome
4
- # Your code goes here...
12
+
13
+ class << self
14
+
15
+ attr_writer :configuration
16
+
17
+ end
18
+
19
+ def self.configuration
20
+ @configuration ||= Configuration.new
21
+ end
22
+
23
+ def self.configure
24
+ yield(configuration)
25
+ end
26
+
27
+ def self.logger
28
+ @logger ||= Logger.new(STDOUT, level: :info)
29
+ end
30
+
31
+ def self.logger=(logger)
32
+ @logger = logger
33
+ end
34
+
5
35
  end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "socket"
5
+
6
+ module Datadome
7
+ class Client
8
+
9
+ OPEN_TIMEOUT = 1
10
+ TIMEOUT = 3
11
+
12
+ class << self
13
+
14
+ def base_url
15
+ "https://#{Datadome.configuration.api_server}/"
16
+ end
17
+
18
+ def default_params
19
+ {
20
+ "Key" => Datadome.configuration.api_key,
21
+ "RequestModuleName" => "DataDome Ruby Gem",
22
+ "ModuleVersion" => ::Datadome::VERSION,
23
+ "ServerName" => hostname,
24
+ }
25
+ end
26
+
27
+ def hostname
28
+ Socket.gethostname
29
+ end
30
+
31
+ end
32
+
33
+ def check
34
+ response =
35
+ connection.get do |req|
36
+ req.url("check")
37
+ end
38
+
39
+ response
40
+ end
41
+
42
+ def validate_request(data)
43
+ data = data.merge(self.class.default_params)
44
+
45
+ response =
46
+ connection.post do |req|
47
+ req.url("validate-request")
48
+ req.headers["User-Agent"] = "DataDome"
49
+ req.body = data
50
+ end
51
+
52
+ ValidationResponse.from_faraday_response(response)
53
+ rescue Faraday::Error::ConnectionFailed, Faraday::Error::TimeoutError => e
54
+ Datadome.logger.warn("Datadome: Timeout #{e}")
55
+
56
+ ValidationResponse.pass
57
+ end
58
+
59
+ private
60
+
61
+ def connection
62
+ @connection ||=
63
+ Faraday.new(url: self.class.base_url) do |faraday|
64
+ faraday.request(:url_encoded)
65
+ faraday.adapter(Faraday.default_adapter)
66
+ faraday.options[:open_timeout] = OPEN_TIMEOUT
67
+ faraday.options[:timeout] = TIMEOUT
68
+ end
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+
5
+ module Datadome
6
+ class Configuration
7
+
8
+ def initialize
9
+ @api_server = "api.datadome.co"
10
+ end
11
+
12
+ attr_accessor :api_key, :api_server
13
+
14
+ end
15
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack"
4
+
5
+ module Datadome
6
+ class Inquirer
7
+
8
+ def initialize(env)
9
+ @env = env
10
+ end
11
+
12
+ def build_response
13
+ @validation_response.to_rack_response
14
+ end
15
+
16
+ def enriching
17
+ status, headers, response = yield
18
+
19
+ added_headers = ::Rack::Utils::HeaderHash.new(@validation_response.response_headers)
20
+
21
+ headers = ::Rack::Utils::HeaderHash.new(headers)
22
+ existing_set_cookie = headers["Set-Cookie"]
23
+
24
+ headers.merge!(added_headers)
25
+
26
+ if added_headers["Set-Cookie"] && existing_set_cookie
27
+ headers["Set-Cookie"] = merge_cookie(existing_set_cookie, added_headers["Set-Cookie"])
28
+ end
29
+
30
+ [status, headers, response]
31
+ end
32
+
33
+ def intercept?
34
+ @validation_response.pass == false || @validation_response.redirect
35
+ end
36
+
37
+ def inquire
38
+ @validation_response = validate_request
39
+ end
40
+
41
+ private
42
+
43
+ def validate_request
44
+ validation_request = ValidationRequest.from_env(@env)
45
+
46
+ Datadome.logger.debug("Datadome: Validation Request: #{validation_request.inspect}")
47
+
48
+ client = Client.new
49
+ client.validate_request(validation_request.to_api_params).tap do |validation_response|
50
+ Datadome.logger.debug("Datadome: Validation Response: #{validation_response.inspect}")
51
+ end
52
+ end
53
+
54
+ def merge_cookie(old_cookie, cookie)
55
+ case old_cookie
56
+ when nil, ""
57
+ cookie
58
+ when String
59
+ [old_cookie, cookie].join("\n")
60
+ when Array
61
+ (old_cookie + [cookie]).join("\n")
62
+ end
63
+ end
64
+
65
+ end
66
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack"
4
+
5
+ module Datadome
6
+ class Rack
7
+
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ inquirer = Inquirer.new(env)
14
+ inquired = inquirer.inquire
15
+
16
+ return @app.call(env) unless inquired
17
+
18
+ if inquirer.intercept?
19
+ inquirer.build_response
20
+ else
21
+ inquirer.enriching do
22
+ @app.call(env)
23
+ end
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,177 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadome
4
+ class ValidationRequest
5
+
6
+ @definitions = []
7
+
8
+ class << self
9
+
10
+ attr_reader(:definitions)
11
+
12
+ def limit_size(value, size:)
13
+ if value && size
14
+ value[0, size]
15
+ else
16
+ value
17
+ end
18
+ end
19
+
20
+ def from_env(env)
21
+ request = ::Rack::Request.new(env)
22
+
23
+ new.tap do |validation_request|
24
+ definitions.each do |definition|
25
+ value = definition[:block].call(env, request)
26
+ next if value.nil?
27
+
28
+ validation_request[definition[:param_name]] = limit_size(value, size: definition[:max_size])
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def capture(param_name, max_size: nil, &block)
36
+ definitions << {
37
+ param_name: param_name,
38
+ block: block,
39
+ max_size: max_size,
40
+ }
41
+ end
42
+
43
+ end
44
+
45
+ capture("IP") do |_env, request|
46
+ request.ip
47
+ end
48
+
49
+ capture("Port") do |_env, request|
50
+ request.port
51
+ end
52
+
53
+ capture("Protocol") do |_env, request|
54
+ request.scheme && request.scheme.upcase
55
+ end
56
+
57
+ capture("Method") do |_env, request|
58
+ request.request_method
59
+ end
60
+
61
+ capture("Request", max_size: 2048) do |env, _request|
62
+ env["ORIGINAL_FULLPATH"]
63
+ end
64
+
65
+ capture("TimeRequest") do |env, _request|
66
+ usec_timestamp = (env["HTTP_X_REQUEST_START"] || "").gsub("t=", "").to_i
67
+ usec_timestamp = (Time.now.to_f * 1_000_000).round if usec_timestamp.zero?
68
+
69
+ usec_timestamp
70
+ end
71
+
72
+ capture("Accept", max_size: 512) do |env, _request|
73
+ env["HTTP_ACCEPT"]
74
+ end
75
+
76
+ capture("AcceptCharset", max_size: 128) do |env, _request|
77
+ env["HTTP_ACCEPT_CHARSET"]
78
+ end
79
+
80
+ capture("AcceptEncoding", max_size: 128) do |env, _request|
81
+ env["HTTP_ACCEPT_ENCODING"]
82
+ end
83
+
84
+ capture("AcceptLanguage", max_size: 256) do |env, _request|
85
+ env["HTTP_ACCEPT_LANGUAGE"]
86
+ end
87
+
88
+ capture("CacheControl") do |env, _request|
89
+ env["HTTP_CACHE_CONTROL"]
90
+ end
91
+
92
+ capture("Connection") do |env, _request|
93
+ env["HTTP_CONNECTION"]
94
+ end
95
+
96
+ capture("Host") do |_env, request|
97
+ request.host
98
+ end
99
+
100
+ capture("Origin", max_size: 512) do |env, _request|
101
+ env["HTTP_ORIGIN"]
102
+ end
103
+
104
+ capture("Pragma") do |env, _request|
105
+ env["HTTP_PRAGMA"]
106
+ end
107
+
108
+ capture("Referer", max_size: 1024) do |env, _request|
109
+ env["HTTP_REFERER"]
110
+ end
111
+
112
+ capture("UserAgent", max_size: 768) do |env, _request|
113
+ env["HTTP_USER_AGENT"]
114
+ end
115
+
116
+ capture("XForwaredForIP", max_size: 512) do |env, _request|
117
+ env["HTTP_X_FORWARDED_FOR"]
118
+ end
119
+
120
+ capture("X-Requested-With", max_size: 128) do |env, _request|
121
+ env["HTTP_X_REQUESTED_WITH"]
122
+ end
123
+
124
+ capture("HeadersList", max_size: 512) do |env, _request|
125
+ headers =
126
+ env.keys
127
+ .select { |key| key[0, 5] == "HTTP_" }
128
+ .map { |key| key.gsub("HTTP_", "").downcase.tr("_", "-") }
129
+ headers -= ["version"]
130
+
131
+ headers.join(",")
132
+ end
133
+
134
+ capture("CookiesLen") do |env, _request|
135
+ next(0) unless env["HTTP_COOKIE"]
136
+
137
+ env["HTTP_COOKIE"].length
138
+ end
139
+
140
+ capture("PostParamLen") do |_env, request|
141
+ raw_post_body = request.body
142
+ next(0) unless raw_post_body
143
+
144
+ data = raw_post_body.read
145
+ raw_post_body.rewind if raw_post_body.respond_to?(:rewind)
146
+
147
+ (data || "").length
148
+ end
149
+
150
+ capture("AuthorizationLen") do |env, _request|
151
+ next(0) unless env["HTTP_AUTHORIZATION"]
152
+
153
+ env["HTTP_AUTHORIZATION"].length
154
+ end
155
+
156
+ capture("ClientID", max_size: 128) do |_env, request|
157
+ request.cookies["datadome"]
158
+ end
159
+
160
+ def initialize
161
+ @data = {}
162
+ end
163
+
164
+ def [](name)
165
+ @data[name]
166
+ end
167
+
168
+ def []=(name, value)
169
+ @data[name] = value
170
+ end
171
+
172
+ def to_api_params
173
+ @data
174
+ end
175
+
176
+ end
177
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadome
4
+ class ValidationResponse
5
+
6
+ class << self
7
+
8
+ def pass
9
+ new(pass: true, redirect: false)
10
+ end
11
+
12
+ def from_faraday_response(response)
13
+ validation_response =
14
+ if response.status == 403
15
+ new(pass: false, redirect: false, response_status: 403, response_body: response.body)
16
+ elsif response.status == 301 || response.status == 302
17
+ new(pass: false, redirect: true, response_status: response.status, redirection_location: response.headers["Location"])
18
+ else
19
+ pass
20
+ end
21
+
22
+ parse_headers_list(response.headers["X-DataDome-request-headers"]).each do |key|
23
+ validation_response.request_headers[key] = response.headers[key]
24
+ end
25
+
26
+ parse_headers_list(response.headers["X-DataDome-headers"]).each do |key|
27
+ validation_response.response_headers[key] = response.headers[key]
28
+ end
29
+
30
+ validation_response
31
+ end
32
+
33
+ def parse_headers_list(list)
34
+ return [] if list.nil? || list == ""
35
+
36
+ list.split(" ")
37
+ end
38
+
39
+ end
40
+
41
+ attr_accessor :pass, :redirect
42
+ attr_accessor :redirection_location, :request_headers, :response_body, :response_headers, :response_status
43
+
44
+ def initialize(attrs = {})
45
+ self.request_headers = {}
46
+ self.response_headers = {}
47
+
48
+ attrs.each do |key, value|
49
+ public_send("#{key}=", value)
50
+ end
51
+ end
52
+
53
+ def to_rack_response
54
+ response = ::Rack::Response.new(@response_body || [], @response_status, @response_headers)
55
+ response.redirect(@redirection_location, @response_status) if @redirect
56
+
57
+ response.finish
58
+ end
59
+
60
+ end
61
+ end
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Datadome
2
- VERSION = "0.0.0".freeze
4
+
5
+ VERSION = "0.0.1"
6
+
3
7
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datadome
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maxime Garcia
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-08-07 00:00:00.000000000 Z
11
+ date: 2017-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
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: faraday
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.9.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.9.2
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.50.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.50.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: timecop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.9.1
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.9.1
55
111
  description: Rack middleware for Datadome.
56
112
  email:
57
113
  - maxime.garcia@shopmium.com
@@ -61,8 +117,12 @@ extra_rdoc_files: []
61
117
  files:
62
118
  - ".gitignore"
63
119
  - ".rspec"
120
+ - ".rspec.travis"
121
+ - ".rubocop.yml"
122
+ - ".ruby-version"
64
123
  - ".travis.yml"
65
124
  - Gemfile
125
+ - Guardfile
66
126
  - LICENSE.txt
67
127
  - README.md
68
128
  - Rakefile
@@ -70,6 +130,12 @@ files:
70
130
  - bin/setup
71
131
  - datadome.gemspec
72
132
  - lib/datadome.rb
133
+ - lib/datadome/client.rb
134
+ - lib/datadome/configuration.rb
135
+ - lib/datadome/inquirer.rb
136
+ - lib/datadome/rack.rb
137
+ - lib/datadome/validation_request.rb
138
+ - lib/datadome/validation_response.rb
73
139
  - lib/datadome/version.rb
74
140
  homepage: https://github.com/shopmium/datadome
75
141
  licenses:
@@ -83,7 +149,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
83
149
  requirements:
84
150
  - - ">="
85
151
  - !ruby/object:Gem::Version
86
- version: '0'
152
+ version: 2.3.0
87
153
  required_rubygems_version: !ruby/object:Gem::Requirement
88
154
  requirements:
89
155
  - - ">="
@@ -91,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
157
  version: '0'
92
158
  requirements: []
93
159
  rubyforge_project:
94
- rubygems_version: 2.6.12
160
+ rubygems_version: 2.6.13
95
161
  signing_key:
96
162
  specification_version: 4
97
163
  summary: Rack middleware for Datadome.