proxes 0.9.4 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/Dockerfile +2 -2
- data/Gemfile.deploy +1 -0
- data/Gemfile.deploy.lock +46 -28
- data/Gemfile.dev +3 -1
- data/config/settings.yml +7 -0
- data/docker-compose.yml +6 -3
- data/lib/ditty/components/proxes.rb +3 -0
- data/lib/proxes/controllers/search.rb +45 -0
- data/lib/proxes/controllers/status.rb +1 -1
- data/lib/proxes/forwarder.rb +0 -7
- data/lib/proxes/middleware/error_handling.rb +25 -37
- data/lib/proxes/middleware/security.rb +0 -1
- data/lib/proxes/models/permission.rb +18 -2
- data/lib/proxes/policies/request_policy.rb +1 -1
- data/lib/proxes/request/stats.rb +4 -0
- data/lib/proxes/services/es.rb +0 -4
- data/lib/proxes/services/listener.rb +29 -0
- data/lib/proxes/services/search.rb +43 -0
- data/lib/proxes/version.rb +1 -1
- data/package.json +1 -1
- data/proxes.gemspec +3 -3
- data/public/css/typeahead.css +94 -0
- data/public/js/bundle.js +34695 -21264
- data/public/js/typeahead.bundle.min.js +8 -0
- data/src/scripts/app.js +8 -7
- data/views/search/index.haml +95 -0
- metadata +22 -16
- data/config/logger.yml +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ef233fd8fd3cf4118e820483e703279eac3921ae2c92dee336f802c0c6f5df2
|
4
|
+
data.tar.gz: 8e7fb52b8b0e152de449d490545d96944502cce8db7491878d90e9042b572c1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4301310adb06293c72b22595985959883c46a316a702995074d5f74b30535c54541ab185725f20edc2b8ba54dcd19d31076bac1e3427b78ae93f0f701b8bd371
|
7
|
+
data.tar.gz: a40f54478277272699c56a5067dd4cf13c8f59feebed6e6cc8d98ec06678e030b6ef1a683c4f3c676f74e7613afb04b8d1e3a8b4bf9d604015d096c58f0014e6
|
data/.gitignore
CHANGED
data/Dockerfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
FROM ruby:2.4-
|
1
|
+
FROM ruby:2.4-alpine3.4
|
2
2
|
MAINTAINER Jurgens du Toit <jurgens@datatools.io>
|
3
3
|
|
4
4
|
EXPOSE 9292
|
@@ -25,7 +25,7 @@ RUN apk add --update \
|
|
25
25
|
|
26
26
|
ADD views /usr/src/app/views
|
27
27
|
COPY config.ru /usr/src/app/
|
28
|
-
COPY config/
|
28
|
+
COPY config/settings.yml /usr/src/app/config/
|
29
29
|
COPY config/puma.rb /usr/src/app/config/
|
30
30
|
COPY Gemfile.deploy /usr/src/app/Gemfile
|
31
31
|
COPY Gemfile.deploy.lock /usr/src/app/Gemfile.lock
|
data/Gemfile.deploy
CHANGED
data/Gemfile.deploy.lock
CHANGED
@@ -1,58 +1,70 @@
|
|
1
1
|
GEM
|
2
2
|
remote: https://rubygems.org/
|
3
3
|
specs:
|
4
|
-
activesupport (5.
|
4
|
+
activesupport (5.2.0)
|
5
5
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
6
|
-
i18n (
|
6
|
+
i18n (>= 0.7, < 2)
|
7
7
|
minitest (~> 5.1)
|
8
8
|
tzinfo (~> 1.1)
|
9
|
-
|
10
|
-
|
9
|
+
ansi (1.5.0)
|
10
|
+
ast (2.4.0)
|
11
|
+
backports (3.11.3)
|
12
|
+
bcrypt (3.1.12)
|
11
13
|
bcrypt-ruby (3.1.5)
|
12
14
|
bcrypt (>= 3.1.3)
|
13
15
|
concurrent-ruby (1.0.5)
|
14
|
-
connection_pool (2.2.
|
15
|
-
ditty (0.
|
16
|
+
connection_pool (2.2.2)
|
17
|
+
ditty (0.6.0)
|
16
18
|
activesupport (>= 3)
|
17
19
|
bcrypt (~> 3.1)
|
18
20
|
haml (~> 5.0)
|
19
21
|
logger (~> 1.0)
|
22
|
+
mail (>= 1.7)
|
23
|
+
oga (>= 2.14)
|
20
24
|
omniauth (~> 1.0)
|
21
25
|
omniauth-identity (~> 1.0)
|
22
26
|
pundit (~> 1.0)
|
23
27
|
rack-contrib (~> 1.0)
|
24
28
|
rake (~> 12.0)
|
25
|
-
sequel (
|
26
|
-
sinatra (
|
29
|
+
sequel (>= 4.0)
|
30
|
+
sinatra (>= 2.0)
|
27
31
|
sinatra-contrib (~> 2.0)
|
28
32
|
sinatra-flash (~> 0.3)
|
33
|
+
thor (>= 0.20)
|
29
34
|
tilt (>= 2)
|
35
|
+
will_paginate (>= 3.1)
|
30
36
|
wisper (~> 2.0)
|
31
|
-
dotenv (2.
|
32
|
-
elasticsearch (6.0
|
33
|
-
elasticsearch-api (= 6.0
|
34
|
-
elasticsearch-transport (= 6.0
|
35
|
-
elasticsearch-api (6.0
|
37
|
+
dotenv (2.5.0)
|
38
|
+
elasticsearch (6.1.0)
|
39
|
+
elasticsearch-api (= 6.1.0)
|
40
|
+
elasticsearch-transport (= 6.1.0)
|
41
|
+
elasticsearch-api (6.1.0)
|
36
42
|
multi_json
|
37
|
-
elasticsearch-transport (6.0
|
43
|
+
elasticsearch-transport (6.1.0)
|
38
44
|
faraday
|
39
45
|
multi_json
|
40
|
-
faraday (0.
|
46
|
+
faraday (0.15.2)
|
41
47
|
multipart-post (>= 1.2, < 3)
|
42
48
|
haml (5.0.4)
|
43
49
|
temple (>= 0.8.0)
|
44
50
|
tilt
|
45
51
|
hashie (3.5.7)
|
46
52
|
highline (1.7.10)
|
47
|
-
i18n (0.
|
53
|
+
i18n (1.0.1)
|
48
54
|
concurrent-ruby (~> 1.0)
|
49
55
|
logger (1.2.8)
|
56
|
+
mail (2.7.0)
|
57
|
+
mini_mime (>= 0.1.1)
|
58
|
+
mini_mime (1.0.0)
|
50
59
|
minitest (5.11.3)
|
51
60
|
multi_json (1.13.1)
|
52
61
|
multipart-post (2.0.0)
|
53
|
-
mustermann (1.0.
|
62
|
+
mustermann (1.0.2)
|
54
63
|
net-http-persistent (3.0.0)
|
55
64
|
connection_pool (~> 2.2)
|
65
|
+
oga (2.15)
|
66
|
+
ast
|
67
|
+
ruby-ll (~> 2.1)
|
56
68
|
omniauth (1.8.1)
|
57
69
|
hashie (>= 3.4.6, < 3.6.0)
|
58
70
|
rack (>= 1.6.2, < 3)
|
@@ -62,7 +74,7 @@ GEM
|
|
62
74
|
bcrypt-ruby (~> 3.0)
|
63
75
|
omniauth (~> 1.0)
|
64
76
|
pg (1.0.0)
|
65
|
-
proxes (0.9.
|
77
|
+
proxes (0.9.4)
|
66
78
|
activesupport (>= 3)
|
67
79
|
bcrypt (~> 3.1)
|
68
80
|
ditty (>= 0.2)
|
@@ -84,35 +96,41 @@ GEM
|
|
84
96
|
sinatra-flash (~> 0.3)
|
85
97
|
tilt (>= 2)
|
86
98
|
wisper (~> 2.0)
|
87
|
-
puma (3.
|
99
|
+
puma (3.12.0)
|
88
100
|
pundit (1.1.0)
|
89
101
|
activesupport (>= 3.0.0)
|
90
|
-
rack (2.0.
|
102
|
+
rack (2.0.5)
|
91
103
|
rack-contrib (1.2.0)
|
92
104
|
rack (>= 0.9.1)
|
93
|
-
rack-protection (2.0.
|
105
|
+
rack-protection (2.0.3)
|
94
106
|
rack
|
95
|
-
rake (12.3.
|
107
|
+
rake (12.3.1)
|
108
|
+
ruby-ll (2.1.2)
|
109
|
+
ansi
|
110
|
+
ast
|
96
111
|
sequel (4.49.0)
|
97
|
-
sinatra (2.0.
|
112
|
+
sinatra (2.0.3)
|
98
113
|
mustermann (~> 1.0)
|
99
114
|
rack (~> 2.0)
|
100
|
-
rack-protection (= 2.0.
|
115
|
+
rack-protection (= 2.0.3)
|
101
116
|
tilt (~> 2.0)
|
102
|
-
sinatra-contrib (2.0.
|
103
|
-
|
117
|
+
sinatra-contrib (2.0.3)
|
118
|
+
activesupport (>= 4.0.0)
|
119
|
+
backports (>= 2.8.2)
|
104
120
|
multi_json
|
105
121
|
mustermann (~> 1.0)
|
106
|
-
rack-protection (= 2.0.
|
107
|
-
sinatra (= 2.0.
|
122
|
+
rack-protection (= 2.0.3)
|
123
|
+
sinatra (= 2.0.3)
|
108
124
|
tilt (>= 1.3, < 3)
|
109
125
|
sinatra-flash (0.3.0)
|
110
126
|
sinatra (>= 1.0.0)
|
111
127
|
temple (0.8.0)
|
128
|
+
thor (0.20.0)
|
112
129
|
thread_safe (0.3.6)
|
113
130
|
tilt (2.0.8)
|
114
131
|
tzinfo (1.2.5)
|
115
132
|
thread_safe (~> 0.1)
|
133
|
+
will_paginate (3.1.6)
|
116
134
|
wisper (2.0.0)
|
117
135
|
|
118
136
|
PLATFORMS
|
data/Gemfile.dev
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
source 'https://rubygems.org'
|
2
3
|
|
3
4
|
# Specify your gem's dependencies in proxes.gemspec
|
4
5
|
gemspec
|
5
6
|
|
7
|
+
gem 'ditty', path: '../ditty'
|
6
8
|
gem 'dotenv'
|
7
9
|
gem 'pry-byebug'
|
8
10
|
gem 'puma'
|
9
11
|
gem 'rerun', git: 'https://github.com/alexch/rerun.git', branch: 'master'
|
10
12
|
gem 'simplecov'
|
11
|
-
gem '
|
13
|
+
gem 'pg'
|
data/config/settings.yml
ADDED
data/docker-compose.yml
CHANGED
@@ -2,16 +2,19 @@ version: '3'
|
|
2
2
|
services:
|
3
3
|
db:
|
4
4
|
image: postgres
|
5
|
-
|
5
|
+
container_name: postgres
|
6
|
+
elasticsearch:
|
6
7
|
image: elasticsearch
|
8
|
+
container_name: elasticsearch
|
7
9
|
web:
|
8
10
|
image: eagerelk/proxes:latest
|
11
|
+
container_name: web-proxes
|
9
12
|
command: web-proxes
|
10
13
|
ports:
|
11
14
|
- '9292:9292'
|
12
15
|
environment:
|
13
16
|
- DATABASE_URL=postgres://postgres:@db/postgres
|
14
|
-
- ELASTICSEARCH_URL=http://
|
17
|
+
- ELASTICSEARCH_URL=http://elasticsearch:9200
|
15
18
|
depends_on:
|
16
19
|
- db
|
17
|
-
-
|
20
|
+
- elasticsearch
|
@@ -8,6 +8,7 @@ module Ditty
|
|
8
8
|
controllers = File.expand_path('../../../proxes/controllers', __FILE__)
|
9
9
|
Dir.glob("#{controllers}/*.rb").each { |f| require f }
|
10
10
|
require 'proxes/models/permission'
|
11
|
+
require 'proxes/services/listener'
|
11
12
|
end
|
12
13
|
|
13
14
|
def self.migrations
|
@@ -25,6 +26,7 @@ module Ditty
|
|
25
26
|
def self.routes
|
26
27
|
load
|
27
28
|
{
|
29
|
+
'/search' => ::ProxES::Search,
|
28
30
|
'/status' => ::ProxES::Status,
|
29
31
|
'/permissions' => ::ProxES::Permissions
|
30
32
|
}
|
@@ -34,6 +36,7 @@ module Ditty
|
|
34
36
|
load
|
35
37
|
[
|
36
38
|
{ order: 0, link: '/status/check', text: 'Status Check', target: ::ProxES::Status, icon: 'dashboard' },
|
39
|
+
{ order: 1, link: '/search', text: 'Search', target: ::ProxES::Status, icon: 'search' },
|
37
40
|
{ order: 15, link: '/permissions/', text: 'Permissions', target: ::ProxES::Permission, icon: 'check-square' }
|
38
41
|
]
|
39
42
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/object/blank'
|
4
|
+
require 'ditty/controllers/application'
|
5
|
+
require 'proxes/services/search'
|
6
|
+
|
7
|
+
module ProxES
|
8
|
+
class Search < Ditty::Application
|
9
|
+
set base_path: "#{settings.map_path}/search"
|
10
|
+
|
11
|
+
get '/' do
|
12
|
+
page = (params['page'] || 1).to_i
|
13
|
+
size = (params['count'] || 25).to_i
|
14
|
+
from = ((page - 1) * size)
|
15
|
+
params['q'] = '*' if params['q'].blank?
|
16
|
+
result = ProxES::Services::Search.search(params['q'], index: params['indices'], from: from, size: size)
|
17
|
+
haml :"#{view_location}/index",
|
18
|
+
locals: {
|
19
|
+
title: 'Search',
|
20
|
+
indices: ProxES::Services::Search.indices,
|
21
|
+
fields: ProxES::Services::Search.fields(params['indices']),
|
22
|
+
result: result
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
get '/fields/?:indices?/?' do
|
27
|
+
json ProxES::Services::Search.fields params['indices']
|
28
|
+
end
|
29
|
+
|
30
|
+
get '/indices/?' do
|
31
|
+
json ProxES::Services::Search.indices
|
32
|
+
end
|
33
|
+
|
34
|
+
get '/values/:field/?:indices?/?' do |field|
|
35
|
+
size = params['size'] || 25
|
36
|
+
json ProxES::Services::Search.values(field, size: size, index: params['indices'])
|
37
|
+
end
|
38
|
+
|
39
|
+
def find_template(views, name, engine, &block)
|
40
|
+
super(views, name, engine, &block) # Root
|
41
|
+
super(::Ditty::ProxES.view_folder, name, engine, &block) # This Component
|
42
|
+
super(::Ditty::App.view_folder, name, engine, &block) # Ditty
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -19,7 +19,7 @@ module ProxES
|
|
19
19
|
get '/check' do
|
20
20
|
checks = []
|
21
21
|
begin
|
22
|
-
health =
|
22
|
+
health = client.cluster.health level: 'cluster'
|
23
23
|
checks << { text: 'Cluster Reachable', passed: true, value: health['cluster_name'] }
|
24
24
|
checks << { text: 'Cluster Health', passed: health['status'] == 'green', value: health['status'] }
|
25
25
|
|
data/lib/proxes/forwarder.rb
CHANGED
@@ -10,13 +10,6 @@ module ProxES
|
|
10
10
|
include ProxES::Services::ES
|
11
11
|
|
12
12
|
def call(env)
|
13
|
-
forward(env)
|
14
|
-
rescue SocketError
|
15
|
-
headers = { 'Content-Type' => 'application/json' }
|
16
|
-
[500, headers, ['{"error":"Could not connect to Elasticsearch"}']]
|
17
|
-
end
|
18
|
-
|
19
|
-
def forward(env)
|
20
13
|
source = Rack::Request.new(env)
|
21
14
|
response = conn.send(source.request_method.downcase) do |req|
|
22
15
|
source_body = body_from(source)
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'wisper'
|
4
|
+
require 'proxes/request'
|
5
|
+
require 'ditty/services/logger'
|
4
6
|
|
5
7
|
module ProxES
|
6
8
|
module Middleware
|
@@ -8,7 +10,6 @@ module ProxES
|
|
8
10
|
attr_reader :logger
|
9
11
|
|
10
12
|
include Wisper::Publisher
|
11
|
-
include Ditty::Helpers::Wisper
|
12
13
|
|
13
14
|
def initialize(app, logger = nil)
|
14
15
|
@app = app
|
@@ -16,47 +17,29 @@ module ProxES
|
|
16
17
|
end
|
17
18
|
|
18
19
|
def call(env)
|
19
|
-
request = Request.from_env(env)
|
20
|
-
|
21
|
-
unless (200..299).cover?
|
22
|
-
|
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]
|
20
|
+
request = ProxES::Request.from_env(env)
|
21
|
+
response = @app.call env
|
22
|
+
broadcast(:es_request_failed, request, response) unless (200..299).cover?(response[0])
|
23
|
+
response
|
29
24
|
rescue Errno::EHOSTUNREACH
|
30
25
|
error 'Could not reach Elasticsearch at ' + ENV['ELASTICSEARCH_URL']
|
31
|
-
rescue Errno::ECONNREFUSED, Faraday::ConnectionFailed
|
26
|
+
rescue Errno::ECONNREFUSED, Faraday::ConnectionFailed, SocketError
|
32
27
|
error 'Elasticsearch not listening at ' + ENV['ELASTICSEARCH_URL']
|
33
|
-
rescue Pundit::NotAuthorizedError, Ditty::Helpers::NotAuthenticated
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
28
|
+
rescue Pundit::NotAuthorizedError, Ditty::Helpers::NotAuthenticated => e
|
29
|
+
broadcast(:es_request_denied, request, e)
|
30
|
+
log_not_authorized request
|
31
|
+
raise e if env['APP_ENV'] == 'development'
|
32
|
+
request.html? && request.user.nil? ? login_and_redirect(request) : error('Not Authorized', 401)
|
43
33
|
rescue StandardError => e
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
logger.error e
|
49
|
-
|
50
|
-
failed request, 'Forbidden', :es_request_denied, 403
|
34
|
+
broadcast(:es_request_denied, request, e)
|
35
|
+
log_not_authorized request
|
36
|
+
raise e if env['APP_ENV'] == 'development'
|
37
|
+
error 'Forbidden', 403
|
51
38
|
end
|
52
39
|
|
53
|
-
def
|
54
|
-
|
55
|
-
|
56
|
-
user: request.user,
|
57
|
-
details: "#{request.request_method.upcase} #{request.fullpath} (#{request.class.name})"
|
58
|
-
)
|
59
|
-
error message, code
|
40
|
+
def log_not_authorized(request)
|
41
|
+
user = request.user ? request.user.email : 'unauthenticated request'
|
42
|
+
logger.error "Access denied for #{user} by security layer: #{request.detail}"
|
60
43
|
end
|
61
44
|
|
62
45
|
# Response Helpers
|
@@ -66,6 +49,11 @@ module ProxES
|
|
66
49
|
[code, headers, ['{"error":"' + message + '"}']]
|
67
50
|
end
|
68
51
|
|
52
|
+
def login_and_redirect(request)
|
53
|
+
request.session['omniauth.origin'] = request.url unless request.url == '/_proxes/auth/identity'
|
54
|
+
redirect '/_proxes/auth/identity'
|
55
|
+
end
|
56
|
+
|
69
57
|
def redirect(destination, code = 302)
|
70
58
|
[code, { 'Location' => destination }, []]
|
71
59
|
end
|
@@ -24,8 +24,18 @@ module ProxES
|
|
24
24
|
validates_includes self.class.verbs, :verb
|
25
25
|
end
|
26
26
|
|
27
|
-
|
28
|
-
|
27
|
+
class << self
|
28
|
+
def verbs
|
29
|
+
%w[GET POST PUT DELETE HEAD OPTIONS TRACE INDEX]
|
30
|
+
end
|
31
|
+
|
32
|
+
def from_audit_log(audit_log)
|
33
|
+
match = audit_log.details.match(/^(\w)+ (\S+)/)
|
34
|
+
{
|
35
|
+
verb: match[1],
|
36
|
+
path: match[2]
|
37
|
+
}
|
38
|
+
end
|
29
39
|
end
|
30
40
|
end
|
31
41
|
end
|
@@ -35,3 +45,9 @@ module Ditty
|
|
35
45
|
one_to_many :permissions, class: ::ProxES::Permission
|
36
46
|
end
|
37
47
|
end
|
48
|
+
|
49
|
+
module Ditty
|
50
|
+
class Role < ::Sequel::Model
|
51
|
+
one_to_many :permissions, class: ::ProxES::Permission
|
52
|
+
end
|
53
|
+
end
|