proxes 0.1.0

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.
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