proxes 0.9.2 → 0.9.4
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/.travis.yml +2 -1
- data/Dockerfile +1 -2
- data/Gemfile.deploy.lock +2 -2
- data/Gemfile.dev +4 -4
- data/config.ru +8 -2
- data/config/logger.yml +2 -0
- data/docker-compose.yml +5 -5
- data/lib/proxes/controllers/permissions.rb +1 -1
- data/lib/proxes/controllers/status.rb +18 -9
- data/lib/proxes/forwarder.rb +0 -11
- data/lib/proxes/helpers/indices.rb +17 -1
- data/lib/proxes/middleware/error_handling.rb +74 -0
- data/lib/proxes/middleware/metrics.rb +25 -0
- data/lib/proxes/middleware/security.rb +60 -0
- data/lib/proxes/models/permission.rb +6 -0
- data/lib/proxes/policies/request/bulk_policy.rb +5 -16
- data/lib/proxes/policies/request/cat_policy.rb +0 -8
- data/lib/proxes/policies/request/create_policy.rb +1 -6
- data/lib/proxes/policies/request/index_policy.rb +1 -7
- data/lib/proxes/policies/request/search_policy.rb +2 -8
- data/lib/proxes/policies/request/stats_policy.rb +0 -8
- data/lib/proxes/policies/request_policy.rb +6 -15
- data/lib/proxes/request.rb +45 -20
- data/lib/proxes/services/es.rb +2 -2
- data/lib/proxes/version.rb +1 -1
- data/public/js/bundle.js +422 -216
- data/startup.sh +3 -2
- data/views/index.haml +1 -0
- data/views/layout.haml +60 -0
- data/views/partials/navbar.haml +25 -0
- metadata +9 -4
- data/lib/proxes/security.rb +0 -89
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a89e0871c6d36ce3b7e6ff19c4b7fa7556cedeedd0d364bd78d0aa741b06c6e9
|
4
|
+
data.tar.gz: b126f70689158d474c5f096386c13a46ffdb8e58c90c7c77181a11cef3de14d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83df2e988cb4f9d64fae3693603dddb03912483b29e04b3c65e0ee691b341b2fe68d029e2253559534c23ee15fad129d83b7954261a297f2ab004e97dc81f2ba
|
7
|
+
data.tar.gz: 591c032478769ea14170e7dfb8ae92c7e34f0a5ad23dc4569bfcb5745ba47bcaa1e1585c1b4e2a5ec669c88fbb2417b9253f6427fbf671b181e8d8b21db3cbbe
|
data/.travis.yml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
sudo: true
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
-
- 2.5.
|
4
|
+
- 2.5.1
|
5
5
|
- 2.4.3
|
6
6
|
- 2.3.6
|
7
7
|
- 2.2.9
|
@@ -9,6 +9,7 @@ gemfile: Gemfile.ci
|
|
9
9
|
env:
|
10
10
|
global:
|
11
11
|
- CC_TEST_REPORTER_ID=1f562305f75e169f5f5eca3b738fee879550c98e50099c2b9cd6ae71478007a0
|
12
|
+
- DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL=true
|
12
13
|
- secure: wTIBP3ZtltfLyIFS6p4XgzPff70EZLxIOpzL4tWCsB2XmEMtCBPdfm9CXLw88yxH4mCJbCVljJHRzrav9N5RimVGb3h5AX5ODpqJYO4PWRZzNYGglXM3f/3QWFXExEdJ97y0m2XytOzlVWtYjShqpCq1V9z88XwmJ2YQtiFMma4n2fjW8+WK30eGwNw60GAf7a2IAA2qMSIymEdM0OcRRVjmyWRtdAslnjANQ/m9lRYeNTfwfG5Xw26BRzv46Urmlw9MZsFGV5bG5bAKRFbp3h00UsPjKlAUL22bqEQ5XmRCuXCMzffoPhfJHDao+3iaVZlViwbCmoHRuuwHnTmUBFvvef/MRSUdLLwBsKBeDVofpGhLEInPX+D/kicNEnidYTtz+O8XZ0Hgur+VN+ayItIVZqFyaw96c9n+2H/KR7TG2lsccdFHNgATTX/fVOCc2AuBI84z3qM1LFYpJibwoTktQS1dnlmX6hwwEg+lJFhY0Spr3+aKOHf/zgqK+Q0jrEDQMo0khDTuPaOy2kznzK6ktrZVizw1tZyH80Eop/Yxpx1bIab8CF49pWlMZAkwmTP3e24qewUtgExyxUK1yBZ23L7QDnYLtfwCFfUbiEScjghJ9Aez1yerMCxNUrSOltyk1XxZw9xMrptA8VgN/0sFFmfICTXTZSqJdIGkfGY=
|
13
14
|
- secure: z4AUz0bssd0C7rfPsh71aH6ki8Zp49WZrYNRhj50MytJympFsEOYRVdVKuuAoq7jaD0cahIioDHrTf1J9bIOqMPc3l2lk9RFWA27Qk46C5zNxspnNBin0disEeO/AENlb5Zwe/Cqamg7Sc/NVpELPqUl8gHfX3FVv4Po3dZZWQb1d/pLXBpl84HGLWgFwz6ku+74XW6aqX1Qzd8G0s9gsqsAgUszwEX3ppltBrai1VdtZyFbv0XCOds3F687Ecyht3FJBQCOaTopPQztdmA8rBTPW+ffhfoZuQWfo8aILqmn9xCGr4vhMjwaOP7cVQdXcPs1ecsFBKFS0XRm5kJKBtBPLDfEc4zl6UIIe5xZBh5m0dysxu78ZoNFVui3QszyUP+dARf3AHsy1m3d8iRXMNEqKTTglKdPIdFKZLnWGoVSf+fidR7NIyJH7MGhr4VC8esGFGazzOXBnqVAX+z1tEse6n7llFcy0dREW0FNMpKMSP6TqN4LRiKXtRdSbeSvHXP3UiH6vPjAE/lHhf7qXSNOLkZDtCWrD0us4kT1ACeL2AV2SArJf7pmGdEL9pUyp4jSuStwxtRPhYJj2kuS6op9MYoU6Q8eyXhIw8Uju4SitGtkTnb8t5L50Xw7vUQT9faEah9ewJwB2kxa2RZxCdIzylwuYssCON4xkdXI1fY=
|
14
15
|
- secure: lUfjVwbIxUBQTGkDTOSMNvSYONBwI5yObn8fCByzGkfleddWPjLEeMPjGBZboOu2CVZ/q/FG3xbn63Hmss7CU83FmWRoV5dMP9Yc7X7cHaGmi31mZcaY2Yah+jgx7PcNIdK8LOAB3/zhxDNOcr8U4O9gqxGZWnV2NLR8SB+KiNTg5Hou3nOeVw7l1Iz+h1hXvZfxkMv7aX/3TLMT8j2JMkfgCN8moMlNRAYnvm/B68FPcVs6UFcaZIwg2mBnq3FrARo127jG1Ozms2SOPTqkPY9y8yoGyo3TYH2iQOKdRxCCECBnkSO8HYRYTL9CUoMk/D4ZTp7TGNRIKxjHtlt+9O1WtfmZB2aevZX5c7ChCZ0wNhQpzlsyPDz0GoIOkms5Bfv7nsvbloejr+vsRxe8YsNaVAVG+9RVZziKxGCWsxTopfnFMfFBK7KIoJ4N60ijhtBr3qcYQbSeoZWviwSd/GCjl9I2d2mTPVI0DsiFVt8lP92ZZitPJEhPRcxHdHu47Wu7oftndcVqzhhgdGnOxMchYKgzccR17VWlactGxffJP+ZIUkHaWCkxVR4etcrE753uaUX9x+M1fMoKKrwvycstX/YWLncgsYM1YensRUN7oW87wk216anlKfHubO2aVeDNnXn+wszK87M12o9gFu1khTBowqZpXsVDaUaa+oc=
|
data/Dockerfile
CHANGED
@@ -18,13 +18,12 @@ RUN apk add --update \
|
|
18
18
|
postgresql-dev \
|
19
19
|
&& rm -rf /var/cache/apk/* \
|
20
20
|
&& mkdir /root/.ssh \
|
21
|
-
&& mkdir /usr/src/app/tmp \
|
22
|
-
&& mkdir /usr/src/app/logs \
|
23
21
|
&& mkdir /usr/src/app/config \
|
24
22
|
&& touch /var/log/cron.log \
|
25
23
|
&& ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts \
|
26
24
|
&& gem install bundler
|
27
25
|
|
26
|
+
ADD views /usr/src/app/views
|
28
27
|
COPY config.ru /usr/src/app/
|
29
28
|
COPY config/logger.yml /usr/src/app/config/
|
30
29
|
COPY config/puma.rb /usr/src/app/config/
|
data/Gemfile.deploy.lock
CHANGED
@@ -44,7 +44,7 @@ GEM
|
|
44
44
|
tilt
|
45
45
|
hashie (3.5.7)
|
46
46
|
highline (1.7.10)
|
47
|
-
i18n (0.9.
|
47
|
+
i18n (0.9.4)
|
48
48
|
concurrent-ruby (~> 1.0)
|
49
49
|
logger (1.2.8)
|
50
50
|
minitest (5.11.3)
|
@@ -62,7 +62,7 @@ GEM
|
|
62
62
|
bcrypt-ruby (~> 3.0)
|
63
63
|
omniauth (~> 1.0)
|
64
64
|
pg (1.0.0)
|
65
|
-
proxes (0.9.
|
65
|
+
proxes (0.9.2)
|
66
66
|
activesupport (>= 3)
|
67
67
|
bcrypt (~> 3.1)
|
68
68
|
ditty (>= 0.2)
|
data/Gemfile.dev
CHANGED
@@ -3,9 +3,9 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify your gem's dependencies in proxes.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
+
gem 'dotenv'
|
7
|
+
gem 'pry-byebug'
|
8
|
+
gem 'puma'
|
6
9
|
gem 'rerun', git: 'https://github.com/alexch/rerun.git', branch: 'master'
|
7
|
-
gem 'sqlite3'
|
8
10
|
gem 'simplecov'
|
9
|
-
gem '
|
10
|
-
gem 'dotenv'
|
11
|
-
|
11
|
+
gem 'sqlite3'
|
data/config.ru
CHANGED
@@ -5,6 +5,8 @@ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
|
5
5
|
|
6
6
|
require 'dotenv/load'
|
7
7
|
|
8
|
+
require 'ditty/services/logger'
|
9
|
+
use Rack::CommonLogger, Ditty::Services::Logger.instance
|
8
10
|
# Session
|
9
11
|
use Rack::Session::Cookie,
|
10
12
|
key: '_ProxES_session',
|
@@ -53,11 +55,15 @@ end
|
|
53
55
|
|
54
56
|
map '/' do
|
55
57
|
# Proxy all Elasticsearch requests
|
56
|
-
require 'proxes/
|
58
|
+
require 'proxes/middleware/metrics'
|
59
|
+
require 'proxes/middleware/error_handling'
|
60
|
+
require 'proxes/middleware/security'
|
57
61
|
require 'proxes/forwarder'
|
58
62
|
|
59
63
|
# Security
|
60
|
-
use ProxES::
|
64
|
+
use ProxES::Middleware::Metrics
|
65
|
+
use ProxES::Middleware::ErrorHandling
|
66
|
+
use ProxES::Middleware::Security, Ditty::Services::Logger.instance unless ENV['PROXES_PASSTHROUGH']
|
61
67
|
use Rack::ContentLength
|
62
68
|
|
63
69
|
# Forward requests to ES
|
data/config/logger.yml
CHANGED
data/docker-compose.yml
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
version: '3'
|
2
2
|
services:
|
3
|
+
db:
|
4
|
+
image: postgres
|
5
|
+
es:
|
6
|
+
image: elasticsearch
|
3
7
|
web:
|
4
|
-
|
8
|
+
image: eagerelk/proxes:latest
|
5
9
|
command: web-proxes
|
6
10
|
ports:
|
7
11
|
- '9292:9292'
|
@@ -11,7 +15,3 @@ services:
|
|
11
15
|
depends_on:
|
12
16
|
- db
|
13
17
|
- es
|
14
|
-
db:
|
15
|
-
image: postgres
|
16
|
-
es:
|
17
|
-
image: elasticsearch
|
@@ -28,7 +28,7 @@ module ProxES
|
|
28
28
|
master_nodes = []
|
29
29
|
data_nodes = []
|
30
30
|
ingestion_nodes = []
|
31
|
-
node_stats['nodes'].
|
31
|
+
node_stats['nodes'].each_value do |node|
|
32
32
|
if node['roles']
|
33
33
|
master_nodes << node['name'] if node['roles'].include? 'master'
|
34
34
|
data_nodes << node['name'] if node['roles'].include? 'data'
|
@@ -61,7 +61,7 @@ module ProxES
|
|
61
61
|
|
62
62
|
jvm_values = []
|
63
63
|
jvm_passed = true
|
64
|
-
node_stats['nodes'].
|
64
|
+
node_stats['nodes'].each_value do |node|
|
65
65
|
jvm_values << "#{node['name']}: #{node['jvm']['mem']['heap_used_percent']}%"
|
66
66
|
jvm_passed = false if node['jvm']['mem']['heap_used_percent'] > 85
|
67
67
|
end
|
@@ -69,19 +69,19 @@ module ProxES
|
|
69
69
|
|
70
70
|
fs_values = []
|
71
71
|
fs_passed = true
|
72
|
-
node_stats['nodes'].
|
72
|
+
node_stats['nodes'].each_value do |node|
|
73
73
|
next if node['attributes'] && node['attributes']['data'] == 'false'
|
74
74
|
next if node['roles'] && node['roles'].include?('data') == false
|
75
75
|
stats = node['fs']['total']
|
76
76
|
left = stats['available_in_bytes'] / stats['total_in_bytes'].to_f * 100
|
77
|
-
fs_values << "#{node['name']}: #{'%.02f'
|
77
|
+
fs_values << "#{node['name']}: #{format('%.02f', left)}% Free"
|
78
78
|
fs_passed = false if left < 10
|
79
79
|
end
|
80
80
|
checks << { text: 'Node File Systems', passed: fs_passed, value: fs_values.sort }
|
81
81
|
|
82
82
|
cpu_values = []
|
83
83
|
cpu_passed = true
|
84
|
-
node_stats['nodes'].
|
84
|
+
node_stats['nodes'].each_value do |node|
|
85
85
|
value = (node['os']['cpu_percent'] || node['os']['cpu']['percent'])
|
86
86
|
cpu_values << "#{node['name']}: #{value}"
|
87
87
|
cpu_passed = false if value.to_i > 70
|
@@ -89,18 +89,27 @@ module ProxES
|
|
89
89
|
checks << { text: 'Node CPU Usage', passed: cpu_passed, value: cpu_values.sort }
|
90
90
|
|
91
91
|
memory_values = []
|
92
|
-
|
93
|
-
node_stats['nodes'].
|
92
|
+
memory_sum = 0
|
93
|
+
node_stats['nodes'].each_value do |node|
|
94
|
+
memory_sum += node['os']['mem']['used_percent']
|
94
95
|
memory_values << "#{node['name']}: #{node['os']['mem']['used_percent']}"
|
95
|
-
memory_passed = false if node['os']['mem']['used_percent'].to_i >= 100
|
96
96
|
end
|
97
|
+
memory_passed = (memory_sum / memory_values.size).to_i < 100
|
97
98
|
checks << { text: 'Node Memory Usage', passed: memory_passed, value: memory_values.sort }
|
98
99
|
rescue Faraday::Error => e
|
99
100
|
checks << { text: 'Cluster Reachable', passed: false, value: e.message }
|
100
101
|
end
|
101
102
|
|
102
103
|
status checks.find { |c| c[:passed] == false } ? 500 : 200
|
103
|
-
|
104
|
+
|
105
|
+
respond_to do |format|
|
106
|
+
format.html do
|
107
|
+
haml :'status/check', locals: { title: 'Status Check', checks: checks }
|
108
|
+
end
|
109
|
+
format.json do
|
110
|
+
json checks
|
111
|
+
end
|
112
|
+
end
|
104
113
|
end
|
105
114
|
end
|
106
115
|
end
|
data/lib/proxes/forwarder.rb
CHANGED
@@ -9,16 +9,6 @@ module ProxES
|
|
9
9
|
include Singleton
|
10
10
|
include ProxES::Services::ES
|
11
11
|
|
12
|
-
attr_reader :streaming
|
13
|
-
|
14
|
-
def backend
|
15
|
-
@backend ||= URI(ENV['ELASTICSEARCH_URL'])
|
16
|
-
end
|
17
|
-
|
18
|
-
def backend=(var)
|
19
|
-
@backend = URI(var)
|
20
|
-
end
|
21
|
-
|
22
12
|
def call(env)
|
23
13
|
forward(env)
|
24
14
|
rescue SocketError
|
@@ -28,7 +18,6 @@ module ProxES
|
|
28
18
|
|
29
19
|
def forward(env)
|
30
20
|
source = Rack::Request.new(env)
|
31
|
-
conn.basic_auth backend.user, backend.password
|
32
21
|
response = conn.send(source.request_method.downcase) do |req|
|
33
22
|
source_body = body_from(source)
|
34
23
|
req.body = source_body if source_body
|
@@ -1,10 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/core_ext/object/blank'
|
5
|
+
|
3
6
|
module ProxES
|
4
7
|
module Helpers
|
5
8
|
module Indices
|
6
9
|
def filter(asked, against)
|
7
|
-
return against.map { |a| a.gsub(/\.\*/, '*') } if asked == ['*'] || asked
|
10
|
+
return against.map { |a| a.gsub(/\.\*/, '*') } if asked == ['*'] || asked.blank?
|
8
11
|
|
9
12
|
answer = []
|
10
13
|
against.each do |pattern|
|
@@ -12,6 +15,19 @@ module ProxES
|
|
12
15
|
end
|
13
16
|
answer
|
14
17
|
end
|
18
|
+
|
19
|
+
def patterns
|
20
|
+
return [] if user.nil?
|
21
|
+
patterns_for('INDEX').map do |permission|
|
22
|
+
return nil if permission.pattern.blank?
|
23
|
+
permission.pattern.gsub(/\{user.(.*)\}/) { |_match| user.send(Regexp.last_match[1].to_sym) }
|
24
|
+
end.compact
|
25
|
+
end
|
26
|
+
|
27
|
+
def patterns_for(action)
|
28
|
+
return [] if user.nil?
|
29
|
+
Permission.for_user(user, action)
|
30
|
+
end
|
15
31
|
end
|
16
32
|
end
|
17
33
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ditty/helpers/wisper'
|
4
|
+
|
5
|
+
module ProxES
|
6
|
+
module Middleware
|
7
|
+
class ErrorHandling
|
8
|
+
attr_reader :logger
|
9
|
+
|
10
|
+
include Wisper::Publisher
|
11
|
+
include Ditty::Helpers::Wisper
|
12
|
+
|
13
|
+
def initialize(app, logger = nil)
|
14
|
+
@app = app
|
15
|
+
@logger = logger || ::Ditty::Services::Logger.instance
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(env)
|
19
|
+
request = Request.from_env(env)
|
20
|
+
code, headers, body = @app.call env
|
21
|
+
unless (200..299).cover? code
|
22
|
+
log_action(
|
23
|
+
:es_request_failed,
|
24
|
+
user: request.user,
|
25
|
+
details: "#{request.request_method.upcase} #{request.fullpath} (#{request.class.name})"
|
26
|
+
)
|
27
|
+
end
|
28
|
+
[code, headers, body]
|
29
|
+
rescue Errno::EHOSTUNREACH
|
30
|
+
error 'Could not reach Elasticsearch at ' + ENV['ELASTICSEARCH_URL']
|
31
|
+
rescue Errno::ECONNREFUSED, Faraday::ConnectionFailed
|
32
|
+
error 'Elasticsearch not listening at ' + ENV['ELASTICSEARCH_URL']
|
33
|
+
rescue Pundit::NotAuthorizedError, Ditty::Helpers::NotAuthenticated
|
34
|
+
if request.html? && request.user.nil?
|
35
|
+
env['rack.session']['omniauth.origin'] = request.url
|
36
|
+
return redirect '/_proxes/auth/identity'
|
37
|
+
end
|
38
|
+
|
39
|
+
user = request.user ? request.user.email : 'unauthenticated request'
|
40
|
+
logger.error "Access denied for #{user} by security layer: #{request.detail}"
|
41
|
+
|
42
|
+
failed request, 'Not Authorized', :es_request_denied, 401
|
43
|
+
rescue StandardError => e
|
44
|
+
raise e if env['RACK_ENV'] != 'production'
|
45
|
+
|
46
|
+
user = request.user ? request.user.email : 'unauthenticated request'
|
47
|
+
logger.error "Access denied for #{user} by security exception: #{request.detail}"
|
48
|
+
logger.error e
|
49
|
+
|
50
|
+
failed request, 'Forbidden', :es_request_denied, 403
|
51
|
+
end
|
52
|
+
|
53
|
+
def failed(request, message, action, code)
|
54
|
+
log_action(
|
55
|
+
action,
|
56
|
+
user: request.user,
|
57
|
+
details: "#{request.request_method.upcase} #{request.fullpath} (#{request.class.name})"
|
58
|
+
)
|
59
|
+
error message, code
|
60
|
+
end
|
61
|
+
|
62
|
+
# Response Helpers
|
63
|
+
def error(message, code = 500)
|
64
|
+
headers = { 'Content-Type' => 'application/json' }
|
65
|
+
headers['WWW-Authenticate'] = 'Basic realm="security"' if code == 401
|
66
|
+
[code, headers, ['{"error":"' + message + '"}']]
|
67
|
+
end
|
68
|
+
|
69
|
+
def redirect(destination, code = 302)
|
70
|
+
[code, { 'Location' => destination }, []]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'wisper'
|
4
|
+
|
5
|
+
module ProxES
|
6
|
+
module Middleware
|
7
|
+
class Metrics
|
8
|
+
include Wisper::Publisher
|
9
|
+
|
10
|
+
def initialize(app)
|
11
|
+
@app = app
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
request = Request.from_env(env)
|
16
|
+
broadcast(:call_started, request)
|
17
|
+
|
18
|
+
result = @app.call request.env
|
19
|
+
|
20
|
+
broadcast(:call_completed, request) if result[0].to_i >= 200 && result[0].to_i < 300
|
21
|
+
result
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'proxes/request'
|
4
|
+
require 'proxes/policies/request_policy'
|
5
|
+
require 'ditty/services/logger'
|
6
|
+
require 'ditty/helpers/pundit'
|
7
|
+
require 'ditty/helpers/authentication'
|
8
|
+
|
9
|
+
module ProxES
|
10
|
+
module Middleware
|
11
|
+
class Security
|
12
|
+
attr_reader :env, :logger
|
13
|
+
|
14
|
+
include Ditty::Helpers::Authentication
|
15
|
+
include Ditty::Helpers::Pundit
|
16
|
+
include Ditty::Helpers::Wisper
|
17
|
+
|
18
|
+
def initialize(app, logger = nil)
|
19
|
+
@app = app
|
20
|
+
@logger = logger || ::Ditty::Services::Logger.instance
|
21
|
+
end
|
22
|
+
|
23
|
+
def call(env)
|
24
|
+
@env = env
|
25
|
+
request = ProxES::Request.from_env(env)
|
26
|
+
log(request, 'BEFORE')
|
27
|
+
|
28
|
+
check_basic request
|
29
|
+
authorize request
|
30
|
+
|
31
|
+
request.index = policy_scope(request) if request.indices?
|
32
|
+
log(request, 'AFTER')
|
33
|
+
|
34
|
+
@app.call env
|
35
|
+
end
|
36
|
+
|
37
|
+
def check_basic(request)
|
38
|
+
auth = Rack::Auth::Basic::Request.new(request.env)
|
39
|
+
return false unless auth.provided? && auth.basic?
|
40
|
+
|
41
|
+
identity = ::Ditty::Identity.find(username: auth.credentials[0])
|
42
|
+
identity ||= ::Ditty::Identity.find(username: CGI.unescape(auth.credentials[0]))
|
43
|
+
return false unless identity && identity.authenticate(auth.credentials[1])
|
44
|
+
request.env['rack.session'] ||= {}
|
45
|
+
request.env['rack.session']['user_id'] = identity.user_id
|
46
|
+
end
|
47
|
+
|
48
|
+
def authorize(request)
|
49
|
+
Pundit.authorize(request.user, request, request.request_method.downcase + '?')
|
50
|
+
end
|
51
|
+
|
52
|
+
def log(request, stage)
|
53
|
+
logger.debug '============' + stage.ljust(56) + '============'
|
54
|
+
logger.debug '= ' + "Request: #{request.detail}".ljust(76) + ' ='
|
55
|
+
logger.debug '= ' + "Endpoint: #{request.endpoint}".ljust(76) + ' ='
|
56
|
+
logger.debug '================================================================================'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|