trackguard 0.19.0 → 0.20.0

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
  SHA256:
3
- metadata.gz: 90c710c8d2149047c75e5b99151b708e9741e29385d17de7c4f101ad9db697cf
4
- data.tar.gz: 49aaf485a932c241d9c18986120f639305485f4c316653923e9ad9a018566e01
3
+ metadata.gz: 3e13b68029bc80d015c4f69531d17e5b362092d6df2d720dfb7c1563b5b4e24c
4
+ data.tar.gz: e676a88de14a04d1c42c0a78f7e895a7ef5011c7567e93a168e82e8f950bfeb1
5
5
  SHA512:
6
- metadata.gz: b1a17b99009baaacee17c4473bf33b811870df411541cee1c055807f2b8981b4ab09ba0c28eeee15adc0a8ab87081f6b463b494435618cafafb2aea424b95226
7
- data.tar.gz: 8da17d592514268ced0ab53cb0c2331671eea10702deaac46264f90874f2af33e60f952a1c89b7c1f920b6ad35ad93297bfe6ab786c796816c3704d35a17424d
6
+ metadata.gz: d4074d349ac565380d3365ef21ca99e61836601f51fe5822cff34a3184f93cea71dc0ab541b2a08f2f0ccb49fade36c89a97f8681a5609748088ecdb661f6f84
7
+ data.tar.gz: 1783d02fa8caedd5816efce4cca6faab7c305af260549de8ece369c22ff47b279725e9503dc5c3d8cade1f5069516faaee594fd362e16b92939317168f4d7dfc
@@ -0,0 +1,29 @@
1
+ module Trackguard
2
+ module Admin
3
+ module Overridable
4
+ extend ActiveSupport::Concern
5
+
6
+ private
7
+
8
+ def visitor_scope
9
+ Visitor.all
10
+ end
11
+
12
+ def page_view_scope
13
+ PageView.all
14
+ end
15
+
16
+ def after_action_path
17
+ dashboard_path
18
+ end
19
+
20
+ def set_visitor
21
+ @visitor = if params[:ip].present?
22
+ visitor_scope.find_by!(ip: params[:ip])
23
+ else
24
+ visitor_scope.find(params[:id])
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,46 +1,25 @@
1
1
  module Trackguard
2
2
  module Admin
3
3
  class AnalyticsController < BaseController
4
+ include Overridable
5
+
4
6
  skip_before_action :verify_authenticity_token, if: :valid_api_token?
5
7
 
6
- # rubocop:disable Metrics/AbcSize
7
8
  def show
8
- @total_today = PageView.today.count
9
- @total_week = PageView.this_week.count
10
- @total_month = PageView.this_month.count
11
-
12
- base = time_scope
13
- @top_pages = base.group(:path).order("count_all DESC").limit(10).count
14
- @top_referrers = base.with_referrer.group(:referer).order("count_all DESC").limit(10).count
15
- @top_sources = base.with_source.group(:source).order("count_all DESC").limit(10).count
16
-
17
- @recent = visitor_filtered(
18
- time_scope(PageView.order(created_at: :desc).limit(20).includes(visitor: :whitelisted_ip))
9
+ query = AnalyticsQuery.call(
10
+ scope: page_view_scope,
11
+ time_scope: apply_time_scope(page_view_scope),
12
+ limit: 10
19
13
  )
20
14
 
21
15
  render json: {
22
- totals: { today: @total_today, week: @total_week, month: @total_month },
23
- top_pages: @top_pages,
24
- top_referrers: @top_referrers,
25
- top_sources: @top_sources,
26
- recent: @recent.map do |pv|
27
- {
28
- path: pv.path,
29
- ip: pv.visitor&.ip,
30
- flagged_at: pv.visitor.flagged_at,
31
- flagged_by: pv.visitor.flagged_by,
32
- whitelisted: pv.visitor.whitelisted_ip&.active? || false,
33
- user_agent: pv.user_agent,
34
- session_id: pv.session_id,
35
- trace_id: pv.trace_id,
36
- referer: pv.referer,
37
- source: pv.source,
38
- created_at: pv.created_at
39
- }
40
- end
16
+ totals: query.totals,
17
+ top_pages: query.top_pages,
18
+ top_referrers: query.top_referrers,
19
+ top_sources: query.top_sources,
20
+ recent: visitor_filtered(apply_time_scope(query.recent)).map { |view| serialize_page_view(view) }
41
21
  }
42
22
  end
43
- # rubocop:enable Metrics/AbcSize
44
23
 
45
24
  private
46
25
 
@@ -50,7 +29,7 @@ module Trackguard
50
29
  super
51
30
  end
52
31
 
53
- def time_scope(base = PageView.all)
32
+ def apply_time_scope(base)
54
33
  params[:since].present? ? base.where(created_at: parsed_since..) : base.last_30
55
34
  end
56
35
 
@@ -64,8 +43,8 @@ module Trackguard
64
43
 
65
44
  def visitor_filtered(scope)
66
45
  if params.key?(:flagged)
67
- visitor_scope = cast_bool(params[:flagged]) ? Visitor.flagged : Visitor.unflagged
68
- scope = scope.joins(:visitor).merge(visitor_scope)
46
+ flagged_scope = cast_bool(params[:flagged]) ? Visitor.flagged : Visitor.unflagged
47
+ scope = scope.joins(:visitor).merge(flagged_scope)
69
48
  end
70
49
  if params.key?(:whitelisted)
71
50
  scope = if cast_bool(params[:whitelisted])
@@ -80,6 +59,22 @@ module Trackguard
80
59
  def cast_bool(val)
81
60
  ActiveRecord::Type::Boolean.new.cast(val)
82
61
  end
62
+
63
+ def serialize_page_view(view)
64
+ {
65
+ path: view.path,
66
+ ip: view.visitor&.ip,
67
+ flagged_at: view.visitor.flagged_at,
68
+ flagged_by: view.visitor.flagged_by,
69
+ whitelisted: view.visitor.whitelisted_ip&.active? || false,
70
+ user_agent: view.user_agent,
71
+ session_id: view.session_id,
72
+ trace_id: view.trace_id,
73
+ referer: view.referer,
74
+ source: view.source,
75
+ created_at: view.created_at
76
+ }
77
+ end
83
78
  end
84
79
  end
85
80
  end
@@ -12,7 +12,7 @@ module Trackguard
12
12
  Rails.cache.delete(BlockedUserAgent::CACHE_KEY)
13
13
  render json: { status: "ok", pattern: record.pattern }
14
14
  rescue ActionController::ParameterMissing, ActiveRecord::RecordInvalid => e
15
- render json: { status: "error", message: e.message }, status: :unprocessable_entity
15
+ render json: { status: "error", message: e.message }, status: :unprocessable_content
16
16
  end
17
17
 
18
18
  private
@@ -1,16 +1,22 @@
1
1
  module Trackguard
2
2
  module Admin
3
3
  class DashboardsController < BaseController
4
- def show
5
- @total_today = PageView.today.count
6
- @total_week = PageView.this_week.count
7
- @total_month = PageView.this_month.count
4
+ include Overridable
8
5
 
9
- @top_pages = PageView.last_30.group(:path).order("count_all DESC").limit(5).count
10
- @top_referrers = PageView.last_30.with_referrer.group(:referer).order("count_all DESC").limit(5).count
11
- @top_sources = PageView.last_30.with_source.group(:source).order("count_all DESC").limit(5).count
6
+ def show
7
+ query = AnalyticsQuery.call(
8
+ scope: page_view_scope,
9
+ time_scope: page_view_scope.last_30,
10
+ limit: 5
11
+ )
12
12
 
13
- @recent = PageView.order(created_at: :desc).limit(20).includes(visitor: :whitelisted_ip)
13
+ @total_today = query.totals[:today]
14
+ @total_week = query.totals[:week]
15
+ @total_month = query.totals[:month]
16
+ @top_pages = query.top_pages
17
+ @top_referrers = query.top_referrers
18
+ @top_sources = query.top_sources
19
+ @recent = query.recent
14
20
  end
15
21
  end
16
22
  end
@@ -1,12 +1,14 @@
1
1
  module Trackguard
2
2
  module Admin
3
3
  class VisitorsController < BaseController
4
+ include Overridable
5
+
4
6
  skip_before_action :verify_authenticity_token, if: :valid_api_token?
5
7
  before_action :set_visitor
6
8
 
7
9
  rescue_from ActiveRecord::RecordNotFound do
8
10
  respond_to do |format|
9
- format.html { redirect_to dashboard_path, alert: "Visitor not found." }
11
+ format.html { redirect_to after_action_path, alert: "Visitor not found." }
10
12
  format.json { render json: { error: "Visitor not found" }, status: :not_found }
11
13
  end
12
14
  end
@@ -20,13 +22,13 @@ module Trackguard
20
22
  name: params[:name].presence || BlockedUserAgent.matching_pattern(@visitor.user_agent)
21
23
  )
22
24
  respond_to do |format|
23
- format.html { redirect_back_or_to dashboard_path }
25
+ format.html { redirect_back_or_to after_action_path }
24
26
  format.json { render json: { status: "ok", ip: @visitor.ip, flagged_at: @visitor.flagged_at } }
25
27
  end
26
28
  else
27
29
  respond_to do |format|
28
- format.html { redirect_back_or_to dashboard_path, alert: @visitor.errors.full_messages.join(", ") }
29
- format.json { render json: { errors: @visitor.errors.full_messages }, status: :unprocessable_entity }
30
+ format.html { redirect_back_or_to after_action_path, alert: @visitor.errors.full_messages.join(", ") }
31
+ format.json { render json: { errors: @visitor.errors.full_messages }, status: :unprocessable_content }
30
32
  end
31
33
  end
32
34
  end
@@ -35,7 +37,7 @@ module Trackguard
35
37
  def unflag
36
38
  @visitor.update!(flagged_at: nil, flag_reason: nil, flagged_by: nil)
37
39
  respond_to do |format|
38
- format.html { redirect_back_or_to dashboard_path }
40
+ format.html { redirect_back_or_to after_action_path }
39
41
  format.json { render json: { status: "ok", ip: @visitor.ip } }
40
42
  end
41
43
  end
@@ -47,14 +49,6 @@ module Trackguard
47
49
 
48
50
  super
49
51
  end
50
-
51
- def set_visitor
52
- @visitor = if params[:ip].present?
53
- Visitor.find_by!(ip: params[:ip])
54
- else
55
- Visitor.find(params[:id])
56
- end
57
- end
58
52
  end
59
53
  end
60
54
  end
@@ -1,16 +1,18 @@
1
1
  module Trackguard
2
2
  module Admin
3
3
  class VisitsController < BaseController
4
+ include Overridable
5
+
4
6
  PER_PAGE = 20
5
7
 
6
8
  def index
7
9
  @page = [ (params[:page] || 1).to_i, 1 ].max
8
- @total = PageView.count
10
+ @total = page_view_scope.count
9
11
  @pages = (@total.to_f / PER_PAGE).ceil
10
- @visits = PageView.order(created_at: :desc)
11
- .limit(PER_PAGE)
12
- .offset((@page - 1) * PER_PAGE)
13
- .includes(visitor: :whitelisted_ip)
12
+ @visits = page_view_scope.order(created_at: :desc)
13
+ .limit(PER_PAGE)
14
+ .offset((@page - 1) * PER_PAGE)
15
+ .includes(visitor: :whitelisted_ip)
14
16
  end
15
17
  end
16
18
  end
@@ -1,12 +1,14 @@
1
1
  module Trackguard
2
2
  module Admin
3
3
  class WhitelistedIpsController < BaseController
4
+ include Overridable
5
+
4
6
  skip_before_action :verify_authenticity_token, if: :valid_api_token?
5
7
  before_action :set_visitor
6
8
 
7
9
  rescue_from ActiveRecord::RecordNotFound do
8
10
  respond_to do |format|
9
- format.html { redirect_to dashboard_path, alert: "Visitor not found." }
11
+ format.html { redirect_to after_action_path, alert: "Visitor not found." }
10
12
  format.json { render json: { error: "Visitor not found" }, status: :not_found }
11
13
  end
12
14
  end
@@ -17,13 +19,13 @@ module Trackguard
17
19
  record.expires_at = params[:expires_at].presence || 7.days.from_now
18
20
  record.save!
19
21
  respond_to do |format|
20
- format.html { redirect_back_or_to dashboard_path }
22
+ format.html { redirect_back_or_to after_action_path }
21
23
  format.json { render json: { status: "ok", ip: @visitor.ip, expires_at: record.expires_at } }
22
24
  end
23
25
  rescue ActiveRecord::RecordInvalid => e
24
26
  respond_to do |format|
25
- format.html { redirect_back_or_to dashboard_path, alert: e.message }
26
- format.json { render json: { status: "error", message: e.message }, status: :unprocessable_entity }
27
+ format.html { redirect_back_or_to after_action_path, alert: e.message }
28
+ format.json { render json: { status: "error", message: e.message }, status: :unprocessable_content }
27
29
  end
28
30
  end
29
31
 
@@ -33,12 +35,12 @@ module Trackguard
33
35
  if record
34
36
  record.destroy!
35
37
  respond_to do |format|
36
- format.html { redirect_back_or_to dashboard_path }
38
+ format.html { redirect_back_or_to after_action_path }
37
39
  format.json { render json: { status: "ok", ip: @visitor.ip } }
38
40
  end
39
41
  else
40
42
  respond_to do |format|
41
- format.html { redirect_back_or_to dashboard_path, alert: "No whitelist entry found." }
43
+ format.html { redirect_back_or_to after_action_path, alert: "No whitelist entry found." }
42
44
  format.json { render json: { error: "Not whitelisted" }, status: :not_found }
43
45
  end
44
46
  end
@@ -51,14 +53,6 @@ module Trackguard
51
53
 
52
54
  super
53
55
  end
54
-
55
- def set_visitor
56
- @visitor = if params[:ip].present?
57
- Visitor.find_by!(ip: params[:ip])
58
- else
59
- Visitor.find(params[:id])
60
- end
61
- end
62
56
  end
63
57
  end
64
58
  end
@@ -0,0 +1,27 @@
1
+ module Trackguard
2
+ class AnalyticsQuery < ApplicationService
3
+ attr_reader :totals, :top_pages, :top_referrers, :top_sources, :recent
4
+
5
+ def initialize(scope:, time_scope:, limit:)
6
+ @scope = scope
7
+ @time_scope = time_scope
8
+ @limit = limit
9
+ end
10
+
11
+ def call
12
+ @totals = {
13
+ today: @scope.today.count,
14
+ week: @scope.this_week.count,
15
+ month: @scope.this_month.count
16
+ }
17
+
18
+ @top_pages = @time_scope.group(:path).order("count_all DESC").limit(@limit).count
19
+ @top_referrers = @time_scope.with_referrer.group(:referer).order("count_all DESC").limit(@limit).count
20
+ @top_sources = @time_scope.with_source.group(:source).order("count_all DESC").limit(@limit).count
21
+
22
+ @recent = @scope.order(created_at: :desc).limit(20).includes(visitor: :whitelisted_ip)
23
+
24
+ self
25
+ end
26
+ end
27
+ end
@@ -2,6 +2,7 @@ class CreateTrackguardTables < ActiveRecord::Migration[<%= ActiveRecord::Migrati
2
2
  def change
3
3
  create_table :trackguard_visitors do |t|
4
4
  t.string :ip
5
+ t.string :name
5
6
  t.string :user_agent
6
7
  t.datetime :first_seen_at, null: false
7
8
  t.datetime :last_seen_at, null: false
@@ -1,3 +1,3 @@
1
1
  module Trackguard
2
- VERSION = "0.19.0".freeze
2
+ VERSION = "0.20.0".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trackguard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.0
4
+ version: 0.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Krzysztof Rygielski
@@ -46,6 +46,7 @@ files:
46
46
  - app/assets/images/trackguard/logo.png
47
47
  - app/assets/javascripts/controllers/page_tracker_controller.js
48
48
  - app/assets/stylesheets/trackguard/admin.css
49
+ - app/controllers/concerns/trackguard/admin/overridable.rb
49
50
  - app/controllers/concerns/trackguard/page_tracker.rb
50
51
  - app/controllers/trackguard/admin/analytics_controller.rb
51
52
  - app/controllers/trackguard/admin/base_controller.rb
@@ -65,6 +66,7 @@ files:
65
66
  - app/models/trackguard/visit.rb
66
67
  - app/models/trackguard/visitor.rb
67
68
  - app/models/trackguard/whitelisted_ip.rb
69
+ - app/services/trackguard/analytics_query.rb
68
70
  - app/services/trackguard/application_service.rb
69
71
  - app/services/trackguard/page_view_recorder.rb
70
72
  - app/views/layouts/trackguard/admin.html.erb