mihari 6.2.0 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (160) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -10
  3. data/.rubocop.yml +2 -0
  4. data/Dockerfile +13 -0
  5. data/config.ru +5 -3
  6. data/docker-compose.yml +62 -0
  7. data/exe/mihari +2 -1
  8. data/lefthook.yml +8 -0
  9. data/lib/mihari/actor.rb +4 -4
  10. data/lib/mihari/analyzers/base.rb +16 -0
  11. data/lib/mihari/analyzers/binaryedge.rb +4 -2
  12. data/lib/mihari/analyzers/censys.rb +7 -5
  13. data/lib/mihari/analyzers/circl.rb +5 -3
  14. data/lib/mihari/analyzers/crtsh.rb +4 -1
  15. data/lib/mihari/analyzers/dnstwister.rb +1 -1
  16. data/lib/mihari/analyzers/feed.rb +12 -20
  17. data/lib/mihari/analyzers/fofa.rb +6 -8
  18. data/lib/mihari/analyzers/greynoise.rb +4 -2
  19. data/lib/mihari/analyzers/hunterhow.rb +4 -2
  20. data/lib/mihari/analyzers/onyphe.rb +4 -2
  21. data/lib/mihari/analyzers/otx.rb +5 -3
  22. data/lib/mihari/analyzers/passivetotal.rb +29 -12
  23. data/lib/mihari/analyzers/pulsedive.rb +5 -3
  24. data/lib/mihari/analyzers/securitytrails.rb +32 -8
  25. data/lib/mihari/analyzers/shodan.rb +4 -2
  26. data/lib/mihari/analyzers/urlscan.rb +4 -2
  27. data/lib/mihari/analyzers/virustotal.rb +5 -5
  28. data/lib/mihari/analyzers/virustotal_intelligence.rb +4 -2
  29. data/lib/mihari/analyzers/zoomeye.rb +4 -2
  30. data/lib/mihari/cli/{main.rb → application.rb} +17 -5
  31. data/lib/mihari/cli/artifact.rb +14 -0
  32. data/lib/mihari/cli/config.rb +14 -0
  33. data/lib/mihari/cli/rule.rb +1 -0
  34. data/lib/mihari/cli/tag.rb +14 -0
  35. data/lib/mihari/clients/base.rb +2 -2
  36. data/lib/mihari/clients/binaryedge.rb +2 -2
  37. data/lib/mihari/clients/crtsh.rb +2 -9
  38. data/lib/mihari/clients/fofa.rb +1 -1
  39. data/lib/mihari/clients/hunterhow.rb +1 -1
  40. data/lib/mihari/clients/mmdb.rb +28 -0
  41. data/lib/mihari/clients/passivetotal.rb +7 -20
  42. data/lib/mihari/clients/securitytrails.rb +19 -43
  43. data/lib/mihari/clients/shodan_internet_db.rb +28 -0
  44. data/lib/mihari/clients/the_hive.rb +7 -5
  45. data/lib/mihari/commands/alert.rb +53 -11
  46. data/lib/mihari/commands/artifact.rb +66 -0
  47. data/lib/mihari/commands/config.rb +23 -0
  48. data/lib/mihari/commands/database.rb +1 -1
  49. data/lib/mihari/commands/rule.rb +40 -27
  50. data/lib/mihari/commands/search.rb +10 -11
  51. data/lib/mihari/commands/sidekiq.rb +31 -0
  52. data/lib/mihari/commands/tag.rb +46 -0
  53. data/lib/mihari/commands/web.rb +6 -7
  54. data/lib/mihari/{mixins/autonomous_system.rb → concerns/autonomous_system_normalizable.rb} +5 -3
  55. data/lib/mihari/concerns/configurable.rb +72 -0
  56. data/lib/mihari/concerns/database_connectable.rb +16 -0
  57. data/lib/mihari/{mixins/unwrap_error.rb → concerns/error_unwrappable.rb} +5 -3
  58. data/lib/mihari/{mixins/falsepositive.rb → concerns/falsepositive_validatable.rb} +5 -3
  59. data/lib/mihari/{mixins/refang.rb → concerns/refangable.rb} +5 -3
  60. data/lib/mihari/{mixins → concerns}/retriable.rb +4 -2
  61. data/lib/mihari/config.rb +13 -12
  62. data/lib/mihari/database.rb +30 -42
  63. data/lib/mihari/emitters/database.rb +5 -6
  64. data/lib/mihari/emitters/misp.rb +4 -11
  65. data/lib/mihari/emitters/slack.rb +7 -5
  66. data/lib/mihari/emitters/the_hive.rb +8 -58
  67. data/lib/mihari/emitters/webhook.rb +6 -6
  68. data/lib/mihari/enrichers/google_public_dns.rb +1 -1
  69. data/lib/mihari/enrichers/mmdb.rb +28 -0
  70. data/lib/mihari/enrichers/shodan.rb +3 -5
  71. data/lib/mihari/enrichers/whois.rb +3 -3
  72. data/lib/mihari/entities/alert.rb +3 -10
  73. data/lib/mihari/entities/artifact.rb +9 -9
  74. data/lib/mihari/entities/config.rb +2 -2
  75. data/lib/mihari/entities/cpe.rb +1 -0
  76. data/lib/mihari/entities/dns.rb +1 -0
  77. data/lib/mihari/entities/geolocation.rb +1 -0
  78. data/lib/mihari/entities/ip_address.rb +1 -3
  79. data/lib/mihari/entities/messages.rb +17 -0
  80. data/lib/mihari/entities/pagination.rb +11 -0
  81. data/lib/mihari/entities/port.rb +1 -0
  82. data/lib/mihari/entities/reverse_dns.rb +1 -0
  83. data/lib/mihari/entities/rule.rb +2 -20
  84. data/lib/mihari/entities/tag.rb +2 -2
  85. data/lib/mihari/entities/whois.rb +1 -0
  86. data/lib/mihari/errors.rb +2 -4
  87. data/lib/mihari/http.rb +4 -0
  88. data/lib/mihari/models/alert.rb +21 -76
  89. data/lib/mihari/models/artifact.rb +51 -31
  90. data/lib/mihari/models/autonomous_system.rb +5 -13
  91. data/lib/mihari/models/concerns/searchable.rb +50 -0
  92. data/lib/mihari/models/cpe.rb +3 -10
  93. data/lib/mihari/models/dns.rb +2 -6
  94. data/lib/mihari/models/geolocation.rb +7 -12
  95. data/lib/mihari/models/port.rb +3 -10
  96. data/lib/mihari/models/reverse_dns.rb +3 -8
  97. data/lib/mihari/models/rule.rb +16 -60
  98. data/lib/mihari/models/tag.rb +17 -1
  99. data/lib/mihari/models/tagging.rb +1 -1
  100. data/lib/mihari/models/whois.rb +1 -4
  101. data/lib/mihari/rule.rb +35 -24
  102. data/lib/mihari/schemas/alert.rb +1 -0
  103. data/lib/mihari/schemas/analyzer.rb +2 -2
  104. data/lib/mihari/schemas/concerns/orrable.rb +24 -0
  105. data/lib/mihari/schemas/emitter.rb +1 -2
  106. data/lib/mihari/schemas/enricher.rb +3 -4
  107. data/lib/mihari/schemas/macros.rb +1 -1
  108. data/lib/mihari/schemas/options.rb +0 -2
  109. data/lib/mihari/schemas/rule.rb +1 -2
  110. data/lib/mihari/services/{rule_builder.rb → builders.rb} +1 -6
  111. data/lib/mihari/services/creators.rb +22 -0
  112. data/lib/mihari/services/destroyers.rb +41 -0
  113. data/lib/mihari/services/enrichers.rb +25 -0
  114. data/lib/mihari/services/feed.rb +107 -0
  115. data/lib/mihari/services/getters.rb +58 -0
  116. data/lib/mihari/services/initializers.rb +22 -0
  117. data/lib/mihari/services/{alert_builder.rb → proxies.rb} +10 -40
  118. data/lib/mihari/services/searchers.rb +91 -0
  119. data/lib/mihari/sidekiq/application.rb +13 -0
  120. data/lib/mihari/sidekiq/jobs.rb +36 -0
  121. data/lib/mihari/structs/censys.rb +1 -1
  122. data/lib/mihari/structs/config.rb +10 -10
  123. data/lib/mihari/structs/filters.rb +12 -86
  124. data/lib/mihari/structs/google_public_dns.rb +1 -1
  125. data/lib/mihari/structs/greynoise.rb +1 -1
  126. data/lib/mihari/structs/mmdb.rb +115 -0
  127. data/lib/mihari/structs/onyphe.rb +1 -1
  128. data/lib/mihari/structs/shodan.rb +2 -2
  129. data/lib/mihari/version.rb +1 -1
  130. data/lib/mihari/web/{app.rb → application.rb} +28 -15
  131. data/lib/mihari/web/endpoints/alerts.rb +34 -81
  132. data/lib/mihari/web/endpoints/artifacts.rb +43 -63
  133. data/lib/mihari/web/endpoints/configs.rb +3 -5
  134. data/lib/mihari/web/endpoints/ip_addresses.rb +14 -15
  135. data/lib/mihari/web/endpoints/rules.rb +58 -137
  136. data/lib/mihari/web/endpoints/tags.rb +21 -17
  137. data/lib/mihari/web/middleware/capture_exceptions.rb +25 -0
  138. data/lib/mihari/web/middleware/{connection_adapter.rb → connection.rb} +4 -2
  139. data/lib/mihari/web/public/assets/index-cQUcyII5.js +1766 -0
  140. data/lib/mihari/web/public/assets/index-dVaNxqTC.css +1 -0
  141. data/lib/mihari/web/public/index.html +2 -3
  142. data/lib/mihari/web/public/redoc-static.html +385 -381
  143. data/lib/mihari.rb +56 -28
  144. data/mihari.gemspec +16 -8
  145. data/mkdocs.yml +5 -2
  146. data/requirements.txt +1 -1
  147. metadata +173 -42
  148. data/lib/mihari/commands/mixins.rb +0 -11
  149. data/lib/mihari/enrichers/ipinfo.rb +0 -52
  150. data/lib/mihari/entities/message.rb +0 -9
  151. data/lib/mihari/feed/parser.rb +0 -38
  152. data/lib/mihari/feed/reader.rb +0 -111
  153. data/lib/mihari/mixins/configurable.rb +0 -68
  154. data/lib/mihari/schemas/mixins.rb +0 -20
  155. data/lib/mihari/services/alert_runner.rb +0 -20
  156. data/lib/mihari/structs/ipinfo.rb +0 -53
  157. data/lib/mihari/web/middleware/error_notification_adapter.rb +0 -35
  158. data/lib/mihari/web/public/assets/index-1d77cd61.js +0 -1756
  159. data/lib/mihari/web/public/assets/index-4c8509ee.css +0 -1
  160. /data/lib/mihari/web/public/assets/{mode-yaml-24faa242.js → mode-yaml-BC4MIiYj.js} +0 -0
@@ -7,142 +7,38 @@ module Mihari
7
7
  # Rule API endpoint
8
8
  #
9
9
  class Rules < Grape::API
10
- class RuleSearcher < Mihari::Service
11
- class ResultValue
12
- # @return [Array<Mihari::Models::Rule>]
13
- attr_reader :rules
14
-
15
- # @return [Integer]
16
- attr_reader :total
17
-
18
- # @return [Mihari::Structs::Filters::Rule::SearchFilterWithPagination]
19
- attr_reader :filter
20
-
21
- #
22
- # @param [Array<Mihari::Models::Rule>] rules
23
- # @param [Integer] total
24
- # @param [Mihari::Structs::Filters::Rule::SearchFilterWithPagination] filter
25
- #
26
- def initialize(rules:, total:, filter:)
27
- @rules = rules
28
- @total = total
29
- @filter = filter
30
- end
31
- end
32
-
33
- #
34
- # @params [Hash]
35
- #
36
- # @return [ResultValue]
37
- #
38
- def call(params)
39
- filter = params.to_h.to_snake_keys
40
-
41
- # normalize keys
42
- filter["tag_name"] = filter["tag"]
43
- # symbolize hash keys
44
- filter = filter.to_h.symbolize_keys
45
-
46
- search_filter_with_pagination = Mihari::Structs::Filters::Rule::SearchFilterWithPagination.new(**filter)
47
- rules = Mihari::Models::Rule.search(search_filter_with_pagination)
48
- total = Mihari::Models::Rule.count(search_filter_with_pagination.without_pagination)
49
-
50
- ResultValue.new(rules: rules, total: total, filter: filter)
51
- end
52
- end
53
-
54
- class RuleGetter < Service
55
- #
56
- # @params [String] id
57
- #
58
- # @return [Mihari::Models::Rule]
59
- #
60
- def call(id)
61
- Mihari::Models::Rule.find id
62
- end
63
- end
64
-
65
- class RuleRunner < Service
66
- #
67
- # @param [String] id
10
+ class RuleCreateUpdater < Service
68
11
  #
69
- def call(id)
70
- rule = Mihari::Rule.from_model(Mihari::Models::Rule.find(id))
71
- rule.call
72
- end
73
- end
74
-
75
- class RuleCreator < Service
76
- #
77
- # @params [String]
12
+ # @params [String] yaml
13
+ # @params [Boolean] overwrite
78
14
  #
79
15
  # @return [Mihari::Models::Rule]
80
16
  #
81
- def call(yaml)
17
+ def call(yaml, overwrite: true)
82
18
  rule = Rule.from_yaml(yaml)
83
19
 
84
- found = Mihari::Models::Rule.find_by_id(rule.id)
85
- error!({ message: "ID:#{rule.id} is already registered" }, 400) unless found.nil?
20
+ raise IntegrityError, "ID:#{rule.id} is already registered" if rule.exists? && !overwrite
86
21
 
87
- rule.model.save
22
+ rule.update_or_create
88
23
  rule
89
24
  end
90
25
  end
91
26
 
92
- class RuleUpdater < Service
93
- #
94
- # @params [String] id
95
- # @params [String] yaml
96
- #
97
- # @return [Mihari::Models::Rule]
98
- #
99
- def call(id:, yaml:)
100
- Mihari::Models::Rule.find(id)
101
-
102
- rule = Rule.from_yaml(yaml)
103
- rule.model.save
104
- rule
105
- end
106
- end
107
-
108
- class RuleDestroyer < Service
109
- #
110
- # @param [String] id
111
- #
112
- def call(id)
113
- Mihari::Models::Rule.find(id).destroy
114
- end
115
- end
116
-
117
27
  namespace :rules do
118
- desc "Get Rule IDs", {
119
- is_array: true,
120
- success: Entities::RuleIDs,
121
- summary: "Get rule IDs"
122
- }
123
- get "/ids" do
124
- rule_ids = Mihari::Models::Rule.distinct.pluck(:id)
125
- present({ rule_ids: rule_ids }, with: Entities::RuleIDs)
126
- end
127
-
128
- desc "Search rules", {
28
+ desc "List/search rules", {
129
29
  is_array: true,
130
30
  success: Entities::RulesWithPagination,
131
- summary: "Search rules"
31
+ summary: "List/search rules"
132
32
  }
133
33
  params do
34
+ optional :q, type: String, default: ""
134
35
  optional :page, type: Integer, default: 1
135
36
  optional :limit, type: Integer, default: 10
136
- optional :title, type: String
137
- optional :description, type: String
138
- optional :tag, type: String
139
- optional :fromAt, type: DateTime
140
- optional :toAt, type: DateTime
141
37
  end
142
38
  get "/" do
143
- value = RuleSearcher.call(params.to_h)
39
+ value = Services::RuleSearcher.call(params.to_h)
144
40
  present({
145
- rules: value.rules,
41
+ results: value.results,
146
42
  total: value.total,
147
43
  current_page: value.filter[:page].to_i,
148
44
  page_size: value.filter[:limit].to_i
@@ -152,7 +48,7 @@ module Mihari
152
48
 
153
49
  desc "Get a rule", {
154
50
  success: Entities::Rule,
155
- failure: [{ code: 404, model: Entities::Message }],
51
+ failure: [{ code: 404, model: Entities::ErrorMessage }],
156
52
  summary: "Get a rule"
157
53
  }
158
54
  params do
@@ -160,41 +56,57 @@ module Mihari
160
56
  end
161
57
  get "/:id" do
162
58
  id = params[:id].to_s
163
- result = RuleGetter.result(params[:id].to_s)
59
+ result = Services::RuleGetter.result(params[:id].to_s)
164
60
  return present(result.value!, with: Entities::Rule) if result.success?
165
61
 
166
62
  case result.failure
167
63
  when ActiveRecord::RecordNotFound
168
- error!({ message: "ID:#{id} is not found" }, 404)
64
+ error!({ message: "ID:#{id} not found" }, 404)
169
65
  end
170
66
  raise result.failure
171
67
  end
172
68
 
173
- desc "Run a rule", {
174
- success: { code: 201, model: Entities::Message },
175
- failure: [{ code: 404, model: Entities::Message }],
69
+ desc "Search by a rule", {
70
+ success: { code: 201, model: Entities::QueueMessage },
71
+ failure: [{ code: 404, model: Entities::ErrorMessage }],
176
72
  summary: "Run a rule"
177
73
  }
178
74
  params do
179
75
  requires :id, type: String
180
76
  end
181
- get "/:id/run" do
77
+ post "/:id/search" do
182
78
  status 201
183
79
 
184
80
  id = params[:id].to_s
185
- result = RuleRunner.result(id)
186
- return present({ message: "ID:#{id}} has been ran" }, with: Entities::Message) if result.success?
81
+
82
+ queued = true
83
+ result = Dry::Monads::Try[StandardError] do
84
+ rule = Mihari::Rule.from_model(Mihari::Models::Rule.find(id))
85
+
86
+ if Mihari.sidekiq?
87
+ Jobs::SearchJob.perform_async(rule.id)
88
+ else
89
+ rule.call
90
+ queued = false
91
+ end
92
+ end.to_result
93
+
94
+ message = queued ? "ID:#{id}'s search has been queued" : "ID:#{id}'s search has been succeed"
95
+ return present({ message: message, queued: queued }, with: Entities::QueueMessage) if result.success?
187
96
 
188
97
  case result.failure
189
98
  when ActiveRecord::RecordNotFound
190
- error!({ message: "ID:#{id} is not found" }, 404)
99
+ error!({ message: "ID:#{id} not found" }, 404)
191
100
  end
192
101
  raise result.failure
193
102
  end
194
103
 
195
104
  desc "Create a rule", {
196
105
  success: { code: 201, model: Entities::Rule },
197
- failure: [{ code: 404, model: Entities::Message }],
106
+ failure: [
107
+ { code: 400, model: Entities::ErrorMessage },
108
+ { code: 422, model: Entities::ErrorMessage }
109
+ ],
198
110
  summary: "Create a rule"
199
111
  }
200
112
  params do
@@ -203,22 +115,29 @@ module Mihari
203
115
  post "/" do
204
116
  status 201
205
117
 
206
- result = RuleCreator.result(params[:yaml])
118
+ yaml = params[:yaml].to_s
119
+
120
+ result = RuleCreateUpdater.result(yaml, overwrite: false)
207
121
  return present(result.value!.model, with: Entities::Rule) if result.success?
208
122
 
209
123
  failure = result.failure
210
124
  case failure
211
125
  when Psych::SyntaxError
212
- error!({ message: failure.message }, 400)
126
+ error!({ message: failure.message }, 422)
213
127
  when ValidationError
214
- error!({ message: "Rule format is invalid", details: failure.errors.to_h }, 400)
128
+ error!({ message: "Rule format invalid", detail: failure.errors.to_h }, 422)
129
+ when IntegrityError
130
+ error!({ message: failure.message }, 400)
215
131
  end
216
132
  raise failure
217
133
  end
218
134
 
219
135
  desc "Update a rule", {
220
136
  success: { code: 201, model: Entities::Rule },
221
- failure: [{ code: 404, model: Entities::Message }],
137
+ failure: [
138
+ { code: 404, model: Entities::ErrorMessage },
139
+ { code: 422, model: Entities::ErrorMessage }
140
+ ],
222
141
  summary: "Update a rule"
223
142
  }
224
143
  params do
@@ -229,24 +148,26 @@ module Mihari
229
148
  status 201
230
149
 
231
150
  id = params[:id].to_s
232
- result = RuleUpdater.result(id: id, yaml: params[:yaml].to_s)
151
+ yaml = params[:yaml].to_s
152
+
153
+ result = RuleCreateUpdater.result(yaml, overwrite: true)
233
154
  return present(result.value!.model, with: Entities::Rule) if result.success?
234
155
 
235
156
  failure = result.failure
236
157
  case failure
237
158
  when ActiveRecord::RecordNotFound
238
- error!({ message: "ID:#{id} is not found" }, 404)
159
+ error!({ message: "ID:#{id} not found" }, 404)
239
160
  when Psych::SyntaxError
240
- error!({ message: failure.message }, 400)
161
+ error!({ message: failure.message }, 422)
241
162
  when ValidationError
242
- error!({ message: "Rule format is invalid", details: failure.errors.to_h }, 400)
163
+ error!({ message: "Rule format is invalid", detail: failure.errors.to_h }, 422)
243
164
  end
244
165
  raise failure
245
166
  end
246
167
 
247
168
  desc "Delete a rule", {
248
169
  success: { code: 204, model: Entities::Message },
249
- failure: [{ code: 404, model: Entities::Message }],
170
+ failure: [{ code: 404, model: Entities::ErrorMessage }],
250
171
  summary: "Delete a rule"
251
172
  }
252
173
  params do
@@ -256,12 +177,12 @@ module Mihari
256
177
  status 204
257
178
 
258
179
  id = params[:id].to_s
259
- result = RuleDestroyer.result(id)
180
+ result = Services::RuleDestroyer.result(id)
260
181
  return present({ message: "ID:#{id} is deleted" }, with: Entities::Message) if result.success?
261
182
 
262
183
  case result.failure
263
184
  when ActiveRecord::RecordNotFound
264
- error!({ message: "ID:#{id} is not found" }, 404)
185
+ error!({ message: "ID:#{id} not found" }, 404)
265
186
  end
266
187
  raise result.failure
267
188
  end
@@ -7,29 +7,33 @@ module Mihari
7
7
  # Tag API endpoint
8
8
  #
9
9
  class Tags < Grape::API
10
- class TagDestroyer < Service
11
- #
12
- # @param [Integer] id
13
- #
14
- def call(id)
15
- Mihari::Models::Tag.find(id).destroy
16
- end
17
- end
18
-
19
10
  namespace :tags do
20
- desc "Get tags", {
11
+ desc "List tags", {
21
12
  is_array: true,
22
- success: Entities::Tags,
23
- summary: "Get tags"
13
+ success: Entities::TagsWithPagination,
14
+ summary: "List tags"
24
15
  }
16
+ params do
17
+ optional :q, type: String, default: ""
18
+ optional :page, type: Integer, default: 1
19
+ optional :limit, type: Integer, default: 10
20
+ end
25
21
  get "/" do
26
- tags = Mihari::Models::Tag.distinct.pluck(:name)
27
- present({ tags: tags }, with: Entities::Tags)
22
+ value = Services::TagSearcher.call(params.to_h)
23
+ present(
24
+ {
25
+ results: value.results,
26
+ total: value.total,
27
+ current_page: value.filter[:page].to_i,
28
+ page_size: value.filter[:limit].to_i
29
+ },
30
+ with: Entities::TagsWithPagination
31
+ )
28
32
  end
29
33
 
30
34
  desc "Delete a tag", {
31
35
  success: { code: 204, model: Entities::Message },
32
- failure: [{ code: 404, model: Entities::Message }],
36
+ failure: [{ code: 404, model: Entities::ErrorMessage }],
33
37
  summary: "Delete a tag"
34
38
  }
35
39
  params do
@@ -39,12 +43,12 @@ module Mihari
39
43
  status 204
40
44
 
41
45
  id = params[:id].to_i
42
- result = TagDestroyer.result(id)
46
+ result = Services::TagDestroyer.result(id)
43
47
  return present({ message: "" }, with: Entities::Message) if result.success?
44
48
 
45
49
  case result.failure
46
50
  when ActiveRecord::RecordNotFound
47
- error!({ message: "ID:#{id} is not found" }, 404)
51
+ error!({ message: "ID:#{id} not found" }, 404)
48
52
  end
49
53
  raise result.failure
50
54
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mihari
4
+ module Web
5
+ module Middleware
6
+ #
7
+ # Customized Sentry::Rack::CaptureExceptions
8
+ #
9
+ class CaptureExceptions < Sentry::Rack::CaptureExceptions
10
+ include Concerns::ErrorUnwrappable
11
+
12
+ private
13
+
14
+ def capture_exception(exception, env)
15
+ unwrapped = unwrap_error(exception)
16
+ Mihari.logger.error unwrapped
17
+
18
+ Sentry.capture_exception(unwrapped).tap do |event|
19
+ env[ERROR_EVENT_ID_KEY] = event.event_id if event
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -6,7 +6,9 @@ module Mihari
6
6
  #
7
7
  # DB connection adapter for Rack app
8
8
  #
9
- class ConnectionAdapter
9
+ class Connection
10
+ include Concerns::DatabaseConnectable
11
+
10
12
  attr_reader :app
11
13
 
12
14
  def initialize(app)
@@ -14,7 +16,7 @@ module Mihari
14
16
  end
15
17
 
16
18
  def call(env)
17
- Mihari::Database.with_db_connection { app.call env }
19
+ with_db_connection { app.call env }
18
20
  end
19
21
  end
20
22
  end