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,59 @@
1
+ # frozen_string_literal: true
2
+ require 'rake'
3
+ require 'rake/tasklib'
4
+
5
+ module ProxES
6
+ class Tasks < ::Rake::TaskLib
7
+ include ::Rake::DSL if defined?(::Rake::DSL)
8
+
9
+ def install_tasks
10
+ namespace :proxes do
11
+ desc 'Generate the needed tokens'
12
+ task :generate_tokens do
13
+ require 'securerandom'
14
+ File.write('.session_secret', SecureRandom.random_bytes(40))
15
+ File.write('.token_secret', SecureRandom.random_bytes(40))
16
+ end
17
+
18
+ desc 'Seed the database'
19
+ task :seed do
20
+ require 'proxes/seed'
21
+ end
22
+
23
+ desc 'Migrate ProxES database to latest version'
24
+ task :migrate do
25
+ Rake::Task['proxes:migrate:up'].invoke
26
+ end
27
+
28
+ namespace :migrate do
29
+ require_relative './db'
30
+ Sequel.extension :migration
31
+ folder = File.expand_path(File.dirname(__FILE__) + '/../../migrate')
32
+
33
+ desc 'Check if the migration is current'
34
+ task :check do
35
+ Sequel::Migrator.check_current(DB, folder)
36
+ end
37
+
38
+ desc 'Migrate ProxES database to latest version'
39
+ task :up do
40
+ Sequel::Migrator.apply(DB, folder)
41
+ end
42
+
43
+ desc 'Roll back the ProxES database'
44
+ task :down do
45
+ Sequel::Migrator.apply(DB, folder, 0)
46
+ end
47
+
48
+ desc 'Reset the ProxES database'
49
+ task :bounce do
50
+ Sequel::Migrator.apply(DB, folder, 0)
51
+ Sequel::Migrator.apply(DB, folder)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ ProxES::Tasks.new.install_tasks
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+ require 'rack'
3
+
4
+ module ProxES
5
+ class Request < Rack::Request
6
+ def self.from_env(env)
7
+ request = Rack::Request.new(env)
8
+ splits = request.path.split('/')
9
+ endpoint = if splits[1] && splits[1][0] == '_'
10
+ splits[1][1..-1].titlecase
11
+ else
12
+ splits.count > 0 ? splits[-1][1..-1].titlecase : 'Root'
13
+ end
14
+ begin
15
+ require 'proxes/request/' + endpoint.downcase
16
+ ProxES::Request.const_get(endpoint).new(env)
17
+ rescue LoadError
18
+ self.new(env)
19
+ end
20
+ end
21
+
22
+ def initialize(env)
23
+ super
24
+ parse
25
+ end
26
+
27
+ def endpoint
28
+ path_parts[0]
29
+ end
30
+
31
+ def parse
32
+ path_parts
33
+ end
34
+
35
+ def indices?
36
+ false
37
+ end
38
+
39
+ private
40
+
41
+ def path_parts
42
+ @path_parts ||= path[1..-1].split('/')
43
+ end
44
+
45
+ def check_part(val)
46
+ return val if val.nil?
47
+ return [] if [endpoint, '_all'].include? val
48
+ val.split(',')
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ require 'rack'
3
+ require 'proxes/request'
4
+
5
+ module ProxES
6
+ class Request
7
+ class Root < ProxES::Request
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+ require 'rack'
3
+ require 'proxes/request'
4
+
5
+ module ProxES
6
+ class Request
7
+ class Search < ProxES::Request
8
+ attr_reader :index, :type
9
+ attr_reader :type
10
+
11
+ def index=(idx)
12
+ @index = idx
13
+ self.path_info = '/' + [ index, type, id, endpoint ]
14
+ .map { |v| v.is_a?(Array) ? v.join(',') : v }
15
+ .select { |v| !v.nil? && v != '' }.join('/')
16
+ end
17
+
18
+ def endpoint
19
+ '_search'
20
+ end
21
+
22
+ def parse
23
+ @index ||= check_part(path_parts[0])
24
+ @type ||= check_part(path_parts[1])
25
+ @id ||= check_part(path_parts[2])
26
+ end
27
+
28
+ def id
29
+ @id == [] ? nil : @id
30
+ end
31
+
32
+ def indices?
33
+ true
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ require 'rack'
3
+ require 'proxes/request'
4
+
5
+ module ProxES
6
+ class Request
7
+ class Snapshot < ProxES::Request
8
+ attr_reader :repository
9
+
10
+ def parse
11
+ @repository ||= check_part(path_parts[1])
12
+ @repository = [] if repository.nil?
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ require 'rack'
3
+ require 'proxes/request'
4
+
5
+ module ProxES
6
+ class Request
7
+ class Stats < ProxES::Request
8
+ attr_reader :index
9
+
10
+ def index=(idx)
11
+ @index = idx
12
+ self.path_info = '/' + [ index, endpoint ]
13
+ .map { |v| v.is_a?(Array) ? v.join(',') : v }
14
+ .select { |v| !v.nil? && v != '' }.join('/')
15
+ end
16
+
17
+ def endpoint
18
+ '_stats'
19
+ end
20
+
21
+ def parse
22
+ @index ||= check_part(path_parts[0])
23
+ end
24
+
25
+ def indices?
26
+ true
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+ require 'proxes/services/logger'
3
+ require 'rack-proxy'
4
+ require 'proxes/request'
5
+ require 'proxes/policies/request_policy'
6
+ require 'proxes/helpers/pundit'
7
+ require 'proxes/helpers/authentication'
8
+ require 'proxes/services/logger'
9
+
10
+ module ProxES
11
+ class Security
12
+ attr_reader :env, :logger
13
+
14
+ include ProxES::Helpers::Authentication
15
+ include ProxES::Helpers::Pundit
16
+
17
+ def initialize(app, logger = nil)
18
+ @app = app
19
+ @logger = logger || ProxES::Services::Logger.instance
20
+ end
21
+
22
+ def error(message, code = 500)
23
+ [code, { 'Content-Type' => 'application/json' }, ['{"error":"' + message + '}']]
24
+ end
25
+
26
+ def call(env)
27
+ @env = env
28
+
29
+ request = ProxES::Request.from_env(env)
30
+
31
+ logger.debug '==========================BEFORE================================================'
32
+ logger.debug '= ' + "Request: #{request.fullpath}".ljust(76) + ' ='
33
+ logger.debug '= ' + "Endpoint: #{request.endpoint}".ljust(76) + ' ='
34
+ logger.debug '================================================================================'
35
+
36
+ begin
37
+ check_basic
38
+ authorize request
39
+ rescue StandardError => e
40
+ logger.debug "Access denied by security layer: #{e.message}"
41
+ return error 'Forbidden', 403
42
+ end
43
+ request.index = policy_scope(request) if request.indices?
44
+
45
+ logger.debug '==========================AFTER================================================='
46
+ logger.debug '= ' + "Request: #{request.fullpath}".ljust(76) + ' ='
47
+ logger.debug '= ' + "Endpoint: #{request.endpoint}".ljust(76) + ' ='
48
+ logger.debug '================================================================================'
49
+
50
+ begin
51
+ @app.call request.env
52
+ rescue Errno::EHOSTUNREACH
53
+ error 'Could not reach Elasticsearch at ' + ENV['ELASTICSEARCH_URL']
54
+ rescue Errno::ECONNREFUSED
55
+ error 'Elasticsearch not listening at ' + ENV['ELASTICSEARCH_URL']
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,10 @@
1
+ require 'proxes/db'
2
+ require 'proxes/models/role'
3
+ require 'proxes/models/permission'
4
+
5
+ ProxES::Role.find_or_create(name: 'user')
6
+ ProxES::Role.find_or_create(name: 'admin')
7
+ sa = ProxES::Role.find_or_create(name: 'super_admin')
8
+ %w(GET POST PUT DELETE HEAD OPTIONS).each do |verb|
9
+ ProxES::Permission.find_or_create(role: sa, verb: verb, pattern: '.*')
10
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ require 'logger'
3
+ require 'yaml'
4
+ require 'singleton'
5
+ require 'active_support/inflector'
6
+ require 'proxes/loggers/elasticsearch'
7
+
8
+ # ProxES::Services::Logger.instance
9
+
10
+ module ProxES
11
+ module Services
12
+ class Logger
13
+ include Singleton
14
+
15
+ CONFIG = './config/logger.yml'
16
+ attr_reader :loggers
17
+
18
+ def initialize
19
+ @loggers = []
20
+ config.each do |values|
21
+ klass = values['class'].constantize
22
+ opts = values['options'] || nil
23
+ logger = klass.new(opts)
24
+ if values['level']
25
+ logger.level = klass.const_get(values['level'].to_sym)
26
+ end
27
+ @loggers << logger
28
+ end
29
+ end
30
+
31
+ def method_missing(method, *args, &block)
32
+ loggers.each { |logger| logger.send(method, *args, &block) }
33
+ end
34
+
35
+ def respond_to_missing?(method, include_private = false)
36
+ loggers.any? { |logger| logger.respond_to?(method) }
37
+ end
38
+
39
+ private
40
+
41
+ def config
42
+ @config ||= File.exist?(CONFIG) ? YAML.load_file(CONFIG) : default
43
+ end
44
+
45
+ def default
46
+ [{ 'name' => 'default', 'class' => 'Logger' }]
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ module ProxES
3
+ VERSION = '0.1.0'
4
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+ Sequel.migration do
3
+ change do
4
+ create_table :users do
5
+ primary_key :id
6
+ String :name
7
+ String :surname
8
+ String :email
9
+ DateTime :created_at
10
+ DateTime :updated_at
11
+ unique [:email]
12
+ end
13
+
14
+ create_table :identities do
15
+ primary_key :id
16
+ foreign_key :user_id, :users
17
+ String :username
18
+ String :crypted_password
19
+ DateTime :created_at
20
+ DateTime :updated_at
21
+ unique [:username]
22
+ end
23
+
24
+ create_table :roles do
25
+ primary_key :id
26
+ String :name
27
+ DateTime :created_at
28
+ DateTime :updated_at
29
+ unique [:name]
30
+ end
31
+
32
+ create_table :permissions do
33
+ primary_key :id
34
+ String :verb
35
+ String :pattern
36
+ DateTime :created_at
37
+ foreign_key :role_id, :roles
38
+ end
39
+
40
+ create_table :roles_users do
41
+ DateTime :created_at
42
+ foreign_key :user_id, :users
43
+ foreign_key :role_id, :roles
44
+ unique [:user_id, :role_id]
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ Sequel.migration do
3
+ change do
4
+ create_table :audit_logs do
5
+ primary_key :id
6
+ foreign_key :user_id, :users
7
+ String :action
8
+ DateTime :created_at
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "proxes",
3
+ "version": "0.1.0",
4
+ "description": "Elasticsearch Management System",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/EagerELK/proxes.git"
8
+ },
9
+ "author": "Jurgens du Toit",
10
+ "license": "LGPL-3.0",
11
+ "bugs": {
12
+ "url": "https://github.com/EagerELK/proxes/issues"
13
+ },
14
+ "homepage": "https://github.com/EagerELK/proxes#readme",
15
+ "dependencies": {
16
+ "body-parser": "^1.4.3",
17
+ "express": "^4.4.5",
18
+ "gulp-connect": "^5.0.0",
19
+ "jquery": "^3.1.0",
20
+ "numeral": "^1.5.3",
21
+ "react": "^15.2.1",
22
+ "react-dom": "^15.2.1",
23
+ "react-proxes-components": "^0.2.2"
24
+ },
25
+ "devDependencies": {
26
+ "babel-preset-es2015": "^6.9.0",
27
+ "babel-preset-react": "^6.11.1",
28
+ "babelify": "^7.3.0",
29
+ "browserify": "^13.1.0",
30
+ "gulp": "^3.9.1",
31
+ "gulp-util": "^3.0.7",
32
+ "vinyl-source-stream": "^1.1.0"
33
+ }
34
+ }
@@ -0,0 +1,44 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'proxes/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'proxes'
9
+ spec.version = ProxES::VERSION
10
+ spec.authors = ['Jurgens du Toit']
11
+ spec.email = ['jrgns@jadeit.co.za']
12
+
13
+ spec.summary = 'Rack wrapper around Elasticsearch to provide security and management features'
14
+ spec.description = 'Rack wrapper around Elasticsearch to provide security and management features'
15
+ spec.homepage = 'https://github.com/eagerelk/proxes'
16
+ spec.license = 'LGPLv3'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ spec.bindir = 'exe'
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.12'
24
+ spec.add_development_dependency 'rake', '~> 10.0'
25
+ spec.add_development_dependency 'rspec', '~> 3.0'
26
+ spec.add_development_dependency 'racksh'
27
+ spec.add_development_dependency 'rack-test'
28
+ spec.add_development_dependency 'database_cleaner'
29
+ spec.add_development_dependency 'factory_girl'
30
+
31
+ spec.add_dependency 'rack-proxy'
32
+ spec.add_dependency 'sinatra'
33
+ spec.add_dependency 'sinatra-flash'
34
+ spec.add_dependency 'sinatra-contrib'
35
+ spec.add_dependency 'elasticsearch'
36
+ spec.add_dependency 'logger'
37
+ spec.add_dependency 'pundit'
38
+ spec.add_dependency 'sequel'
39
+ spec.add_dependency 'bcrypt'
40
+ spec.add_dependency 'omniauth'
41
+ spec.add_dependency 'omniauth-identity'
42
+ spec.add_dependency 'haml'
43
+ spec.add_dependency 'tilt', '>= 2'
44
+ end