snitch_reporting 1.2.3 → 1.2.8
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 +4 -4
- data/app/assets/javascripts/snitch_reporting/search_bar.js +14 -8
- data/app/assets/javascripts/snitch_reporting/snitch_report.js +5 -1
- data/app/controllers/snitch_reporting/snitch_reports_controller.rb +158 -235
- data/app/helpers/snitch_reporting/snitch_report_helper.rb +11 -0
- data/app/models/snitch_reporting/service/filter_string_builder.rb +160 -0
- data/app/models/snitch_reporting/snitch_report.rb +3 -3
- data/app/views/snitch_reporting/snitch_reports/index.html.erb +0 -1
- data/lib/snitch_reporting/rack.rb +1 -2
- data/lib/snitch_reporting/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ca3d8591d21ac20134ebd44f75d3ec482cebbe2eefd5a1429d78669ebb535cd5
|
|
4
|
+
data.tar.gz: 370bfe6cb40196f331f24aa6dbd67a2b0455d9fc3e03a51501c84e337097f5a3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7489b6381958b0b219ec1263fdef97a7f65fd3fc97a6479f1a8d29ee1053d6f8368720fb74979e96a94f516d4b9f46f9344063e07f8bb3ae88a6edf683485812
|
|
7
|
+
data.tar.gz: 45aaacad3ea9e6f65eaf0b9d1e997b092416f9b13e472cdeb989db87f6f1e111a2aae056e8f419e669371f9c8eeaf05c9ea767e2a722a88577b2c6fbd29eeaba
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
document.addEventListener("DOMContentLoaded",
|
|
2
|
-
document.querySelector("[name=filter_string]").addEventListener("focus", function(event) {
|
|
3
|
-
document.querySelector(".filters").classList.add("open")
|
|
4
|
-
})
|
|
5
|
-
|
|
6
|
-
setNewFilters(document.querySelector("[name=filter_string]").value)
|
|
7
|
-
});
|
|
1
|
+
document.addEventListener("DOMContentLoaded", setupFilters)
|
|
8
2
|
|
|
9
3
|
document.addEventListener("click", function(event) {
|
|
10
4
|
if (event.target.matches(".filters") || event.target.matches("[name=filter_string]")) {
|
|
@@ -16,9 +10,21 @@ document.addEventListener("click", function(event) {
|
|
|
16
10
|
return applyFilter(event.target)
|
|
17
11
|
}
|
|
18
12
|
|
|
19
|
-
document.querySelector(".filters")
|
|
13
|
+
if (document.querySelector(".filters")) {
|
|
14
|
+
document.querySelector(".filters").classList.remove("open")
|
|
15
|
+
}
|
|
20
16
|
})
|
|
21
17
|
|
|
18
|
+
function setupFilters() {
|
|
19
|
+
if (document.querySelector("[name=filter_string]")) {
|
|
20
|
+
document.querySelector("[name=filter_string]").addEventListener("focus", function(event) {
|
|
21
|
+
document.querySelector(".filters").classList.add("open")
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
setNewFilters(document.querySelector("[name=filter_string]").value)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
function applyFilter(selected_cell) {
|
|
23
29
|
var filter_field = document.querySelector("[name=filter_string]")
|
|
24
30
|
var filter_string = filter_field.value
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
//= require_tree .
|
|
2
2
|
|
|
3
3
|
document.addEventListener("change", function(evt) {
|
|
4
|
+
remoteCheckbox(evt)
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
function remoteCheckbox(evt) {
|
|
4
8
|
if (evt.target && evt.target.hasAttribute("data-mark-resolution-url")) {
|
|
5
9
|
var report_url = evt.target.getAttribute("data-mark-resolution-url")
|
|
6
10
|
var data = JSON.stringify({
|
|
@@ -19,7 +23,7 @@ document.addEventListener("change", function(evt) {
|
|
|
19
23
|
body: data
|
|
20
24
|
})
|
|
21
25
|
}
|
|
22
|
-
}
|
|
26
|
+
}
|
|
23
27
|
|
|
24
28
|
// Must include Jquery
|
|
25
29
|
// Or rewrite to use pure JS
|
|
@@ -2,246 +2,169 @@ require_dependency "snitch_reporting/application_controller"
|
|
|
2
2
|
|
|
3
3
|
class ::SnitchReporting::SnitchReportsController < ApplicationController
|
|
4
4
|
include ::SnitchReporting::ParamsHelper
|
|
5
|
+
include ::SnitchReporting::SnitchReportHelper
|
|
5
6
|
helper ::SnitchReporting::SnitchReportHelper
|
|
6
7
|
|
|
7
8
|
layout "application"
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
#
|
|
50
|
-
# def comment
|
|
51
|
-
# if @report.comments.create(comment_params.merge(author: current_credential).merge(params.permit(:resolved, :ignored)))
|
|
52
|
-
# update_report_for(:resolved, comment: false)
|
|
53
|
-
# update_report_for(:ignored, comment: false)
|
|
54
|
-
#
|
|
55
|
-
# redirect_to snitch_report_path(@report)
|
|
56
|
-
# else
|
|
57
|
-
# redirect_to snitch_report_path(@report), alert: "Failed to comment. Please try again."
|
|
58
|
-
# end
|
|
59
|
-
# end
|
|
60
|
-
#
|
|
61
|
-
private
|
|
62
|
-
|
|
63
|
-
def report_params
|
|
64
|
-
params.require(:snitch_report).permit(
|
|
65
|
-
:ignored,
|
|
66
|
-
:resolved
|
|
67
|
-
)
|
|
68
|
-
end
|
|
69
|
-
#
|
|
70
|
-
# def current_snitch_report
|
|
71
|
-
# @report = SnitchReporting::SnitchReport.find(params[:id])
|
|
72
|
-
# end
|
|
73
|
-
#
|
|
74
|
-
# def update_report_for(status, comment: true)
|
|
75
|
-
# raise "Value not allowed: #{status}" unless status.in?([:resolved, :ignored])
|
|
76
|
-
#
|
|
77
|
-
# if true_param?(status)
|
|
78
|
-
# @report.update("#{status}_at": Time.current, "#{status}_by": current_credential)
|
|
79
|
-
# # @report.comments.create(author: current_credential, message: ">>> Marked as #{status} <<<", skip_notify: true, status => true) if comment
|
|
80
|
-
# elsif params[status].present?
|
|
81
|
-
# # @report.comments.create(author: current_credential, message: ">>> Marked as un#{status} <<<", skip_notify: true, status => false) if comment
|
|
82
|
-
# @report.update("#{status}_at": nil, "#{status}_by": nil)
|
|
83
|
-
# end
|
|
84
|
-
# end
|
|
85
|
-
#
|
|
86
|
-
# def report_params
|
|
87
|
-
# params.require(:snitch_report).permit(
|
|
88
|
-
# :source,
|
|
89
|
-
# :severity,
|
|
90
|
-
# :assigned_to_id,
|
|
91
|
-
# :title,
|
|
92
|
-
# :custom_details
|
|
93
|
-
# )
|
|
94
|
-
# end
|
|
95
|
-
#
|
|
96
|
-
# def comment_params
|
|
97
|
-
# params.require(:snitch_comment).permit(:message)
|
|
98
|
-
# end
|
|
99
|
-
#
|
|
100
|
-
# def set_report_preferences
|
|
101
|
-
# @filters = begin
|
|
102
|
-
# preferences = JSON.parse(session[:filters].presence || "{}").symbolize_keys
|
|
103
|
-
#
|
|
104
|
-
# available_preferences = [:level_tags, :severity_tags, :source_tags, :resolved, :ignored]
|
|
105
|
-
# available_preferences.each do |pref_key|
|
|
106
|
-
# pref_val = params[pref_key]
|
|
107
|
-
# preferences[pref_key] = pref_val if pref_val.present?
|
|
108
|
-
# preferences.delete(pref_key) if pref_val == "all"
|
|
109
|
-
# end
|
|
110
|
-
#
|
|
111
|
-
# session[:filters] = preferences.to_json
|
|
112
|
-
# preferences
|
|
113
|
-
# end
|
|
114
|
-
# end
|
|
115
|
-
def set_filters
|
|
116
|
-
@filter_sets = {
|
|
117
|
-
status: {
|
|
118
|
-
default: :unresolved,
|
|
119
|
-
values: [:all, :resolved, :unresolved]
|
|
120
|
-
},
|
|
121
|
-
# assignee: {
|
|
122
|
-
# default: :any,
|
|
123
|
-
# values: [:any, :me, :not_me, :not_assigned]
|
|
124
|
-
# },
|
|
125
|
-
log_level: {
|
|
126
|
-
default: :any,
|
|
127
|
-
values: [:any] + ::SnitchReporting::SnitchReport.log_levels.keys.map(&:to_sym)
|
|
128
|
-
},
|
|
129
|
-
# ignored: {
|
|
130
|
-
# default: :not_ignored,
|
|
131
|
-
# values: [:all, :ignored, :not_ignored]
|
|
132
|
-
# }
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
set_filter_string
|
|
136
|
-
|
|
137
|
-
# @filters = @filter_sets.each_with_object({set_filters: {}}) do |(filter_name, filter_set), filters|
|
|
138
|
-
# filters[filter_name] = filter_set[:default]
|
|
139
|
-
# filter_in_param = params[filter_name].try(:to_sym)
|
|
140
|
-
# next unless filter_in_param && filter_set[:values].include?(filter_in_param)
|
|
141
|
-
# filters[filter_name] = filter_in_param
|
|
142
|
-
# filters[:set_filters][filter_name] = filter_in_param
|
|
143
|
-
# end
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def filter_reports
|
|
147
|
-
set_filters
|
|
148
|
-
|
|
149
|
-
@reports = @reports.resolved if @filters[:status] == :resolved
|
|
150
|
-
@reports = @reports.unresolved if @filters[:status] == :unresolved
|
|
151
|
-
@reports = @reports.search(@filters[:search]) if @filters[:search].present?
|
|
152
|
-
@reports = @reports.by_level(@filters[:log_level]) if @filters[:log_level].present?
|
|
153
|
-
|
|
154
|
-
@reports = @reports.by_tag(*@filters[:tag]) if @filters[:tag].any?
|
|
155
|
-
# @reports = @reports.by_severity(@filters[:severity_tags]) if @filters[:severity_tags].present?
|
|
156
|
-
# @reports = @reports.by_source(@filters[:source_tags]) if @filters[:source_tags].present?
|
|
157
|
-
#
|
|
158
|
-
# @reports = @filters[:resolved].present? && truthy?(@filters[:resolved]) ? @reports.resolved : @reports.unresolved
|
|
159
|
-
# @reports = @filters[:ignored].present? && truthy?(@filters[:ignored]) ? @reports.ignored : @reports.unignored
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def encode_string(token, str)
|
|
163
|
-
@interpolated_strings ||= []
|
|
164
|
-
|
|
165
|
-
@interpolated_strings << str
|
|
166
|
-
"#{token}(#{@interpolated_strings.length})"
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
def decode_string(token, encoded_str)
|
|
170
|
-
@interpolated_strings ||= []
|
|
171
|
-
|
|
172
|
-
encoded_str.gsub(/(\w+)\((\d+)\)/) do |found|
|
|
173
|
-
token = Regexp.last_match(1)
|
|
174
|
-
idx = Regexp.last_match(2)
|
|
175
|
-
|
|
176
|
-
if idx.to_i.to_s == idx
|
|
177
|
-
@interpolated_strings[idx.to_i - 1]
|
|
178
|
-
else
|
|
179
|
-
found
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
def param_safe_value(str)
|
|
185
|
-
return str unless str.include?(" ")
|
|
186
|
-
|
|
187
|
-
"\"#{str}\""
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
def set_filter_string
|
|
191
|
-
@filter_string = params[:filter_string] || session[:snitch_filter_string] || "status:unresolved"
|
|
192
|
-
@unknown_strings = []
|
|
193
|
-
@filters = {}
|
|
194
|
-
|
|
195
|
-
secret_key = loop do
|
|
196
|
-
token = SecureRandom.hex(10)
|
|
197
|
-
break token unless @filter_string.include?(token)
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
temp_filter_string = @filter_string.gsub(/\"(.*?)\"/) do |found|
|
|
201
|
-
encode_string(secret_key, Regexp.last_match(1))
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
search_strings = []
|
|
205
|
-
tag_strings = []
|
|
206
|
-
filter_strings = temp_filter_string.split(" ").select do |filter_string|
|
|
207
|
-
search_strings << filter_string unless filter_string.include?(":")
|
|
208
|
-
filter_string.include?(":")
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
filter_strings.each do |filter_string|
|
|
212
|
-
filter, value, * = filter_string.split(":")
|
|
213
|
-
if value.blank?
|
|
214
|
-
# Search pure text by itself
|
|
215
|
-
search_strings << value
|
|
216
|
-
elsif @filter_sets.keys.include?(filter.to_s.to_sym)
|
|
217
|
-
value = decode_string(secret_key, value)
|
|
218
|
-
@filters[filter.to_sym] = value.to_sym
|
|
219
|
-
elsif filter == "search"
|
|
220
|
-
search_strings << decode_string(secret_key, value)
|
|
221
|
-
elsif filter == "tag" || filter == "tags"
|
|
222
|
-
tag_strings << decode_string(secret_key, value)
|
|
223
|
-
else
|
|
224
|
-
@unknown_strings << filter_string
|
|
225
|
-
end
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
@filters[:search] = "\"#{search_strings.join(' ')}\"" if search_strings.any?
|
|
229
|
-
@filters[:tag] = tag_strings
|
|
230
|
-
|
|
231
|
-
new_filter_strings = @filters.each_with_object([]) do |(filter_string, filter_value), filter_array|
|
|
232
|
-
next unless filter_value.present?
|
|
233
|
-
if filter_value.is_a?(Array)
|
|
234
|
-
filter_value.each do |filter_value_i|
|
|
235
|
-
filter_array << "#{filter_string}:#{filter_value_i}"
|
|
236
|
-
end
|
|
237
|
-
else
|
|
238
|
-
filter_array << "#{filter_string}:#{filter_value}"
|
|
239
|
-
end
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
@filter_string = new_filter_strings.join(" ")
|
|
243
|
-
session[:snitch_filter_string] = @filter_string.dup
|
|
10
|
+
def index
|
|
11
|
+
::SnitchReporting::SnitchReport.warn("Error", some: :data)
|
|
12
|
+
@reports = ::SnitchReporting::SnitchReport.order("last_occurrence_at DESC NULLS LAST").page(params[:page]).per(params[:per] || 25)
|
|
13
|
+
|
|
14
|
+
# set_report_preferences
|
|
15
|
+
filter_reports
|
|
16
|
+
# sort_reports
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def interpret_search
|
|
20
|
+
redirect_to snitch_reports_path(filter_string: params[:filter_string])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def show
|
|
24
|
+
@report = ::SnitchReporting::SnitchReport.find(params[:id])
|
|
25
|
+
occurrences = @report.occurrences.order(created_at: :asc)
|
|
26
|
+
@occurrence = occurrences.find_by(id: params[:occurrence]) || occurrences.last
|
|
27
|
+
occurrence_ids = occurrences.ids
|
|
28
|
+
occurrence_idx = occurrence_ids.index(@occurrence.id)
|
|
29
|
+
@paged_ids = {
|
|
30
|
+
first: occurrence_idx == 0 ? nil : occurrence_ids.first,
|
|
31
|
+
prev: occurrence_idx == 0 ? nil : occurrence_ids[occurrence_idx - 1],
|
|
32
|
+
next: occurrence_idx == occurrence_ids.length - 1 ? nil : occurrence_ids[occurrence_idx + 1],
|
|
33
|
+
last: occurrence_idx == occurrence_ids.length - 1 ? nil : occurrence_ids.last,
|
|
34
|
+
}
|
|
35
|
+
# @formatted_occurrence_data = occurrences.staggered_occurrence_data
|
|
36
|
+
# @comments = @report.comments.order(created_at: :desc)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def update
|
|
41
|
+
@report = ::SnitchReporting::SnitchReport.find(params[:id])
|
|
42
|
+
# @report.acting_user = current_user
|
|
43
|
+
@report.update(report_params)
|
|
44
|
+
|
|
45
|
+
respond_to do |format|
|
|
46
|
+
format.html { redirect_to @report }
|
|
47
|
+
format.json
|
|
244
48
|
end
|
|
49
|
+
end
|
|
50
|
+
#
|
|
51
|
+
# def comment
|
|
52
|
+
# if @report.comments.create(comment_params.merge(author: current_credential).merge(params.permit(:resolved, :ignored)))
|
|
53
|
+
# update_report_for(:resolved, comment: false)
|
|
54
|
+
# update_report_for(:ignored, comment: false)
|
|
55
|
+
#
|
|
56
|
+
# redirect_to snitch_report_path(@report)
|
|
57
|
+
# else
|
|
58
|
+
# redirect_to snitch_report_path(@report), alert: "Failed to comment. Please try again."
|
|
59
|
+
# end
|
|
60
|
+
# end
|
|
61
|
+
#
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def report_params
|
|
65
|
+
params.require(:snitch_report).permit(
|
|
66
|
+
:ignored,
|
|
67
|
+
:resolved
|
|
68
|
+
)
|
|
69
|
+
end
|
|
70
|
+
#
|
|
71
|
+
# def current_snitch_report
|
|
72
|
+
# @report = SnitchReporting::SnitchReport.find(params[:id])
|
|
73
|
+
# end
|
|
74
|
+
#
|
|
75
|
+
# def update_report_for(status, comment: true)
|
|
76
|
+
# raise "Value not allowed: #{status}" unless status.in?([:resolved, :ignored])
|
|
77
|
+
#
|
|
78
|
+
# if true_param?(status)
|
|
79
|
+
# @report.update("#{status}_at": Time.current, "#{status}_by": current_credential)
|
|
80
|
+
# # @report.comments.create(author: current_credential, message: ">>> Marked as #{status} <<<", skip_notify: true, status => true) if comment
|
|
81
|
+
# elsif params[status].present?
|
|
82
|
+
# # @report.comments.create(author: current_credential, message: ">>> Marked as un#{status} <<<", skip_notify: true, status => false) if comment
|
|
83
|
+
# @report.update("#{status}_at": nil, "#{status}_by": nil)
|
|
84
|
+
# end
|
|
85
|
+
# end
|
|
86
|
+
#
|
|
87
|
+
# def report_params
|
|
88
|
+
# params.require(:snitch_report).permit(
|
|
89
|
+
# :source,
|
|
90
|
+
# :severity,
|
|
91
|
+
# :assigned_to_id,
|
|
92
|
+
# :title,
|
|
93
|
+
# :custom_details
|
|
94
|
+
# )
|
|
95
|
+
# end
|
|
96
|
+
#
|
|
97
|
+
# def comment_params
|
|
98
|
+
# params.require(:snitch_comment).permit(:message)
|
|
99
|
+
# end
|
|
100
|
+
#
|
|
101
|
+
# def set_report_preferences
|
|
102
|
+
# @filters = begin
|
|
103
|
+
# preferences = JSON.parse(session[:filters].presence || "{}").symbolize_keys
|
|
104
|
+
#
|
|
105
|
+
# available_preferences = [:level_tags, :severity_tags, :source_tags, :resolved, :ignored]
|
|
106
|
+
# available_preferences.each do |pref_key|
|
|
107
|
+
# pref_val = params[pref_key]
|
|
108
|
+
# preferences[pref_key] = pref_val if pref_val.present?
|
|
109
|
+
# preferences.delete(pref_key) if pref_val == "all"
|
|
110
|
+
# end
|
|
111
|
+
#
|
|
112
|
+
# session[:filters] = preferences.to_json
|
|
113
|
+
# preferences
|
|
114
|
+
# end
|
|
115
|
+
# end
|
|
116
|
+
def set_filters
|
|
117
|
+
@filter_sets = {
|
|
118
|
+
status: {
|
|
119
|
+
default: :unresolved,
|
|
120
|
+
values: [:all, :resolved, :unresolved]
|
|
121
|
+
},
|
|
122
|
+
# assignee: {
|
|
123
|
+
# default: :any,
|
|
124
|
+
# values: [:any, :me, :not_me, :not_assigned]
|
|
125
|
+
# },
|
|
126
|
+
log_level: {
|
|
127
|
+
default: :any,
|
|
128
|
+
values: [:any] + ::SnitchReporting::SnitchReport.log_levels.keys.map(&:to_sym)
|
|
129
|
+
},
|
|
130
|
+
# ignored: {
|
|
131
|
+
# default: :not_ignored,
|
|
132
|
+
# values: [:all, :ignored, :not_ignored]
|
|
133
|
+
# }
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
filter_string_from_params
|
|
137
|
+
|
|
138
|
+
# @filters = @filter_sets.each_with_object({set_filters: {}}) do |(filter_name, filter_set), filters|
|
|
139
|
+
# filters[filter_name] = filter_set[:default]
|
|
140
|
+
# filter_in_param = params[filter_name].try(:to_sym)
|
|
141
|
+
# next unless filter_in_param && filter_set[:values].include?(filter_in_param)
|
|
142
|
+
# filters[filter_name] = filter_in_param
|
|
143
|
+
# filters[:set_filters][filter_name] = filter_in_param
|
|
144
|
+
# end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def filter_reports
|
|
148
|
+
set_filters
|
|
149
|
+
|
|
150
|
+
@reports = @reports.resolved if @filters[:status] == :resolved
|
|
151
|
+
@reports = @reports.unresolved if @filters[:status] == :unresolved
|
|
152
|
+
@reports = @reports.search(@filters[:search]) if @filters[:search].present?
|
|
153
|
+
@reports = @reports.by_level(@filters[:log_level]) if @filters[:log_level].present? && @filters[:log_level] != :any
|
|
154
|
+
|
|
155
|
+
@reports = @reports.by_tag(*@filters[:tags]) if @filters[:tags].present?
|
|
156
|
+
# @reports = @reports.by_severity(@filters[:severity_tags]) if @filters[:severity_tags].present?
|
|
157
|
+
# @reports = @reports.by_source(@filters[:source_tags]) if @filters[:source_tags].present?
|
|
158
|
+
#
|
|
159
|
+
# @reports = @filters[:resolved].present? && truthy?(@filters[:resolved]) ? @reports.resolved : @reports.unresolved
|
|
160
|
+
# @reports = @filters[:ignored].present? && truthy?(@filters[:ignored]) ? @reports.ignored : @reports.unignored
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def param_safe_value(str)
|
|
164
|
+
return str unless str.include?(" ")
|
|
165
|
+
|
|
166
|
+
"\"#{str}\""
|
|
167
|
+
end
|
|
245
168
|
#
|
|
246
169
|
# def sort_reports
|
|
247
170
|
# order = sort_order || "desc"
|
|
@@ -1,2 +1,13 @@
|
|
|
1
1
|
module ::SnitchReporting::SnitchReportHelper
|
|
2
|
+
def search_path_from_filter_string(new_params={})
|
|
3
|
+
snitch_reports_path(filter_string: filter_string_from_params(new_params))
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def filter_string_from_params(extra_params={})
|
|
7
|
+
@filter_builder = ::SnitchReporting::Service::FilterStringBuilder.new(from_string: params[:filter_string] || session[:snitch_filter_string] || "status:unresolved")
|
|
8
|
+
@filter_string = @filter_builder.to_filter_string
|
|
9
|
+
@filters = @filter_builder.filters
|
|
10
|
+
|
|
11
|
+
session[:snitch_filter_string] = @filter_string.dup
|
|
12
|
+
end
|
|
2
13
|
end
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
class ::SnitchReporting::Service::FilterStringBuilder
|
|
2
|
+
attr_accessor :filter_hash, :filters, :unknown_filters
|
|
3
|
+
|
|
4
|
+
def self.filter_sets
|
|
5
|
+
{
|
|
6
|
+
status: {
|
|
7
|
+
default: :unresolved,
|
|
8
|
+
values: [:all, :resolved, :unresolved]
|
|
9
|
+
},
|
|
10
|
+
# assignee: {
|
|
11
|
+
# default: :any,
|
|
12
|
+
# values: [:any, :me, :not_me, :not_assigned]
|
|
13
|
+
# },
|
|
14
|
+
log_level: {
|
|
15
|
+
default: :any,
|
|
16
|
+
values: [:any] + ::SnitchReporting::SnitchReport.log_levels.keys.map(&:to_sym)
|
|
17
|
+
},
|
|
18
|
+
# ignored: {
|
|
19
|
+
# default: :not_ignored,
|
|
20
|
+
# values: [:all, :ignored, :not_ignored]
|
|
21
|
+
# }
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# extra_params.each do |param_key, param_value|
|
|
26
|
+
# param_key = param_key.to_s
|
|
27
|
+
# param_value = param_value.to_s
|
|
28
|
+
#
|
|
29
|
+
# if param_value.blank?
|
|
30
|
+
# # Search pure text by itself
|
|
31
|
+
# search_strings << param_key
|
|
32
|
+
# elsif @filter_sets.keys.include?(param_key.to_s.to_sym)
|
|
33
|
+
# param_value = decode_string(secret_key, param_value)
|
|
34
|
+
# @filters[param_key.to_sym] = param_value.to_sym
|
|
35
|
+
# elsif param_key == "search"
|
|
36
|
+
# search_strings << decode_string(secret_key, param_value)
|
|
37
|
+
# elsif param_key == "tag" || param_key == "tags"
|
|
38
|
+
# tag_strings << decode_string(secret_key, param_value)
|
|
39
|
+
# else
|
|
40
|
+
# @unknown_strings << "#{param_key}:#{param_value}"
|
|
41
|
+
# end
|
|
42
|
+
# end
|
|
43
|
+
|
|
44
|
+
def filter_sets
|
|
45
|
+
self.class.filter_sets
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def initialize(from_string: nil, from_data: nil)
|
|
49
|
+
parse_filters_from_string(from_string) if from_string.present?
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def to_param
|
|
53
|
+
{ filter_string: to_filter_string }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def to_filter_string
|
|
57
|
+
filter_strings = []
|
|
58
|
+
tag_strings = []
|
|
59
|
+
search_strings = []
|
|
60
|
+
|
|
61
|
+
@filters.each do |filter_key, filter_value|
|
|
62
|
+
if filter_key == :search
|
|
63
|
+
search_strings += filter_value
|
|
64
|
+
elsif filter_key == :tags
|
|
65
|
+
tag_strings += filter_value.map { |value| filter_to_string(filter_key, filter_value) }
|
|
66
|
+
elsif filter_sets.keys.include?(filter_key.to_s.to_sym)
|
|
67
|
+
filter_strings << filter_to_string(filter_key, filter_value)
|
|
68
|
+
else
|
|
69
|
+
# No-op for now. Probably should display these somewhere?
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
(filter_strings + tag_strings + search_strings).join(" ")
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def add_filter(filter_key, filter_value)
|
|
77
|
+
filter_key = filter_key.to_s.to_sym
|
|
78
|
+
@filters ||= {search: [], tags: [], unknown: []}
|
|
79
|
+
|
|
80
|
+
if filter_value.blank?
|
|
81
|
+
@filters[:search] << filter_key
|
|
82
|
+
elsif filter_key == :search
|
|
83
|
+
@filters[:search] << filter_key
|
|
84
|
+
elsif filter_key == :tags
|
|
85
|
+
@filters[:tags] << {filter_key => filter_value}
|
|
86
|
+
else
|
|
87
|
+
@filters[filter_key] = filter_value.to_s.to_sym
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
def encode_string(str)
|
|
94
|
+
@encoded_strings ||= []
|
|
95
|
+
|
|
96
|
+
@encoded_strings << str
|
|
97
|
+
"#{@parse_token}(#{@encoded_strings.length - 1})"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def decode_string(encoded_str)
|
|
101
|
+
@encoded_strings ||= []
|
|
102
|
+
|
|
103
|
+
encoded_str.gsub(/#{Regexp.escape(@parse_token)}\((\d+)\)/) do |found|
|
|
104
|
+
encoded_idx = Regexp.last_match(1)
|
|
105
|
+
|
|
106
|
+
if encoded_idx.to_i.to_s == encoded_idx
|
|
107
|
+
@encoded_strings[encoded_idx.to_i]
|
|
108
|
+
else
|
|
109
|
+
found
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def parse_filters_from_string(filter_string)
|
|
115
|
+
@parse_token = generate_uniq_key(filter_string)
|
|
116
|
+
encoded_string = extract_quoted_strings(filter_string)
|
|
117
|
+
parsed_strings = group_values_without_filter(encoded_string)
|
|
118
|
+
|
|
119
|
+
parsed_strings[:filters].each do |parsed_string|
|
|
120
|
+
filter, value, * = parsed_string.split(":")
|
|
121
|
+
|
|
122
|
+
add_filter(filter, decode_string(value))
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def group_values_without_filter(encoded_string)
|
|
127
|
+
filter_group_hash = {
|
|
128
|
+
filters: [],
|
|
129
|
+
search: [],
|
|
130
|
+
tags: [],
|
|
131
|
+
unknown: []
|
|
132
|
+
}
|
|
133
|
+
encoded_string.split(" ").each_with_object(filter_group_hash) do |filter, filter_groups|
|
|
134
|
+
if filter.include?(":")
|
|
135
|
+
filter_groups[:filters] << filter
|
|
136
|
+
else
|
|
137
|
+
filter_groups[:search] << filter
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def filter_to_string(filter, value)
|
|
143
|
+
filter = "\"#{filter}\"" if filter.to_s.include?(" ")
|
|
144
|
+
value = "\"#{value}\"" if value.to_s.include?(" ")
|
|
145
|
+
[filter.presence, value.presence].compact.join(":")
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def extract_quoted_strings(filter_string)
|
|
149
|
+
filter_string.gsub(/\"(.*?)\"/) do |found|
|
|
150
|
+
encode_string(secret_key, Regexp.last_match(1))
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def generate_uniq_key(filter_string)
|
|
155
|
+
loop do
|
|
156
|
+
token = SecureRandom.hex(10)
|
|
157
|
+
break token unless filter_string.to_s.include?(token)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
@@ -86,9 +86,9 @@ class SnitchReporting::SnitchReport < ApplicationRecord
|
|
|
86
86
|
return SnitchReporting::SnitchReport.error("Failed to save occurrence.", occurrence.errors.full_messages) unless occurrence.persisted?
|
|
87
87
|
occurrence
|
|
88
88
|
rescue StandardError => ex
|
|
89
|
-
env ||= {}
|
|
90
|
-
|
|
91
|
-
SnitchReporting::SnitchReport.fatal("Failed to create report. (#{ex.class})"
|
|
89
|
+
# env ||= {}
|
|
90
|
+
# SnitchReporting::SnitchReport.fatal("Failed to create report. (#{ex.class})", env.to_s, ex.to_s)
|
|
91
|
+
SnitchReporting::SnitchReport.fatal("Failed to create report. (#{ex.class})")
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
def format_args(args)
|
|
@@ -17,8 +17,7 @@ class SnitchReporting::Rack
|
|
|
17
17
|
_, headers, = response
|
|
18
18
|
|
|
19
19
|
# if headers["X-Cascade"] == "pass"
|
|
20
|
-
# msg = "This exception means that the preceding Rack middleware set the 'X-Cascade' header to 'pass' -- in "
|
|
21
|
-
# "Rails, this often means that the route was not found (404 error)."
|
|
20
|
+
# msg = "This exception means that the preceding Rack middleware set the 'X-Cascade' header to 'pass' -- in Rails, this often means that the route was not found (404 error)."
|
|
22
21
|
# raise SnitchException, msg
|
|
23
22
|
# end
|
|
24
23
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: snitch_reporting
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rocco Nicholls
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-
|
|
11
|
+
date: 2020-08-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -92,6 +92,7 @@ files:
|
|
|
92
92
|
- app/controllers/snitch_reporting/snitch_reports_controller.rb
|
|
93
93
|
- app/helpers/snitch_reporting/params_helper.rb
|
|
94
94
|
- app/helpers/snitch_reporting/snitch_report_helper.rb
|
|
95
|
+
- app/models/snitch_reporting/service/filter_string_builder.rb
|
|
95
96
|
- app/models/snitch_reporting/service/json_wrapper.rb
|
|
96
97
|
- app/models/snitch_reporting/snitch_comment.rb
|
|
97
98
|
- app/models/snitch_reporting/snitch_history.rb
|
|
@@ -131,8 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
131
132
|
- !ruby/object:Gem::Version
|
|
132
133
|
version: '0'
|
|
133
134
|
requirements: []
|
|
134
|
-
|
|
135
|
-
rubygems_version: 2.7.3
|
|
135
|
+
rubygems_version: 3.1.2
|
|
136
136
|
signing_key:
|
|
137
137
|
specification_version: 4
|
|
138
138
|
summary: Adds a localized error reporting/tracking system.
|