proxes 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +24 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/.rubocop.yml +12 -0
- data/.ruby-version +1 -0
- data/.travis.yml +18 -0
- data/Gemfile +4 -0
- data/Gemfile.ci +15 -0
- data/Gemfile.dev +10 -0
- data/Gemfile.dev.lock +155 -0
- data/LICENSE.txt +8 -0
- data/README.md +83 -0
- data/Rakefile +9 -0
- data/Vagrantfile +46 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/config.ru +64 -0
- data/config/logger.yml +3 -0
- data/gulpfile.js +80 -0
- data/lib/proxes.rb +3 -0
- data/lib/proxes/app.rb +48 -0
- data/lib/proxes/controllers/application.rb +53 -0
- data/lib/proxes/controllers/audit_logs.rb +34 -0
- data/lib/proxes/controllers/auth_identity.rb +21 -0
- data/lib/proxes/controllers/component.rb +108 -0
- data/lib/proxes/controllers/permissions.rb +10 -0
- data/lib/proxes/controllers/roles.rb +10 -0
- data/lib/proxes/controllers/users.rb +119 -0
- data/lib/proxes/db.rb +17 -0
- data/lib/proxes/helpers/authentication.rb +45 -0
- data/lib/proxes/helpers/component.rb +40 -0
- data/lib/proxes/helpers/indices.rb +16 -0
- data/lib/proxes/helpers/pundit.rb +39 -0
- data/lib/proxes/helpers/views.rb +41 -0
- data/lib/proxes/loggers/elasticsearch.rb +9 -0
- data/lib/proxes/models/audit_log.rb +12 -0
- data/lib/proxes/models/identity.rb +67 -0
- data/lib/proxes/models/permission.rb +17 -0
- data/lib/proxes/models/role.rb +14 -0
- data/lib/proxes/models/user.rb +57 -0
- data/lib/proxes/policies/application_policy.rb +20 -0
- data/lib/proxes/policies/audit_log_policy.rb +40 -0
- data/lib/proxes/policies/identity_policy.rb +24 -0
- data/lib/proxes/policies/permission_policy.rb +40 -0
- data/lib/proxes/policies/request/root_policy.rb +12 -0
- data/lib/proxes/policies/request/search_policy.rb +15 -0
- data/lib/proxes/policies/request/snapshot_policy.rb +12 -0
- data/lib/proxes/policies/request/stats_policy.rb +15 -0
- data/lib/proxes/policies/request_policy.rb +69 -0
- data/lib/proxes/policies/role_policy.rb +40 -0
- data/lib/proxes/policies/token_policy.rb +46 -0
- data/lib/proxes/policies/user_policy.rb +46 -0
- data/lib/proxes/rake_tasks.rb +59 -0
- data/lib/proxes/request.rb +51 -0
- data/lib/proxes/request/root.rb +10 -0
- data/lib/proxes/request/search.rb +37 -0
- data/lib/proxes/request/snapshot.rb +16 -0
- data/lib/proxes/request/stats.rb +30 -0
- data/lib/proxes/security.rb +59 -0
- data/lib/proxes/seed.rb +10 -0
- data/lib/proxes/services/logger.rb +50 -0
- data/lib/proxes/version.rb +4 -0
- data/migrate/001_tables.rb +47 -0
- data/migrate/002_audit_log.rb +11 -0
- data/package.json +34 -0
- data/proxes.gemspec +44 -0
- data/public/js/bundle.js +28988 -0
- data/src/scripts/app.js +10 -0
- data/views/404.haml +1 -0
- data/views/audit_logs/index.haml +18 -0
- data/views/error.haml +4 -0
- data/views/getting_started.haml +16 -0
- data/views/identity/login.haml +19 -0
- data/views/identity/register.haml +17 -0
- data/views/index.haml +3 -0
- data/views/layout.haml +48 -0
- data/views/partials/delete_form.haml +4 -0
- data/views/partials/form_control.haml +21 -0
- data/views/partials/navbar.haml +25 -0
- data/views/partials/notifications.haml +24 -0
- data/views/partials/pager.haml +19 -0
- data/views/partials/sidebar.haml +32 -0
- data/views/permissions/display.haml +24 -0
- data/views/permissions/edit.haml +11 -0
- data/views/permissions/form.haml +3 -0
- data/views/permissions/index.haml +14 -0
- data/views/permissions/new.haml +10 -0
- data/views/roles/display.haml +33 -0
- data/views/roles/edit.haml +11 -0
- data/views/roles/form.haml +1 -0
- data/views/roles/index.haml +17 -0
- data/views/roles/new.haml +10 -0
- data/views/users/display.haml +32 -0
- data/views/users/edit.haml +11 -0
- data/views/users/identity.haml +3 -0
- data/views/users/index.haml +20 -0
- data/views/users/new.haml +11 -0
- data/views/users/profile.haml +37 -0
- data/views/users/user.haml +3 -0
- metadata +424 -0
data/bin/setup
ADDED
data/config.ru
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#\-o 0.0.0.0 -p 9294
|
3
|
+
libdir = File.expand_path(File.dirname(__FILE__) + '/lib')
|
4
|
+
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
5
|
+
|
6
|
+
raise 'Unconfigured' unless ENV['ELASTICSEARCH_URL']
|
7
|
+
|
8
|
+
require 'proxes'
|
9
|
+
require 'proxes/db'
|
10
|
+
|
11
|
+
Sequel.extension :migration
|
12
|
+
Sequel::Migrator.check_current(DB, './migrate')
|
13
|
+
|
14
|
+
use Rack::Static, urls: ['/css', '/js'], root: 'public'
|
15
|
+
use Rack::MethodOverride
|
16
|
+
use Rack::Session::Cookie,
|
17
|
+
key: '_ProxES_session',
|
18
|
+
#:secure=>!TEST_MODE, # Uncomment if only allowing https:// access
|
19
|
+
secret: File.read('.session_secret')
|
20
|
+
|
21
|
+
require 'omniauth'
|
22
|
+
require 'omniauth-identity'
|
23
|
+
require 'proxes/models/identity'
|
24
|
+
require 'proxes/controllers/auth_identity'
|
25
|
+
# OmniAuth.config.test_mode = true
|
26
|
+
use OmniAuth::Builder do
|
27
|
+
# The identity provider is used by the App.
|
28
|
+
provider :identity,
|
29
|
+
fields: [:username],
|
30
|
+
callback_path: '/_proxes/auth/identity/callback',
|
31
|
+
model: ProxES::Identity,
|
32
|
+
on_login: ProxES::AuthIdentity,
|
33
|
+
on_registration: ProxES::AuthIdentity,
|
34
|
+
locate_conditions: ->(req) { { username: req['username'] } }
|
35
|
+
end
|
36
|
+
OmniAuth.config.on_failure = ProxES::AuthIdentity
|
37
|
+
|
38
|
+
# Management App
|
39
|
+
Dir.glob("#{libdir}/proxes/controllers/*.rb").each { |file| require file }
|
40
|
+
|
41
|
+
map '/_proxes' do
|
42
|
+
{
|
43
|
+
'/users' => ProxES::Users,
|
44
|
+
'/roles' => ProxES::Roles,
|
45
|
+
'/permissions' => ProxES::Permissions,
|
46
|
+
'/audit-logs' => ProxES::AuditLogs,
|
47
|
+
}.each do |route, app|
|
48
|
+
map route do
|
49
|
+
run app
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
run ProxES::App
|
54
|
+
end
|
55
|
+
|
56
|
+
# Proxy all Elasticsearch requests
|
57
|
+
require 'proxes/security'
|
58
|
+
map '/' do
|
59
|
+
# Security
|
60
|
+
use ProxES::Security, ProxES::Services::Logger.instance
|
61
|
+
|
62
|
+
# Forward requests to ES
|
63
|
+
run Rack::Proxy.new(backend: ENV['ELASTICSEARCH_URL'])
|
64
|
+
end
|
data/config/logger.yml
ADDED
data/gulpfile.js
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
// From http://jpsierens.com/tutorial-gulp-javascript-2015-react/
|
2
|
+
var gulp = require('gulp');
|
3
|
+
var browserify = require('browserify');
|
4
|
+
var source = require('vinyl-source-stream');
|
5
|
+
var gutil = require('gulp-util');
|
6
|
+
var babelify = require('babelify');
|
7
|
+
var connect = require('gulp-connect');
|
8
|
+
|
9
|
+
// External dependencies you do not want to rebundle while developing,
|
10
|
+
// but include in your application deployment
|
11
|
+
var dependencies = [
|
12
|
+
// 'react',
|
13
|
+
// 'react-dom'
|
14
|
+
// 'react-proxes-components'
|
15
|
+
];
|
16
|
+
// keep a count of the times a task refires
|
17
|
+
var scriptsCount = 0;
|
18
|
+
|
19
|
+
// Gulp tasks
|
20
|
+
// ----------------------------------------------------------------------------
|
21
|
+
gulp.task('scripts', function () {
|
22
|
+
bundleApp(false);
|
23
|
+
});
|
24
|
+
|
25
|
+
gulp.task('deploy', function (){
|
26
|
+
bundleApp(true);
|
27
|
+
});
|
28
|
+
|
29
|
+
gulp.task('watch', function () {
|
30
|
+
gulp.watch(['./src/scripts/**/*.js'], ['scripts']);
|
31
|
+
});
|
32
|
+
|
33
|
+
// When running 'gulp' on the terminal this task will fire.
|
34
|
+
// It will start watching for changes in every .js file.
|
35
|
+
// If there's a change, the task 'scripts' defined above will fire.
|
36
|
+
gulp.task('default', ['scripts','watch']);
|
37
|
+
|
38
|
+
// Private Functions
|
39
|
+
// ----------------------------------------------------------------------------
|
40
|
+
function bundleApp(isProduction) {
|
41
|
+
scriptsCount++;
|
42
|
+
// Browserify will bundle all our js files together in to one and will let
|
43
|
+
// us use modules in the front end.
|
44
|
+
var appBundler = browserify({
|
45
|
+
entries: './src/scripts/app.js',
|
46
|
+
debug: true
|
47
|
+
});
|
48
|
+
|
49
|
+
// If it's not for production, a separate vendors.js file will be created
|
50
|
+
// the first time gulp is run so that we don't have to rebundle things like
|
51
|
+
// react everytime there's a change in the js file
|
52
|
+
if (!isProduction && scriptsCount === 1){
|
53
|
+
// create vendors.js for dev environment.
|
54
|
+
browserify({
|
55
|
+
require: dependencies,
|
56
|
+
debug: true
|
57
|
+
})
|
58
|
+
.bundle()
|
59
|
+
.on('error', gutil.log)
|
60
|
+
.pipe(source('vendors.js'))
|
61
|
+
.pipe(gulp.dest('./public/js/'));
|
62
|
+
}
|
63
|
+
if (!isProduction){
|
64
|
+
// make the dependencies external so they dont get bundled by the
|
65
|
+
// app bundler. Dependencies are already bundled in vendor.js for
|
66
|
+
// development environments.
|
67
|
+
dependencies.forEach(function(dep){
|
68
|
+
appBundler.external(dep);
|
69
|
+
})
|
70
|
+
}
|
71
|
+
|
72
|
+
|
73
|
+
appBundler
|
74
|
+
// transform ES6 and JSX to ES5 with babelify
|
75
|
+
.transform("babelify", {presets: ["es2015", "react"]})
|
76
|
+
.bundle()
|
77
|
+
.on('error',gutil.log)
|
78
|
+
.pipe(source('bundle.js'))
|
79
|
+
.pipe(gulp.dest('./public/js/'));
|
80
|
+
}
|
data/lib/proxes.rb
ADDED
data/lib/proxes/app.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'proxes/controllers/application'
|
3
|
+
|
4
|
+
module ProxES
|
5
|
+
# Manage your Elasticsearch cluster, user and user sessions
|
6
|
+
class App < Application
|
7
|
+
get '/' do
|
8
|
+
authenticate!
|
9
|
+
haml :index, locals: { title: 'Dashboard' }
|
10
|
+
end
|
11
|
+
|
12
|
+
['/unauthenticated', '/_proxes/unauthenticated'].each do |path|
|
13
|
+
get path do
|
14
|
+
redirect '/auth/identity'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
post '/auth/identity/new' do
|
19
|
+
identity = Identity.new(params['identity'])
|
20
|
+
if identity.valid? && identity.save
|
21
|
+
flash[:info] = 'Successfully Registered. Please log in'
|
22
|
+
redirect '/auth/identity'
|
23
|
+
else
|
24
|
+
flash.now[:warning] = 'Could not complete the registration. Please try again.'
|
25
|
+
haml :'identity/register', locals: { identity: identity }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
post '/auth/identity/callback' do
|
30
|
+
user = User.find_or_create(email: env['omniauth.auth']['info']['email'])
|
31
|
+
|
32
|
+
identity = Identity.find(username: user.email)
|
33
|
+
user.add_identity identity unless identity.user == user
|
34
|
+
|
35
|
+
self.current_user = user
|
36
|
+
flash[:success] = 'Logged In'
|
37
|
+
redirect '/_proxes'
|
38
|
+
end
|
39
|
+
|
40
|
+
delete '/auth/identity' do
|
41
|
+
logout
|
42
|
+
|
43
|
+
flash[:info] = 'Logged Out'
|
44
|
+
|
45
|
+
redirect '/_proxes'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'sinatra/base'
|
3
|
+
require 'sinatra/flash'
|
4
|
+
require 'sinatra/respond_with'
|
5
|
+
require 'proxes/helpers/views'
|
6
|
+
require 'proxes/helpers/pundit'
|
7
|
+
require 'proxes/helpers/authentication'
|
8
|
+
|
9
|
+
module ProxES
|
10
|
+
class Application < Sinatra::Base
|
11
|
+
set :root, ::File.expand_path(::File.dirname(__FILE__) + '/../../../')
|
12
|
+
register Sinatra::Flash, Sinatra::RespondWith
|
13
|
+
helpers ProxES::Helpers::Pundit, ProxES::Helpers::Views, ProxES::Helpers::Authentication
|
14
|
+
|
15
|
+
configure :production do
|
16
|
+
disable :show_exceptions
|
17
|
+
end
|
18
|
+
|
19
|
+
configure :development do
|
20
|
+
set :show_exceptions, :after_handler
|
21
|
+
end
|
22
|
+
|
23
|
+
configure :production, :development do
|
24
|
+
enable :logging
|
25
|
+
end
|
26
|
+
|
27
|
+
not_found do
|
28
|
+
haml :'404', locals: { title: '4 oh 4' }
|
29
|
+
end
|
30
|
+
|
31
|
+
error do
|
32
|
+
error = env['sinatra.error']
|
33
|
+
haml :error, locals: { title: 'Something went wrong', message: error }
|
34
|
+
end
|
35
|
+
|
36
|
+
error ::ProxES::Helpers::NotAuthenticated do
|
37
|
+
flash[:warning] = 'Please log in first.'
|
38
|
+
redirect '/auth/identity'
|
39
|
+
end
|
40
|
+
|
41
|
+
error ::Pundit::NotAuthorizedError do
|
42
|
+
flash[:warning] = 'Please log in first.'
|
43
|
+
redirect '/auth/identity'
|
44
|
+
end
|
45
|
+
|
46
|
+
before (/.*/) do
|
47
|
+
if request.url.match(/.json/)
|
48
|
+
request.accept.unshift('application/json')
|
49
|
+
request.path_info = request.path_info.gsub(/.json/,'')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'proxes/controllers/component'
|
3
|
+
require 'proxes/models/audit_log'
|
4
|
+
require 'proxes/policies/audit_log_policy'
|
5
|
+
|
6
|
+
module ProxES
|
7
|
+
class AuditLogs < Component
|
8
|
+
set model_class: ProxES::AuditLog
|
9
|
+
|
10
|
+
get '/new' do
|
11
|
+
halt 404
|
12
|
+
end
|
13
|
+
|
14
|
+
post '/' do
|
15
|
+
halt 404
|
16
|
+
end
|
17
|
+
|
18
|
+
get '/:id' do
|
19
|
+
halt 404
|
20
|
+
end
|
21
|
+
|
22
|
+
get '/:id/edit' do
|
23
|
+
halt 404
|
24
|
+
end
|
25
|
+
|
26
|
+
put '/:id' do
|
27
|
+
halt 404
|
28
|
+
end
|
29
|
+
|
30
|
+
delete '/:id' do
|
31
|
+
halt 404
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'proxes/controllers/application'
|
3
|
+
|
4
|
+
module ProxES
|
5
|
+
class AuthIdentity < Application
|
6
|
+
get '/auth/identity' do
|
7
|
+
haml :'identity/login', locals: { title: 'Log In' }
|
8
|
+
end
|
9
|
+
|
10
|
+
# Failed Login
|
11
|
+
post '/_proxes/auth/identity/callback' do
|
12
|
+
flash[:warning] = 'Invalid credentials. Please try again.'
|
13
|
+
redirect '/auth/identity'
|
14
|
+
end
|
15
|
+
|
16
|
+
get '/auth/identity/register' do
|
17
|
+
identity = Identity.new
|
18
|
+
haml :'identity/register', locals: { title: 'Register', identity: identity }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'proxes/controllers/application'
|
3
|
+
require 'proxes/helpers/component'
|
4
|
+
|
5
|
+
module ProxES
|
6
|
+
class Component < Application
|
7
|
+
helpers ProxES::Helpers::Component
|
8
|
+
set base_path: nil
|
9
|
+
set view_location: nil
|
10
|
+
|
11
|
+
# List
|
12
|
+
get '/', provides: [:html, :json] do
|
13
|
+
authorize settings.model_class, :list
|
14
|
+
|
15
|
+
actions = {}
|
16
|
+
actions["#{base_path}/new"] = "New #{heading}" if policy(settings.model_class).create?
|
17
|
+
|
18
|
+
respond_to do |format|
|
19
|
+
format.html do
|
20
|
+
haml :"#{view_location}/index",
|
21
|
+
locals: { list: list, title: heading(:list), actions: actions }
|
22
|
+
end
|
23
|
+
format.json do
|
24
|
+
{
|
25
|
+
'items' => list.map { |entity| entity.values },
|
26
|
+
'page' => params[:page],
|
27
|
+
'count' => params[:count],
|
28
|
+
'total' => list.to_a.size
|
29
|
+
}.to_json
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Create Form
|
35
|
+
get '/new' do
|
36
|
+
authorize settings.model_class, :create
|
37
|
+
|
38
|
+
entity = settings.model_class.new(permitted_attributes(settings.model_class, :create))
|
39
|
+
haml :"#{view_location}/new", locals: { entity: entity, title: heading(:new) }
|
40
|
+
end
|
41
|
+
|
42
|
+
# Create
|
43
|
+
post '/' do
|
44
|
+
authorize settings.model_class, :create
|
45
|
+
|
46
|
+
entity = settings.model_class.new(permitted_attributes(settings.model_class, :create))
|
47
|
+
if entity.valid? && entity.save
|
48
|
+
flash[:success] = "#{heading} Created"
|
49
|
+
redirect "#{base_path}/#{entity.id}"
|
50
|
+
else
|
51
|
+
haml :"#{view_location}/new", locals: { entity: entity, title: heading(:new) }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Read
|
56
|
+
get '/:id' do |id|
|
57
|
+
entity = dataset[id.to_i]
|
58
|
+
halt 404 unless entity
|
59
|
+
authorize entity, :read
|
60
|
+
|
61
|
+
actions = {}
|
62
|
+
actions["#{base_path}/#{entity.id}/edit"] = "Edit #{heading}" if policy(entity).update?
|
63
|
+
|
64
|
+
respond_to do |format|
|
65
|
+
format.html do
|
66
|
+
haml :"#{view_location}/display",
|
67
|
+
locals: { entity: entity, title: heading, actions: actions }
|
68
|
+
end
|
69
|
+
format.json { entity.values.to_json }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Update Form
|
74
|
+
get '/:id/edit' do |id|
|
75
|
+
entity = dataset[id.to_i]
|
76
|
+
halt 404 unless entity
|
77
|
+
authorize entity, :update
|
78
|
+
|
79
|
+
haml :"#{view_location}/edit", locals: { entity: entity, title: heading(:edit) }
|
80
|
+
end
|
81
|
+
|
82
|
+
# Update
|
83
|
+
put '/:id' do |id|
|
84
|
+
entity = dataset[id.to_i]
|
85
|
+
halt 404 unless entity
|
86
|
+
authorize entity, :update
|
87
|
+
|
88
|
+
entity.set(permitted_attributes(settings.model_class, :update))
|
89
|
+
if entity.valid? && entity.save
|
90
|
+
flash[:success] = "#{heading} Updated"
|
91
|
+
redirect "#{base_path}/#{entity.id}"
|
92
|
+
else
|
93
|
+
haml :"#{view_location}/edit", locals: { entity: entity, title: heading(:edit) }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
delete '/:id' do |id|
|
98
|
+
entity = dataset[id.to_i]
|
99
|
+
halt 404 unless entity
|
100
|
+
authorize entity, :delete
|
101
|
+
|
102
|
+
entity.destroy
|
103
|
+
|
104
|
+
flash[:success] = "#{heading} Deleted"
|
105
|
+
redirect base_path.to_s
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|