redis_web_manager 0.1.6 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +2 -0
  3. data/.travis.yml +1 -0
  4. data/Gemfile.lock +23 -1
  5. data/README.md +95 -4
  6. data/Rakefile +1 -1
  7. data/app/controllers/redis_web_manager/actions_controller.rb +15 -3
  8. data/app/controllers/redis_web_manager/application_controller.rb +4 -0
  9. data/app/controllers/redis_web_manager/clients_controller.rb +1 -1
  10. data/app/controllers/redis_web_manager/configuration_controller.rb +1 -1
  11. data/app/controllers/redis_web_manager/dashboard_controller.rb +23 -3
  12. data/app/controllers/redis_web_manager/information_controller.rb +1 -1
  13. data/app/controllers/redis_web_manager/keys_controller.rb +135 -0
  14. data/app/helpers/redis_web_manager/application_helper.rb +16 -0
  15. data/app/helpers/redis_web_manager/dashboard_helper.rb +1 -1
  16. data/app/views/redis_web_manager/dashboard/index.html.erb +20 -1
  17. data/app/views/redis_web_manager/keys/edit.html.erb +14 -0
  18. data/app/views/redis_web_manager/keys/index.html.erb +54 -0
  19. data/app/views/redis_web_manager/keys/show.html.erb +30 -0
  20. data/app/views/redis_web_manager/shared/_header.html.erb +12 -2
  21. data/app/views/redis_web_manager/shared/_status.html.erb +2 -2
  22. data/bin/rails +1 -1
  23. data/config/routes.rb +8 -0
  24. data/lib/redis_web_manager.rb +1 -1
  25. data/lib/redis_web_manager/action.rb +1 -1
  26. data/lib/redis_web_manager/data.rb +16 -0
  27. data/lib/redis_web_manager/version.rb +1 -1
  28. data/redis_web_manager.gemspec +6 -4
  29. data/spec/controllers/redis_web_manager/actions_controller_spec.rb +16 -1
  30. data/spec/controllers/redis_web_manager/clients_controller_spec.rb +1 -1
  31. data/spec/controllers/redis_web_manager/keys_controller_spec.rb +139 -0
  32. data/spec/helpers/application_helper_spec.rb +13 -1
  33. data/spec/helpers/dashboard_helper_spec.rb +1 -1
  34. data/spec/redis_web_manager_data_spec.rb +23 -0
  35. data/spec/routing/actions_controller_spec.rb +6 -0
  36. data/spec/routing/keys_controller_spec.rb +39 -0
  37. data/spec/spec_helper.rb +6 -0
  38. metadata +295 -342
@@ -2,6 +2,22 @@
2
2
 
3
3
  module RedisWebManager
4
4
  module ApplicationHelper
5
+ require 'pagy'
6
+
7
+ include ::Pagy::Frontend
8
+
9
+ def status(value)
10
+ if value
11
+ content_tag(:kbd, 'ON', class: 'bg-success bounce')
12
+ else
13
+ content_tag(:kbd, 'OFF', class: 'bg-danger bounce')
14
+ end
15
+ end
16
+
17
+ def url(value)
18
+ content_tag(:kbd, value, class: 'bg-dark')
19
+ end
20
+
5
21
  def expire(value)
6
22
  if value == -1
7
23
  'No expiration date'
@@ -17,4 +17,4 @@ module RedisWebManager
17
17
  end
18
18
  end
19
19
  end
20
- end
20
+ end
@@ -1,7 +1,7 @@
1
1
  <div class="container">
2
2
  <%= render 'redis_web_manager/shared/status' %>
3
3
  <div class="row my-4">
4
- <div class="col-sm-12 col-md-12">
4
+ <div class="col-sm-12 col-md-9">
5
5
  <div class="row mb-4">
6
6
  <div class="col-12">
7
7
  <div class="card">
@@ -45,5 +45,24 @@
45
45
  </div>
46
46
  </div>
47
47
  </div>
48
+ <div class="col-sm-12 col-md-3">
49
+ <div class="card">
50
+ <div class="card-header">
51
+ <h5 class="card-title mb-0">
52
+ Information
53
+ </h5>
54
+ </div>
55
+ <div class="card-body p-0">
56
+ <ul class="list-group list-group-flush">
57
+ <% @information.each do |data| %>
58
+ <li class="list-group-item d-flex justify-content-between">
59
+ <div class="font-weight-normal"><%= data[:name] %></div>
60
+ <div class="font-weight-light"><%= data[:value] %></div>
61
+ </li>
62
+ <% end %>
63
+ </ul>
64
+ </div>
65
+ </div>
66
+ </div>
48
67
  </div>
49
68
  </div>
@@ -0,0 +1,14 @@
1
+ <div class="container">
2
+ <div class="row my-4">
3
+ <div class="col-sm-6 offset-sm-3">
4
+ <%= form_tag update_key_path, method: :put, class: "form-horizontal center" do %>
5
+ <div class="form-group">
6
+ <%= label_tag :key, "Name key:", class: "control-label" %>
7
+ <%= text_field_tag :key, @key[:key], class: "form-control" %>
8
+ <%= hidden_field_tag :old_key, @key[:key] %>
9
+ </div>
10
+ <%= submit_tag "Submit", class: "btn btn-default btn-primary" %>
11
+ <% end %>
12
+ </div>
13
+ </div>
14
+ </div>
@@ -0,0 +1,54 @@
1
+ <div class="container">
2
+ <%= render 'redis_web_manager/shared/status' %>
3
+ <div class="row my-4">
4
+ <div class="col-12">
5
+ <div class="card">
6
+ <div class="card-header">
7
+ <h5 class="card-title mb-0">
8
+ Keys
9
+ </h5>
10
+ </div>
11
+ <div class="card-body p-0">
12
+ <%= form_tag(keys_path, method: :get, class: 'p-4', enforce_utf8: false) do %>
13
+ <div class="input-group">
14
+ <%= text_field_tag :query, params[:query], class: 'form-control', placeholder: 'Search key(s)' %>
15
+ <div class="input-group-append">
16
+ <%= submit_tag 'Search', class: 'btn btn-primary', name: nil %>
17
+ </div>
18
+ </div>
19
+ <% end %>
20
+ <div class="table-responsive">
21
+ <table class="table mb-0">
22
+ <thead>
23
+ <tr>
24
+ <th>Name</th>
25
+ <th>Expiration Date</th>
26
+ <th>Size</th>
27
+ <th>Type</th>
28
+ <th>Options</th>
29
+ </tr>
30
+ </thead>
31
+ <tbody>
32
+ <% @keys.each do |key| %>
33
+ <tr>
34
+ <td><%= link_to (key[:key]).truncate(45), key_path(key: key[:key]), title: "Show #{key[:key]}" %></td>
35
+ <td><%= expire(key[:expire]) %></td>
36
+ <td><code><%= number_to_human_size(key[:memory]) %></code></td>
37
+ <td><kbd class="bg-dark"><%= key[:type] %></kbd></td>
38
+ <td>
39
+ <%= link_to 'Edit', edit_key_path(key: key[:key]), title: "Edit #{key[:key]}", class: 'btn btn-sm btn-primary ml-2' %>
40
+ <%= link_to 'Delete', destroy_key_path(key: key[:key]), method: :delete, data: {confirm: 'Are you sure ?'}, title: "Delete #{key[:key]}", class: 'btn btn-sm btn-danger ml-2' %>
41
+ </td>
42
+ </tr>
43
+ <% end %>
44
+ </tbody>
45
+ </table>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ <div class="d-flex align-items-center justify-content-center mt-3">
50
+ <%= pagy_bootstrap_nav(@pagy).html_safe %>
51
+ </div>
52
+ </div>
53
+ </div>
54
+ </div>
@@ -0,0 +1,30 @@
1
+ <div class="container mt-4">
2
+ <div class="row">
3
+ <div class="col-12">
4
+ <label class="font-weight-normal">Key:</label>
5
+ <p class="font-weight-light">
6
+ <code><%= @key[:key] %></code>
7
+ </p>
8
+ <label class="font-weight-normal">Value:</label>
9
+ <p class="font-weight-light">
10
+ <code><%= @key[:node][:value] %></code>
11
+ </p>
12
+ <label class="font-weight-normal">Expires in:</label>
13
+ <p class="font-weight-light">
14
+ <%= expire(@key[:expire]) %>
15
+ </p>
16
+ <label class="font-weight-normal">Size:</label>
17
+ <p class="font-weight-light">
18
+ <code><%= number_to_human_size(@key[:memory]) %></code>
19
+ </p>
20
+ <label class="font-weight-normal">Type:</label>
21
+ <p class="font-weight-light">
22
+ <kbd class="bg-dark"><%= @key[:type] %></kbd>
23
+ </p>
24
+ <p class="font-weight-light">
25
+ <%= link_to 'Delete', destroy_key_path(key: @key[:key]), method: :delete, data: {confirm: 'Are you sure ?'}, title: "Delete #{@key}", class: 'btn btn-sm btn-danger w-100 mb-2' %>
26
+ <%= link_to 'Back', keys_path, title: 'View keys', class: 'btn btn-sm btn-primary w-100' %>
27
+ </p>
28
+ </div>
29
+ </div>
30
+ </div>
@@ -23,15 +23,25 @@
23
23
  </li>
24
24
  </ul>
25
25
  <ul class="navbar-nav ml-auto">
26
+ <li class="nav-item">
27
+ <%= link_to 'Reset statistics',
28
+ reset_path,
29
+ title: 'Reset statistics',
30
+ method: :delete,
31
+ data: {
32
+ confirm: 'Are you sure you want to reset statistics ?'
33
+ },
34
+ class: 'btn btn-sm btn-info nav-link text-white mr-xs-0 mr-lg-2 mb-2 mb-lg-0' %>
35
+ </li>
26
36
  <li class="nav-item">
27
37
  <%= link_to 'Flush ALL',
28
- flushall_url,
38
+ flushall_path,
29
39
  title: 'Flush ALL',
30
40
  method: :delete,
31
41
  data: {
32
42
  confirm: 'Are you sure you want to flush all DB ?'
33
43
  },
34
- class: 'btn btn-sm btn-danger nav-link text-white mr-xs-0 mr-lg-2 mb-2 mb-lg-0' %>
44
+ class: 'btn btn-sm btn-dark nav-link text-white mr-xs-0 mr-lg-2 mb-2 mb-lg-0' %>
35
45
  </li>
36
46
  <li class="nav-item">
37
47
  <%= link_to 'Flush DB',
@@ -1,6 +1,6 @@
1
1
  <div class="row my-4">
2
2
  <div class="col-12">
3
- <%= @url %>
4
- <%= @status %>
3
+ <%= url(@url) %>
4
+ <%= status(@status) %>
5
5
  </div>
6
6
  </div>
data/bin/rails CHANGED
@@ -17,4 +17,4 @@ require 'rails'
17
17
  require 'action_controller/railtie'
18
18
  require 'action_view/railtie'
19
19
  require 'sprockets/railtie'
20
- require 'rails/engine/commands'
20
+ require 'rails/engine/commands'
@@ -7,10 +7,18 @@ RedisWebManager::Engine.routes.draw do
7
7
  # Information
8
8
  get :information, to: 'information#index'
9
9
 
10
+ # Keys
11
+ get 'keys' => 'keys#index'
12
+ get 'key' => 'keys#show'
13
+ get 'key/edit' => 'keys#edit', as: :edit_key
14
+ put 'keys' => 'keys#update', as: :update_key
15
+ delete 'keys' => 'keys#destroy', as: :destroy_key
16
+
10
17
  # Clients
11
18
  get :clients, to: 'clients#index'
12
19
 
13
20
  # Actions
21
+ delete :reset, to: 'actions#reset'
14
22
  delete :flushdb, to: 'actions#flushdb'
15
23
  delete :flushall, to: 'actions#flushall'
16
24
 
@@ -10,8 +10,8 @@ require 'redis'
10
10
 
11
11
  module RedisWebManager
12
12
  mattr_accessor :redis, default: ::Redis.new
13
- mattr_accessor :authenticate, default: nil
14
13
  mattr_accessor :lifespan, default: 15.days
14
+ mattr_accessor :authenticate, default: nil
15
15
 
16
16
  class << self
17
17
  def configure
@@ -18,4 +18,4 @@ module RedisWebManager
18
18
  redis.rename(old_name, new_name)
19
19
  end
20
20
  end
21
- end
21
+ end
@@ -4,14 +4,30 @@ module RedisWebManager
4
4
  class Data < Base
5
5
  BASE = 'RedisWebManager'
6
6
 
7
+ def keys
8
+ data.map { |key| JSON.parse(redis.get(key), symbolize_names: true) }
9
+ end
10
+
7
11
  def perform
8
12
  now = Time.now.to_i
9
13
  seconds = (now + lifespan.to_i) - now
10
14
  redis.setex("#{BASE}_#{now}", seconds, serialize.to_json)
11
15
  end
12
16
 
17
+ def flush
18
+ data.map { |key| redis.del(key) }
19
+ end
20
+
13
21
  private
14
22
 
23
+ def data
24
+ @data ||= redis.scan_each(match: "#{BASE}_*").to_a
25
+ end
26
+
27
+ def lifespan
28
+ @lifespan ||= RedisWebManager.lifespan
29
+ end
30
+
15
31
  def serialize
16
32
  {
17
33
  date: Time.now,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RedisWebManager
4
- VERSION = '0.1.6'
4
+ VERSION = '0.1.8'
5
5
  end
@@ -10,11 +10,10 @@ Gem::Specification.new do |spec|
10
10
  spec.name = 'redis_web_manager'
11
11
  spec.version = RedisWebManager::VERSION
12
12
 
13
- spec.authors = ['Boris BRESCIANI', 'Benjamin DARCET', 'Olivier DUMAS', 'Sylvain KRAISIN']
13
+ spec.authors = ['Boris BRESCIANI', 'Benjamin DARCET', 'Olivier DUMAS']
14
14
  spec.email = %w[boris2bresciani@gmail.com
15
15
  b.darcet@gmail.com
16
- dumas.olivier@outlook.fr
17
- sylvain.kraisin@gmail.com]
16
+ dumas.olivier@outlook.fr]
18
17
 
19
18
  spec.summary = 'Manage your Redis instance (See keys, memory used, connected client, etc...)'
20
19
  spec.description = 'Manage your Redis instance (See keys, memory used, connected client, configuration, information)'
@@ -35,8 +34,11 @@ Gem::Specification.new do |spec|
35
34
  spec.require_paths = ['lib']
36
35
  spec.test_files = Dir['spec/**/*']
37
36
 
37
+ spec.add_development_dependency 'coveralls', '~> 0.8'
38
38
  spec.add_development_dependency 'rspec-rails', '= 4.0.0.beta3'
39
+ spec.add_development_dependency 'simplecov', '~> 0.16'
39
40
 
41
+ spec.add_dependency 'pagy', '~> 3.7'
40
42
  spec.add_dependency 'rails', '>= 5.2', '< 7'
41
43
  spec.add_dependency 'redis', '~> 4.1.0'
42
- end
44
+ end
@@ -5,9 +5,24 @@ require 'rails_helper'
5
5
  RSpec.describe RedisWebManager::ActionsController, type: :controller do
6
6
  routes { RedisWebManager::Engine.routes }
7
7
 
8
+ describe 'DELETE #reset' do
9
+ it 'returns a success response' do
10
+ delete :reset
11
+ expect(response).to be_redirect
12
+ end
13
+ end
14
+
8
15
  describe 'DELETE #flushdb' do
16
+ it 'returns a success response' do
17
+ delete :flushdb
18
+ expect(response).to be_redirect
19
+ end
9
20
  end
10
21
 
11
22
  describe 'DELETE #flushall' do
23
+ it 'returns a success response' do
24
+ delete :flushall
25
+ expect(response).to be_redirect
26
+ end
12
27
  end
13
- end
28
+ end
@@ -11,4 +11,4 @@ RSpec.describe RedisWebManager::ClientsController, type: :controller do
11
11
  expect(response).to be_successful
12
12
  end
13
13
  end
14
- end
14
+ end
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe RedisWebManager::KeysController, type: :controller do
6
+ routes { RedisWebManager::Engine.routes }
7
+ let(:redis) do
8
+ ::Redis.new
9
+ end
10
+
11
+ describe 'GET #index' do
12
+ it 'returns a success response' do
13
+ get :index
14
+ expect(response).to be_successful
15
+ get :index, params: { query: 'Search' }
16
+ expect(response).to be_successful
17
+ end
18
+ end
19
+
20
+ describe 'GET #show' do
21
+ it 'returns a success response' do
22
+ redis.set('test', 'test')
23
+ get :show, params: { key: 'test' }
24
+ expect(response).to be_successful
25
+ end
26
+ end
27
+
28
+ describe 'GET #edit' do
29
+ it 'returns a success response' do
30
+ redis.set('test', 'test')
31
+ get :edit, params: { key: 'test' }
32
+ expect(response).to be_successful
33
+ end
34
+ end
35
+
36
+ describe 'GET #update' do
37
+ it 'returns a success response' do
38
+ redis.set('test', 'test')
39
+ put :update, params: { old_name: 'test', new_name: 'testtest' }
40
+ expect(response).to be_redirect
41
+ end
42
+ end
43
+
44
+ describe 'GET #destroy' do
45
+ it 'returns a success response' do
46
+ redis.set('test', 'test')
47
+ delete :destroy, params: { key: 'test' }
48
+ expect(response).to be_redirect
49
+ end
50
+ end
51
+
52
+ describe 'Methods' do
53
+ it 'returns a hash value (get_value - string)' do
54
+ redis.set('test', 'test')
55
+ eql = {
56
+ value: 'test'
57
+ }
58
+ expect(controller.send(:get_value, 'test')).to eql(eql)
59
+ end
60
+
61
+ it 'returns a hash value (get_value - hgetall)' do
62
+ eql = {
63
+ value: {
64
+ 'name' => {
65
+ type: 'string',
66
+ value: 'hgetall'
67
+ }
68
+ }
69
+ }
70
+ redis.hset('hgetall', 'name', 'hgetall')
71
+ expect(controller.send(:get_value, 'hgetall')).to eql(eql)
72
+ end
73
+
74
+ it 'returns a hash value (get_value - lrange)' do
75
+ redis.lpush('lrange', '1')
76
+ redis.lpush('lrange', '2')
77
+ eql = {
78
+ length: 2,
79
+ values: [
80
+ {
81
+ index: 0,
82
+ type: 'json',
83
+ value: 2
84
+ },
85
+ {
86
+ index: 1,
87
+ type: 'json',
88
+ value: 1
89
+ }
90
+ ]
91
+ }
92
+ expect(controller.send(:get_value, 'lrange')).to eql(eql)
93
+ end
94
+
95
+ it 'returns a hash value (get_value - set)' do
96
+ redis.sadd('smembers', 'smembers')
97
+ eql = {
98
+ values: [{ type: 'string', value: 'smembers' }]
99
+ }
100
+ expect(controller.send(:get_value, 'smembers')).to eql(eql)
101
+ end
102
+
103
+ it 'returns a hash value (get_value - zset)' do
104
+ redis.zadd('zrange', 10, '1')
105
+ redis.zadd('zrange', 20, '2')
106
+ redis.zadd('zrange', 30, '3')
107
+ eql = {
108
+ values: [
109
+ {
110
+ score: 10.0,
111
+ type: 'json',
112
+ value: 1
113
+ },
114
+ {
115
+ score: 20.0,
116
+ type: 'json',
117
+ value: 2
118
+ },
119
+ {
120
+ score: 30.0,
121
+ type: 'json',
122
+ value: 3
123
+ }
124
+ ]
125
+ }
126
+ expect(controller.send(:get_value, 'zrange')).to eql(eql)
127
+ end
128
+
129
+ it 'returns a hash value (get_value - not found)' do
130
+ redis.zadd('zrange', 10, '1')
131
+ redis.zadd('zrange', 20, '2')
132
+ redis.zadd('zrange', 30, '3')
133
+ eql = {
134
+ value: 'Not found'
135
+ }
136
+ expect(controller.send(:get_value, 'testtesttesttesttest')).to eql(eql)
137
+ end
138
+ end
139
+ end