active_endpoint 0.2.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.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +55 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +60 -0
  5. data/.travis.yml +5 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +25 -0
  8. data/Gemfile.lock +140 -0
  9. data/LICENSE +21 -0
  10. data/README.md +233 -0
  11. data/Rakefile +6 -0
  12. data/active_endpoint.gemspec +28 -0
  13. data/app/assets/config/active_endpoint_manifest.js +2 -0
  14. data/app/assets/javascripts/active_endpoint/application.js +2 -0
  15. data/app/assets/stylesheets/active_endpoint/application.css +10 -0
  16. data/app/controllers/active_endpoint/application_controller.rb +5 -0
  17. data/app/controllers/active_endpoint/dashboard_controller.rb +7 -0
  18. data/app/controllers/active_endpoint/probes_controller.rb +22 -0
  19. data/app/controllers/active_endpoint/unregistred_probes_controller.rb +14 -0
  20. data/app/helpers/active_endpoint/application_helper.rb +105 -0
  21. data/app/models/active_endpoint/application_record.rb +5 -0
  22. data/app/models/active_endpoint/probe.rb +52 -0
  23. data/app/models/active_endpoint/unregistred_probe.rb +3 -0
  24. data/app/views/active_endpoint/application/_flashes.html.erb +5 -0
  25. data/app/views/active_endpoint/application/_header.html.erb +18 -0
  26. data/app/views/active_endpoint/dashboard/_blacklist.html.erb +57 -0
  27. data/app/views/active_endpoint/dashboard/_constraints.html.erb +117 -0
  28. data/app/views/active_endpoint/dashboard/_settings.html.erb +13 -0
  29. data/app/views/active_endpoint/dashboard/_tags.html.erb +20 -0
  30. data/app/views/active_endpoint/dashboard/index.html.erb +8 -0
  31. data/app/views/active_endpoint/probes/index.html.erb +28 -0
  32. data/app/views/active_endpoint/probes/show.html.erb +43 -0
  33. data/app/views/active_endpoint/probes/show_response.html.erb +9 -0
  34. data/app/views/active_endpoint/unregistred_probes/index.html.erb +28 -0
  35. data/app/views/layouts/active_endpoint/application.html.erb +39 -0
  36. data/bin/console +14 -0
  37. data/bin/rails +13 -0
  38. data/bin/setup +8 -0
  39. data/config/routes.rb +8 -0
  40. data/lib/active_endpoint.rb +60 -0
  41. data/lib/active_endpoint/concerns/configurable.rb +29 -0
  42. data/lib/active_endpoint/concerns/constraintable.rb +51 -0
  43. data/lib/active_endpoint/concerns/optionable.rb +41 -0
  44. data/lib/active_endpoint/concerns/rails_routable.rb +49 -0
  45. data/lib/active_endpoint/engine.rb +15 -0
  46. data/lib/active_endpoint/extentions/active_record.rb +30 -0
  47. data/lib/active_endpoint/logger.rb +28 -0
  48. data/lib/active_endpoint/proxy.rb +64 -0
  49. data/lib/active_endpoint/rails/middleware.rb +17 -0
  50. data/lib/active_endpoint/rails/railtie.rb +13 -0
  51. data/lib/active_endpoint/request.rb +79 -0
  52. data/lib/active_endpoint/response.rb +17 -0
  53. data/lib/active_endpoint/routes/blacklist.rb +67 -0
  54. data/lib/active_endpoint/routes/cache/proxy.rb +22 -0
  55. data/lib/active_endpoint/routes/cache/proxy/redis_store_proxy.rb +41 -0
  56. data/lib/active_endpoint/routes/cache/store.rb +73 -0
  57. data/lib/active_endpoint/routes/constraint_rule.rb +38 -0
  58. data/lib/active_endpoint/routes/constraints.rb +81 -0
  59. data/lib/active_endpoint/routes/matcher.rb +51 -0
  60. data/lib/active_endpoint/routes/momento.rb +81 -0
  61. data/lib/active_endpoint/storage.rb +112 -0
  62. data/lib/active_endpoint/tags.rb +15 -0
  63. data/lib/active_endpoint/version.rb +3 -0
  64. data/lib/generators/active_endpoint/install_generator.rb +35 -0
  65. data/lib/generators/templates/active_endpoint.rb +40 -0
  66. data/lib/generators/templates/migration.erb +30 -0
  67. metadata +109 -0
@@ -0,0 +1,13 @@
1
+ <div class="card">
2
+ <div class="card-header">Settings</div>
3
+ <ul class="list-group">
4
+ <%- settings.each do |setting|%>
5
+ <li class="list-group-item">
6
+ <div class="row">
7
+ <div class="col"><%= setting.to_s.gsub('_', ' ').capitalize %></div>
8
+ <div class="col"><%= ActiveEndpoint.get_settings(setting) %></div>
9
+ </div>
10
+ </li>
11
+ <% end %>
12
+ </ul>
13
+ </div>
@@ -0,0 +1,20 @@
1
+ <div class="card">
2
+ <div class="card-header">Tags</div>
3
+ <ul class="list-group">
4
+ <%- tags.each do |name, label_class, condition, helper| %>
5
+ <li class="list-group-item">
6
+ <div class="row">
7
+ <div class="col col-2">
8
+ <span class="label <%= label_class %>"><%= name %></span>
9
+ </div>
10
+ <div class="col">
11
+ <span><%= condition %></span>
12
+ </div>
13
+ <div class="col">
14
+ <code><%= helper %></code>
15
+ </div>
16
+ </div>
17
+ </li>
18
+ <% end %>
19
+ </ul>
20
+ </div>
@@ -0,0 +1,8 @@
1
+ <h1>Dashboard</h1>
2
+ <%= render 'settings' %>
3
+ <br/>
4
+ <%= render 'tags' %>
5
+ <br/>
6
+ <%= render 'blacklist' %>
7
+ <br/>
8
+ <%= render 'constraints' %>
@@ -0,0 +1,28 @@
1
+ <h1>Probes</h1>
2
+
3
+ <table class="table table-hover table-bordered">
4
+ <thead>
5
+ <tr>
6
+ <th>endpoint</th>
7
+ <th>method</th>
8
+ <th>amount in period</th>
9
+ <th>Average duration</th>
10
+ <th></th>
11
+ </tr>
12
+ </thead>
13
+ <tbody>
14
+ <% if @probes_group.any?%>
15
+ <% @probes_group.each do |group| %>
16
+ <tr>
17
+ <th><%= group[:endpoint] %></th>
18
+ <td><%= group[:method] %></td>
19
+ <td><%= group[:amount] %></td>
20
+ <td><%= (group[:duration].round(3) * 1000).to_i %></td>
21
+ <td><%= link_to 'Show', active_endpoint.probe_path(id: group[:endpoint]), class: 'btn btn-info btn-sm' %></td>
22
+ </tr>
23
+ <% end %>
24
+ <% else %>
25
+ <tr><td colspan="4" style="text-align: center;">No Probes</td></tr>
26
+ <% end %>
27
+ </tbody>
28
+ </table>
@@ -0,0 +1,43 @@
1
+ <h1>Probes for <%= @endpoint %></h1>
2
+
3
+ <table class="table table-hover table-bordered">
4
+ <thead>
5
+ <tr>
6
+ <th>uuid</th>
7
+ <th>ip</th>
8
+ <th>xhr?</th>
9
+ <th>query string</th>
10
+ <th>params</th>
11
+ <th>duration</th>
12
+ <th>tag</th>
13
+ <td>created at</td>
14
+ <th></th>
15
+ </tr>
16
+ </thead>
17
+ <tbody>
18
+ <%- if @probes.any? %>
19
+ <%- @probes.each do |probe| %>
20
+ <tr>
21
+ <td><%= probe.uuid %></td>
22
+ <td><%= probe.ip %></td>
23
+ <td><%= probe.xhr %></td>
24
+ <td><%= probe.query_string %></td>
25
+ <td><%= probe.params %></td>
26
+ <td><%= (probe.duration * 1000).to_i %></td>
27
+ <td>
28
+ <span class="label <%= label_for(probe.tag) %>">
29
+ <%= probe.tag %>
30
+ </span>
31
+ </td>
32
+ <td><%= probe.created_at %></td>
33
+ <td>
34
+ <%= link_to 'Show Response', active_endpoint.probe_show_response_path(probe), class: 'btn btn-info btn-sm' %>
35
+ <%= link_to 'Remove', active_endpoint.probe_path(probe), method: :delete, class: 'btn btn-danger btn-sm' %>
36
+ </td>
37
+ </tr>
38
+ <% end%>
39
+ <% else %>
40
+ <tr><td colspan="2" style="text-align: center;">No Probes</td></tr>
41
+ <% end %>
42
+ </tbody>
43
+ </table>
@@ -0,0 +1,9 @@
1
+ <h2>Proberesponse for <%= @probe.endpoint %> with <%= @probe.uuid %></h2>
2
+
3
+ <div class="">
4
+ <%= Base64.decode64(@probe.response) %>
5
+ </div>
6
+
7
+ <br/>
8
+
9
+ <%= link_to 'Back', :back, class: '' %>
@@ -0,0 +1,28 @@
1
+ <h1>Unregistred Probes</h1>
2
+
3
+ <table class="table table-hover table-bordered">
4
+ <thead>
5
+ <tr>
6
+ <th>uuid</th>
7
+ <th>path</th>
8
+ <th>query string</th>
9
+ <th>started_at</th>
10
+ <th></th>
11
+ </tr>
12
+ </thead>
13
+ <tbody>
14
+ <% if @probes.any?%>
15
+ <% @probes.each do |probe| %>
16
+ <tr>
17
+ <th><%= probe.uuid %></th>
18
+ <td><%= probe.path %></td>
19
+ <td><%= probe.query_string%></td>
20
+ <td><%= probe.started_at %></td>
21
+ <td><%= link_to 'Remove', active_endpoint.unregistred_probe_path(probe.id), method: :delete, class: 'btn btn-danger btn-sm' %></td>
22
+ </tr>
23
+ <% end%>
24
+ <% else %>
25
+ <tr><td colspan="4">No Probes</td></tr>
26
+ <% end %>
27
+ </tbody>
28
+ </table>
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="ROBOTS" content="NOODP" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
7
+ <title>ActiveEndpoint</title>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/css/tether.css" integrity="sha256-XlckdtWgpo4xmVoJR0BgtatbV/UpLTiOE+UBfRGFutg=" crossorigin="anonymous" />
9
+ <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
10
+ <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
11
+ <link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/flatly/bootstrap.min.css" rel="stylesheet" integrity="sha384-+ENW/yibaokMnme+vBLnHMphUYxHs34h9lpdbSLuAwGkOKFRl4C34WkjazBtb7eT" crossorigin="anonymous">
12
+
13
+ <%= stylesheet_link_tag 'active_endpoint/application', media: 'all' %>
14
+ <%= csrf_meta_tags %>
15
+ </head>
16
+ <body class="active_endpoint active_endpoint-body">
17
+ <div class="active_endpoint-layout">
18
+ <div class="active_endpoint-header">
19
+ <%= render 'flashes' %>
20
+ </div>
21
+ <div class="active_endpoint-header">
22
+ <%= render 'header' %>
23
+ </div>
24
+ <div class="active_endpoint-content">
25
+ <div class="container">
26
+ <%= yield %>
27
+ </div>
28
+ </div>
29
+ </div>
30
+
31
+ <script src="http://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
32
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-ujs/1.2.2/rails.js" integrity="sha256-eEqZf2cmA2sZk+siF8nLVY4cu4AcbaiBBViMVvE7Rmo=" crossorigin="anonymous"></script>
33
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.js" integrity="sha256-jVfFb7AbGi7S/SLNl8SB4/MYaf549eEs+NlIWMoARHg=" crossorigin="anonymous"></script>
34
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
35
+ <script src="https://maxcdn.bootstrapcdn.com/bootlint/0.14.2/bootlint.min.js" integrity="sha384-SLfe/wBrCVfyGjtLhfUmA5cYQLnNVTRmwMUJ11s7x5HxXCKom2oeEwX9bvY74CAs" crossorigin="anonymous"></script>
36
+
37
+ <%= javascript_include_tag 'active_endpoint/application' %>
38
+ </body>
39
+ </html>
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'active_endpoint'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start(__FILE__)
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
6
+ ENGINE_PATH = File.expand_path('../../lib/active_endpoint/engine', __FILE__)
7
+
8
+ # Set up gems listed in the Gemfile.
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
10
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
11
+
12
+ require 'rails/all'
13
+ require 'rails/engine/commands'
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,8 @@
1
+ ActiveEndpoint::Engine.routes.draw do
2
+ root 'dashboard#index'
3
+
4
+ resources :probes, only: [:index, :show, :destroy] do
5
+ get :show_response
6
+ end
7
+ resources :unregistred_probes, only: [:index, :destroy]
8
+ end
@@ -0,0 +1,60 @@
1
+ require 'base64'
2
+ require 'rack'
3
+ require 'rack/request'
4
+ require 'active_support/time'
5
+ require 'active_support/rails'
6
+ require 'active_support/core_ext/module/delegation'
7
+
8
+ require 'active_endpoint/concerns/configurable'
9
+ require 'active_endpoint/concerns/constraintable'
10
+ require 'active_endpoint/concerns/optionable'
11
+ require 'active_endpoint/concerns/rails_routable'
12
+ require 'active_endpoint/extentions/active_record'
13
+ require 'active_endpoint/routes/momento'
14
+ require 'active_endpoint/routes/blacklist'
15
+ require 'active_endpoint/routes/constraints'
16
+ require 'active_endpoint/routes/constraint_rule'
17
+ require 'active_endpoint/routes/matcher'
18
+ require 'active_endpoint/routes/cache/proxy/redis_store_proxy'
19
+ require 'active_endpoint/routes/cache/proxy'
20
+ require 'active_endpoint/routes/cache/store'
21
+ require 'active_endpoint/proxy'
22
+ require 'active_endpoint/logger'
23
+ require 'active_endpoint/request'
24
+ require 'active_endpoint/response'
25
+ require 'active_endpoint/storage'
26
+ require 'active_endpoint/tags'
27
+ require 'active_endpoint/version'
28
+
29
+ module ActiveEndpoint
30
+ extend Configurable
31
+
32
+ define_setting :blacklist, ActiveEndpoint::Routes::Blacklist.new
33
+
34
+ define_setting :cache_store_client, :redis
35
+ define_setting :cache_prefix, 'active_endpoint'
36
+
37
+ define_setting :constraint_limit, 10
38
+ define_setting :constraint_period, 10.minutes
39
+ define_setting :constraints, ActiveEndpoint::Routes::Constraints.new
40
+
41
+ define_setting :logger, ActiveEndpoint::Logger
42
+
43
+ define_setting :log_probe_info, false
44
+ define_setting :log_debug_info, false
45
+
46
+ define_setting :storage_limit, 1000
47
+ define_setting :storage_period, 1.day
48
+ define_setting :storage_keep_periods, 2
49
+
50
+ define_setting :tags, ActiveEndpoint::Tags.new
51
+ end
52
+
53
+ if defined?(::Rails)
54
+ require 'rails/generators'
55
+ require 'rails/generators/migration'
56
+
57
+ require 'active_endpoint/rails/middleware'
58
+ require 'active_endpoint/rails/railtie'
59
+ require 'active_endpoint/engine'
60
+ end
@@ -0,0 +1,29 @@
1
+ module Configurable
2
+ def configure
3
+ yield self
4
+ end
5
+
6
+ def define_setting(name, default = nil)
7
+ class_variable_set("@@#{name}", default)
8
+
9
+ define_class_method "#{name}=" do |value|
10
+ class_variable_set("@@#{name}", value)
11
+ end
12
+
13
+ define_class_method name do
14
+ class_variable_get("@@#{name}")
15
+ end
16
+ end
17
+
18
+ def get_settings(name)
19
+ class_variable_get("@@#{name}")
20
+ end
21
+
22
+ private
23
+
24
+ def define_class_method(name, &block)
25
+ (class << self; self; end).instance_eval do
26
+ define_method name, &block
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,51 @@
1
+ module Constraintable
2
+ def constraints(options)
3
+ {
4
+ rule: rule_constraints(options),
5
+ storage: storage_constraints(options)
6
+ }
7
+ end
8
+
9
+ def rule_constraints(options)
10
+ rule_options = fetch_rule(options)
11
+
12
+ defined_rule_constraints = {
13
+ limit: fetch_limit(rule_options),
14
+ period: fetch_period(rule_options)
15
+ }.reject { |_key, value| value.nil? }
16
+
17
+ default_rule_constraints.merge(defined_rule_constraints)
18
+ end
19
+
20
+ def storage_constraints(options)
21
+ storage_options = fetch_storage(options)
22
+
23
+ defined_storage_constraints = {
24
+ limit: fetch_limit(storage_options),
25
+ period: fetch_period(storage_options)
26
+ }.reject { |_key, value| value.nil? }
27
+
28
+ default_storage_constraints.merge(defined_storage_constraints)
29
+ end
30
+
31
+ def default_constraints
32
+ {
33
+ rule: default_rule_constraints,
34
+ storage: default_storage_constraints
35
+ }
36
+ end
37
+
38
+ def default_rule_constraints
39
+ {
40
+ limit: ActiveEndpoint.constraint_limit,
41
+ period: ActiveEndpoint.constraint_period
42
+ }
43
+ end
44
+
45
+ def default_storage_constraints
46
+ {
47
+ limit: ActiveEndpoint.storage_limit,
48
+ period: ActiveEndpoint.storage_period
49
+ }
50
+ end
51
+ end
@@ -0,0 +1,41 @@
1
+ module Optionable
2
+ def fetch_endpoint(options)
3
+ return nil unless options
4
+ options[:endpoint]
5
+ end
6
+
7
+ def fetch_actions(options)
8
+ return nil unless options
9
+ options[:actions]
10
+ end
11
+
12
+ def fetch_resources(options)
13
+ return nil unless options
14
+ options[:resources]
15
+ end
16
+
17
+ def fetch_scope(options)
18
+ return nil unless options
19
+ options[:scope]
20
+ end
21
+
22
+ def fetch_limit(options)
23
+ return nil unless options
24
+ options[:limit]
25
+ end
26
+
27
+ def fetch_period(options)
28
+ return nil unless options
29
+ options[:period]
30
+ end
31
+
32
+ def fetch_storage(options)
33
+ return nil unless options
34
+ options[:storage]
35
+ end
36
+
37
+ def fetch_rule(options)
38
+ return nil unless options
39
+ options[:rule]
40
+ end
41
+ end
@@ -0,0 +1,49 @@
1
+ module RailsRoutable
2
+ ACTION_KEYS = [
3
+ :controller,
4
+ :action
5
+ ].freeze
6
+
7
+ def rails_action?(request)
8
+ rails_action(request).present?
9
+ end
10
+
11
+ def rails_request_params(request)
12
+ action = rails_action(request)
13
+ return unless action
14
+ action.reject do |key, _value|
15
+ ACTION_KEYS.include?(key)
16
+ end
17
+ end
18
+
19
+ def rails_endpoint(request)
20
+ action = rails_action(request)
21
+ return unless action
22
+ action.select do |key, _value|
23
+ ACTION_KEYS.include?(key)
24
+ end
25
+ end
26
+
27
+ def rails_endpoint_name(action)
28
+ return unless action
29
+ "#{action[:controller]}##{action[:action]}"
30
+ end
31
+
32
+ def rails_action(request)
33
+ rails_routes.recognize_path(request.path, method: request.method)
34
+ rescue ActionController::RoutingError
35
+ nil
36
+ end
37
+
38
+ def rails_route_pattern(request)
39
+ rails_routes.router.recognize(request) do |route|
40
+ return route.path.spec.to_s
41
+ end
42
+ rescue ActionController::RoutingError
43
+ nil
44
+ end
45
+
46
+ def rails_routes
47
+ ::Rails.application.routes
48
+ end
49
+ end