proxes 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +24 -0
  3. data/.gitignore +13 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +12 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +18 -0
  8. data/Gemfile +4 -0
  9. data/Gemfile.ci +15 -0
  10. data/Gemfile.dev +10 -0
  11. data/Gemfile.dev.lock +155 -0
  12. data/LICENSE.txt +8 -0
  13. data/README.md +83 -0
  14. data/Rakefile +9 -0
  15. data/Vagrantfile +46 -0
  16. data/bin/console +15 -0
  17. data/bin/setup +8 -0
  18. data/config.ru +64 -0
  19. data/config/logger.yml +3 -0
  20. data/gulpfile.js +80 -0
  21. data/lib/proxes.rb +3 -0
  22. data/lib/proxes/app.rb +48 -0
  23. data/lib/proxes/controllers/application.rb +53 -0
  24. data/lib/proxes/controllers/audit_logs.rb +34 -0
  25. data/lib/proxes/controllers/auth_identity.rb +21 -0
  26. data/lib/proxes/controllers/component.rb +108 -0
  27. data/lib/proxes/controllers/permissions.rb +10 -0
  28. data/lib/proxes/controllers/roles.rb +10 -0
  29. data/lib/proxes/controllers/users.rb +119 -0
  30. data/lib/proxes/db.rb +17 -0
  31. data/lib/proxes/helpers/authentication.rb +45 -0
  32. data/lib/proxes/helpers/component.rb +40 -0
  33. data/lib/proxes/helpers/indices.rb +16 -0
  34. data/lib/proxes/helpers/pundit.rb +39 -0
  35. data/lib/proxes/helpers/views.rb +41 -0
  36. data/lib/proxes/loggers/elasticsearch.rb +9 -0
  37. data/lib/proxes/models/audit_log.rb +12 -0
  38. data/lib/proxes/models/identity.rb +67 -0
  39. data/lib/proxes/models/permission.rb +17 -0
  40. data/lib/proxes/models/role.rb +14 -0
  41. data/lib/proxes/models/user.rb +57 -0
  42. data/lib/proxes/policies/application_policy.rb +20 -0
  43. data/lib/proxes/policies/audit_log_policy.rb +40 -0
  44. data/lib/proxes/policies/identity_policy.rb +24 -0
  45. data/lib/proxes/policies/permission_policy.rb +40 -0
  46. data/lib/proxes/policies/request/root_policy.rb +12 -0
  47. data/lib/proxes/policies/request/search_policy.rb +15 -0
  48. data/lib/proxes/policies/request/snapshot_policy.rb +12 -0
  49. data/lib/proxes/policies/request/stats_policy.rb +15 -0
  50. data/lib/proxes/policies/request_policy.rb +69 -0
  51. data/lib/proxes/policies/role_policy.rb +40 -0
  52. data/lib/proxes/policies/token_policy.rb +46 -0
  53. data/lib/proxes/policies/user_policy.rb +46 -0
  54. data/lib/proxes/rake_tasks.rb +59 -0
  55. data/lib/proxes/request.rb +51 -0
  56. data/lib/proxes/request/root.rb +10 -0
  57. data/lib/proxes/request/search.rb +37 -0
  58. data/lib/proxes/request/snapshot.rb +16 -0
  59. data/lib/proxes/request/stats.rb +30 -0
  60. data/lib/proxes/security.rb +59 -0
  61. data/lib/proxes/seed.rb +10 -0
  62. data/lib/proxes/services/logger.rb +50 -0
  63. data/lib/proxes/version.rb +4 -0
  64. data/migrate/001_tables.rb +47 -0
  65. data/migrate/002_audit_log.rb +11 -0
  66. data/package.json +34 -0
  67. data/proxes.gemspec +44 -0
  68. data/public/js/bundle.js +28988 -0
  69. data/src/scripts/app.js +10 -0
  70. data/views/404.haml +1 -0
  71. data/views/audit_logs/index.haml +18 -0
  72. data/views/error.haml +4 -0
  73. data/views/getting_started.haml +16 -0
  74. data/views/identity/login.haml +19 -0
  75. data/views/identity/register.haml +17 -0
  76. data/views/index.haml +3 -0
  77. data/views/layout.haml +48 -0
  78. data/views/partials/delete_form.haml +4 -0
  79. data/views/partials/form_control.haml +21 -0
  80. data/views/partials/navbar.haml +25 -0
  81. data/views/partials/notifications.haml +24 -0
  82. data/views/partials/pager.haml +19 -0
  83. data/views/partials/sidebar.haml +32 -0
  84. data/views/permissions/display.haml +24 -0
  85. data/views/permissions/edit.haml +11 -0
  86. data/views/permissions/form.haml +3 -0
  87. data/views/permissions/index.haml +14 -0
  88. data/views/permissions/new.haml +10 -0
  89. data/views/roles/display.haml +33 -0
  90. data/views/roles/edit.haml +11 -0
  91. data/views/roles/form.haml +1 -0
  92. data/views/roles/index.haml +17 -0
  93. data/views/roles/new.haml +10 -0
  94. data/views/users/display.haml +32 -0
  95. data/views/users/edit.haml +11 -0
  96. data/views/users/identity.haml +3 -0
  97. data/views/users/index.haml +20 -0
  98. data/views/users/new.haml +11 -0
  99. data/views/users/profile.haml +37 -0
  100. data/views/users/user.haml +3 -0
  101. metadata +424 -0
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -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
@@ -0,0 +1,3 @@
1
+ ---
2
+ - name: default
3
+ class: Logger
@@ -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
+ }
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+ require 'proxes/version'
3
+ require 'proxes/app'
@@ -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
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ require 'proxes/controllers/component'
3
+ require 'proxes/models/permission'
4
+ require 'proxes/policies/permission_policy'
5
+
6
+ module ProxES
7
+ class Permissions < Component
8
+ set model_class: ProxES::Permission
9
+ end
10
+ end