proxes 0.9.2 → 0.9.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|