jungle_path 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +22 -0
- data/README.md +5 -0
- data/jungle_path.gemspec +43 -0
- data/lib/jungle_path/api/helpers/auth.rb +45 -0
- data/lib/jungle_path/api/helpers/auth_local_user.rb +284 -0
- data/lib/jungle_path/api/helpers/auth_old.rb +232 -0
- data/lib/jungle_path/api/helpers/data_cache.rb +20 -0
- data/lib/jungle_path/api/helpers/defaults.rb +83 -0
- data/lib/jungle_path/api/helpers/logging.rb +36 -0
- data/lib/jungle_path/api/helpers/query_filters.rb +15 -0
- data/lib/jungle_path/api/helpers/rescues.rb +15 -0
- data/lib/jungle_path/api/helpers/result.rb +16 -0
- data/lib/jungle_path/api/helpers/standard_apis.rb +280 -0
- data/lib/jungle_path/api/helpers.rb +16 -0
- data/lib/jungle_path/api/template.erb +35 -0
- data/lib/jungle_path/api.rb +5 -0
- data/lib/jungle_path/app/a.gitignore +1 -0
- data/lib/jungle_path/app/api/server_base.rb +95 -0
- data/lib/jungle_path/app/api/server_custom.rb +121 -0
- data/lib/jungle_path/app/api/server_gen.rb +11 -0
- data/lib/jungle_path/app/auth/authorization.rb +96 -0
- data/lib/jungle_path/app/config/a.gitignore +1 -0
- data/lib/jungle_path/app/config/config.rb +240 -0
- data/lib/jungle_path/app/config/override.rb +3 -0
- data/lib/jungle_path/app/config.ru +28 -0
- data/lib/jungle_path/app/logs/log_files_go_here +0 -0
- data/lib/jungle_path/app/run.sh +4 -0
- data/lib/jungle_path/app/schemas/schema.rb +21 -0
- data/lib/jungle_path/app/schemas/schema_all_in_one.rb +181 -0
- data/lib/jungle_path/app.rb +8 -0
- data/lib/jungle_path/authentication/auth_provider/default.rb +83 -0
- data/lib/jungle_path/authentication/auth_provider.rb +7 -0
- data/lib/jungle_path/authentication/data_provider/default.rb +144 -0
- data/lib/jungle_path/authentication/data_provider.rb +7 -0
- data/lib/jungle_path/authentication/helpers.rb +19 -0
- data/lib/jungle_path/authentication/identity.rb +30 -0
- data/lib/jungle_path/authentication/password_hash.rb +124 -0
- data/lib/jungle_path/authentication.rb +9 -0
- data/lib/jungle_path/authorization/filter.rb +106 -0
- data/lib/jungle_path/authorization/paths.rb +71 -0
- data/lib/jungle_path/authorization.rb +5 -0
- data/lib/jungle_path/cache.rb +36 -0
- data/lib/jungle_path/config.rb +65 -0
- data/lib/jungle_path/controller/authentication.rb +129 -0
- data/lib/jungle_path/controller/base.rb +193 -0
- data/lib/jungle_path/controller/helpers.rb +47 -0
- data/lib/jungle_path/controller/template.erb +14 -0
- data/lib/jungle_path/controller.rb +7 -0
- data/lib/jungle_path/db_access/import/db_dir.rb +74 -0
- data/lib/jungle_path/db_access/import/delete.rb +30 -0
- data/lib/jungle_path/db_access/import/insert.rb +168 -0
- data/lib/jungle_path/db_access/import/schema.rb +34 -0
- data/lib/jungle_path/db_access/import/select.rb +68 -0
- data/lib/jungle_path/db_access/import.rb +15 -0
- data/lib/jungle_path/db_access/io/chunked_file_reader.rb +62 -0
- data/lib/jungle_path/db_access/io/config.rb +19 -0
- data/lib/jungle_path/db_access/io/copy.rb +73 -0
- data/lib/jungle_path/db_access/io/db.rb +82 -0
- data/lib/jungle_path/db_access/io/delete.rb +23 -0
- data/lib/jungle_path/db_access/io/init_db.rb +39 -0
- data/lib/jungle_path/db_access/io/insert.rb +24 -0
- data/lib/jungle_path/db_access/io/schema.rb +21 -0
- data/lib/jungle_path/db_access/io/select.rb +44 -0
- data/lib/jungle_path/db_access/io/update.rb +36 -0
- data/lib/jungle_path/db_access/io.rb +104 -0
- data/lib/jungle_path/db_model/column.rb +186 -0
- data/lib/jungle_path/db_model/params.rb +60 -0
- data/lib/jungle_path/db_model/schema.rb +100 -0
- data/lib/jungle_path/db_model/string.rb +9 -0
- data/lib/jungle_path/db_model/table.rb +307 -0
- data/lib/jungle_path/db_model.rb +34 -0
- data/lib/jungle_path/exceptions.rb +10 -0
- data/lib/jungle_path/gen/api.rb +52 -0
- data/lib/jungle_path/gen/controller.rb +0 -0
- data/lib/jungle_path/gen/db.rb +0 -0
- data/lib/jungle_path/gen/schema.rb +47 -0
- data/lib/jungle_path/gen/schema_tree/filter.rb +33 -0
- data/lib/jungle_path/gen/schema_tree/match_columns.rb +54 -0
- data/lib/jungle_path/gen/schema_tree/match_table_data.rb +22 -0
- data/lib/jungle_path/gen/schema_tree/match_tables.rb +70 -0
- data/lib/jungle_path/gen/schema_tree/node.rb +39 -0
- data/lib/jungle_path/gen/schema_tree.rb +105 -0
- data/lib/jungle_path/gen.rb +9 -0
- data/lib/jungle_path/json/base.rb +29 -0
- data/lib/jungle_path/json/time.rb +8 -0
- data/lib/jungle_path/json.rb +6 -0
- data/lib/jungle_path/logging.rb +23 -0
- data/lib/jungle_path/query/alias_info.rb +16 -0
- data/lib/jungle_path/query/engine.rb +878 -0
- data/lib/jungle_path/query/entity.rb +141 -0
- data/lib/jungle_path/query/field.rb +28 -0
- data/lib/jungle_path/query/field_primary_key.rb +27 -0
- data/lib/jungle_path/query/filter.rb +34 -0
- data/lib/jungle_path/query/float_value.rb +16 -0
- data/lib/jungle_path/query/from.rb +33 -0
- data/lib/jungle_path/query/int_value.rb +16 -0
- data/lib/jungle_path/query/limit.rb +19 -0
- data/lib/jungle_path/query/nested_hash_sorter.rb +94 -0
- data/lib/jungle_path/query/operator.rb +17 -0
- data/lib/jungle_path/query/query.rb +23 -0
- data/lib/jungle_path/query/sort_field.rb +34 -0
- data/lib/jungle_path/query/sql_string.rb +145 -0
- data/lib/jungle_path/query/string_value.rb +16 -0
- data/lib/jungle_path/query.rb +19 -0
- data/lib/jungle_path/rack/basic_credentials.rb +70 -0
- data/lib/jungle_path/rack/json_body_parser.rb +41 -0
- data/lib/jungle_path/rack.rb +6 -0
- data/lib/jungle_path/schema/auth.rb +83 -0
- data/lib/jungle_path/schema/base.rb +6 -0
- data/lib/jungle_path/schema/db.rb +10 -0
- data/lib/jungle_path/schema/version.rb +19 -0
- data/lib/jungle_path/schema.rb +8 -0
- data/lib/jungle_path/sql/auth_local_user.rb +5 -0
- data/lib/jungle_path/sql/general.rb +10 -0
- data/lib/jungle_path/sql/helpers.rb +11 -0
- data/lib/jungle_path/sql/key.rb +107 -0
- data/lib/jungle_path/sql/query_filter.rb +5 -0
- data/lib/jungle_path/sql/role.rb +5 -0
- data/lib/jungle_path/sql/user.rb +35 -0
- data/lib/jungle_path/sql/user_role.rb +5 -0
- data/lib/jungle_path/sql.rb +12 -0
- data/lib/jungle_path.rb +13 -0
- data/test.rb +33 -0
- data/test2.rb +15 -0
- metadata +200 -0
@@ -0,0 +1,106 @@
|
|
1
|
+
module JunglePath
|
2
|
+
require 'jungle_path/gen/schema_tree/node'
|
3
|
+
module Authorization
|
4
|
+
# will need to assign roles to user keys or nothing will show up in keys? Yes.
|
5
|
+
# Look at created at datetime for keys?...
|
6
|
+
# *** add any new accounts to bootstrap data with hard coded key values, etc.!
|
7
|
+
class Filter
|
8
|
+
def initialize roles, schema_models_hash, role_permissions={}, role_restrictions={}, role_schema_filters={}, schema_filters={}
|
9
|
+
@schema_models_hash = schema_models_hash
|
10
|
+
@role_permissions = role_permissions
|
11
|
+
@role_restrictions = role_restrictions
|
12
|
+
eat_roles roles, role_permissions, role_restrictions, role_schema_filters, schema_filters
|
13
|
+
end
|
14
|
+
|
15
|
+
def is_root?
|
16
|
+
@is_root = has_permission?(:root) if @is_root == nil
|
17
|
+
@is_root
|
18
|
+
end
|
19
|
+
|
20
|
+
def is_user_admin?
|
21
|
+
@is_user_admin = has_permission?(:auth_admin) if @is_user_admin == nil
|
22
|
+
@is_user_admin
|
23
|
+
end
|
24
|
+
|
25
|
+
def has_access? permission_restriction_name
|
26
|
+
has_permission?(permission_restriction_name) and !(has_restriction?(permission_restriction_name))
|
27
|
+
end
|
28
|
+
|
29
|
+
def has_permission? permission_name
|
30
|
+
puts "@permissions.keys #{@permissions.keys}."
|
31
|
+
puts "has_permission? #{permission_name}."
|
32
|
+
symbol = permission_name.to_sym
|
33
|
+
symbol == @permissions[symbol]
|
34
|
+
end
|
35
|
+
|
36
|
+
def has_restriction? restriction_name
|
37
|
+
symbol = restriction_name.to_sym
|
38
|
+
symbol == @restrictions[symbol]
|
39
|
+
end
|
40
|
+
|
41
|
+
def permissions
|
42
|
+
@permissions.keys
|
43
|
+
end
|
44
|
+
|
45
|
+
def restrictions
|
46
|
+
@restrictions.keys
|
47
|
+
end
|
48
|
+
|
49
|
+
def schema_filter
|
50
|
+
@schema_filter
|
51
|
+
end
|
52
|
+
|
53
|
+
def schema_node_tree
|
54
|
+
@schema_node_tree = JunglePath::Gen::SchemaTree.gen_node_tree(@schema_models_hash, JunglePath::Gen::SchemaTree::Filter.new(@schema_filter)) unless @schema_node_tree
|
55
|
+
@schema_node_tree
|
56
|
+
end
|
57
|
+
|
58
|
+
def roles
|
59
|
+
@roles[0..-1]
|
60
|
+
end
|
61
|
+
|
62
|
+
def root_roles
|
63
|
+
return @root_roles if @root_roles
|
64
|
+
@root_roles = {}
|
65
|
+
@role_permissions.each do |k, v|
|
66
|
+
@root_roles[k] = k if v.include? :root
|
67
|
+
end
|
68
|
+
@root_roles
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def eat_roles roles, role_permissions, role_restrictions, role_schema_filters, schema_filters
|
74
|
+
puts "eat_roles:"
|
75
|
+
@roles = []
|
76
|
+
@permissions = {}
|
77
|
+
@restrictions = {}
|
78
|
+
@schema_filter = nil
|
79
|
+
if roles
|
80
|
+
roles.each do |role|
|
81
|
+
puts "role.class: #{role.class}."
|
82
|
+
puts "role: #{role}."
|
83
|
+
|
84
|
+
@roles << role[:name].to_sym
|
85
|
+
permissions = role_permissions[role[:name].to_sym]
|
86
|
+
if permissions
|
87
|
+
permissions.each do |permission|
|
88
|
+
puts "permission: #{permission}."
|
89
|
+
@permissions[permission.to_sym] = permission.to_sym
|
90
|
+
end
|
91
|
+
end
|
92
|
+
restrictions = role_restrictions[role[:name].to_sym]
|
93
|
+
if restrictions
|
94
|
+
restrictions.each do |restriction|
|
95
|
+
puts "restriction: #{restriction}."
|
96
|
+
@restrictions[restriction.to_sym] = restriction.to_sym
|
97
|
+
end
|
98
|
+
end
|
99
|
+
@schema_filter = schema_filters[role_schema_filters[role[:name].to_sym]]
|
100
|
+
puts "schema_filter: #{@schema_filter}."
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module JunglePath
|
2
|
+
module Authorization
|
3
|
+
module Paths
|
4
|
+
def self.is_open_path? request, route_access
|
5
|
+
# Allowed paths for any user even if not authenticated. (But to get to this point they will have already been authenticated...)
|
6
|
+
if route_access
|
7
|
+
if request.get? and route_access[:public] and route_access[:public][:get]
|
8
|
+
return true if exact_match?(route_access[:public][:get][:routes], request.path_info)
|
9
|
+
return true if leading_segment_match?(route_access[:public][:get][:routes_start_with], request.path_info)
|
10
|
+
|
11
|
+
elsif request.put? and route_access[:public] and route_access[:public][:put]
|
12
|
+
return true if exact_match?(route_access[:public][:put][:routes], request.path_info)
|
13
|
+
return true if leading_segment_match?(route_access[:public][:put][:routes_start_with], request.path_info)
|
14
|
+
|
15
|
+
elsif request.post? and route_access[:public] and route_access[:public][:post]
|
16
|
+
return true if exact_match?(ra[:public][:post][:routes], request.path_info)
|
17
|
+
return true if leading_segment_match?(ra[:public][:post][:routes_start_with], request.path_info)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.is_authenticated_path? request, route_access
|
24
|
+
# Allowed paths for any authenticated user regardless of permissions or restrictions.
|
25
|
+
if route_access
|
26
|
+
if request.get? and route_access[:authenticated] and route_access[:authenticated][:get]
|
27
|
+
return true if exact_match?(route_access[:authenticated][:get][:routes], request.path_info)
|
28
|
+
return true if leading_segment_match?(route_access[:authenticated][:get][:routes_start_with], request.path_info)
|
29
|
+
|
30
|
+
elsif request.put? and route_access[:authenticated] and route_access[:authenticated][:put]
|
31
|
+
return true if exact_match?(route_access[:authenticated][:put][:routes], request.path_info)
|
32
|
+
return true if leading_segment_match?(route_access[:authenticated][:put][:routes_start_with], request.path_info)
|
33
|
+
|
34
|
+
elsif request.post? and route_access[:authenticated] and route_access[:authenticated][:post]
|
35
|
+
return true if exact_match?(route_access[:authenticated][:post][:routes], request.path_info)
|
36
|
+
return true if leading_segment_match?(route_access[:authenticated][:post][:routes_start_with], request.path_info)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.is_query_only_path? request, current_auth
|
43
|
+
is_it = false
|
44
|
+
allowed_paths = {}
|
45
|
+
allowed_paths["/query"] = true
|
46
|
+
allowed_paths["/current/user"] = true
|
47
|
+
allowed_paths["/current/user/auth"] = true
|
48
|
+
is_it = allowed_paths[request.path_info]
|
49
|
+
is_it
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.exact_match? paths, request_path
|
53
|
+
return paths.include?(request_path) if paths
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.leading_segment_match? paths, request_path
|
57
|
+
result = false
|
58
|
+
if paths
|
59
|
+
paths.each do |path|
|
60
|
+
path = path + "/" unless path[-1] == "/"
|
61
|
+
if request_path[0, path.length] == path
|
62
|
+
result = true
|
63
|
+
break
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
result
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module JunglePath
|
2
|
+
module Cache
|
3
|
+
@hash = {}
|
4
|
+
DEFAULT_TIMEOUT = 30 # seconds
|
5
|
+
def self.[] key
|
6
|
+
unwrap(@hash[key], key)
|
7
|
+
end
|
8
|
+
def self.[]= key, value
|
9
|
+
@hash[key] = wrap(value)
|
10
|
+
end
|
11
|
+
def self.get key
|
12
|
+
unwrap(@hash[key], key)
|
13
|
+
end
|
14
|
+
def self.set key, value, timeout=DEFAULT_TIMEOUT
|
15
|
+
@hash[key] = wrap(value, timeout)
|
16
|
+
end
|
17
|
+
def self.clear key
|
18
|
+
@hash.delete key
|
19
|
+
end
|
20
|
+
private
|
21
|
+
def self.wrap value, timeout=DEFAULT_TIMEOUT
|
22
|
+
{value: value, timestamp: Time.now.utc, timeout: timeout}
|
23
|
+
end
|
24
|
+
def self.unwrap item, key
|
25
|
+
if item
|
26
|
+
if Time.now.utc - item[:timestamp] > item[:timeout]
|
27
|
+
@hash.delete key
|
28
|
+
return nil
|
29
|
+
end
|
30
|
+
item[:timestamp] = Time.now.utc
|
31
|
+
return item[:value]
|
32
|
+
end
|
33
|
+
item
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# config.rb
|
2
|
+
require 'singleton'
|
3
|
+
|
4
|
+
module JunglePath
|
5
|
+
module Config
|
6
|
+
# replacement for configatron gem.
|
7
|
+
class Configuration
|
8
|
+
attr_accessor :lock
|
9
|
+
|
10
|
+
def initialize(parent=nil)
|
11
|
+
@parent = parent
|
12
|
+
@hash = {}
|
13
|
+
@lock = false
|
14
|
+
end
|
15
|
+
|
16
|
+
def is_locked?
|
17
|
+
return true if @lock
|
18
|
+
return @parent.lock if @parent
|
19
|
+
@lock
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing(m, *args, &block)
|
23
|
+
s = m.to_s
|
24
|
+
return_value = nil
|
25
|
+
if s.end_with? "="
|
26
|
+
key = s[0..-2]
|
27
|
+
if is_locked?
|
28
|
+
raise "Configuration '#{key}' is locked."
|
29
|
+
else
|
30
|
+
@hash[key] = args[0]
|
31
|
+
end
|
32
|
+
else
|
33
|
+
key = s
|
34
|
+
if @hash.include?(key)
|
35
|
+
return_value = @hash[key]
|
36
|
+
else
|
37
|
+
if is_locked?
|
38
|
+
return_value = nil
|
39
|
+
else
|
40
|
+
return_value = Configuration.new self
|
41
|
+
@hash[key] = return_value
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
return_value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class ConfigurationRoot < Configuration
|
50
|
+
include ::Singleton
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.set_global_on
|
54
|
+
# Monkey patch kernel module:
|
55
|
+
::Kernel.module_eval do
|
56
|
+
#def configatron
|
57
|
+
# Config::ConfigurationRoot.instance
|
58
|
+
#end
|
59
|
+
def config_jungle
|
60
|
+
Config::ConfigurationRoot.instance
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'sequel'
|
3
|
+
require 'jungle_path/authentication'
|
4
|
+
require 'jungle_path/controller'
|
5
|
+
require 'jungle_path/exceptions'
|
6
|
+
require 'jungle_path/schema'
|
7
|
+
require 'jungle_path/sql'
|
8
|
+
|
9
|
+
module JunglePath
|
10
|
+
module Controller
|
11
|
+
class User < Base
|
12
|
+
def initialize(current_user, current_key, params, db)
|
13
|
+
super(current_user, current_key, params, db, JunglePath::Schema::User)
|
14
|
+
end
|
15
|
+
|
16
|
+
def insert(include_secure_columns: false)
|
17
|
+
params = self.class.add_audit_parameter_values_for_insert(@params, @current_user, @current_key, @table_class)
|
18
|
+
model = @table_class.new params
|
19
|
+
|
20
|
+
password = params[:password]
|
21
|
+
message = self.class.validate_password_message(password)
|
22
|
+
if message
|
23
|
+
self.class.validate_insert(model, message)
|
24
|
+
raise JunglePath::Exceptions::InvalidPassword, "#{message}", caller
|
25
|
+
end
|
26
|
+
# todo: validate password strength, etc. here!
|
27
|
+
model.hash = JunglePath::Authentication::PasswordHash.createHash(password)
|
28
|
+
|
29
|
+
self.class.validate_insert(model)
|
30
|
+
begin
|
31
|
+
result = @db.insert._model(model)
|
32
|
+
result = self.class.handle_include_secure_columns_flag(result, include_secure_columns, @table_class)
|
33
|
+
rescue Sequel::UniqueConstraintViolation => e
|
34
|
+
# already there? update instead...
|
35
|
+
#puts "not unique!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
36
|
+
user_query = JunglePath::Schema::User.new({user_name: params[:user_name]})
|
37
|
+
user = @db.select._model_by_any(user_query)
|
38
|
+
#puts "user: #{user}."
|
39
|
+
params[:id] = user.id if user
|
40
|
+
if user
|
41
|
+
update
|
42
|
+
user = @db.select._model(user)
|
43
|
+
else
|
44
|
+
raise
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def update
|
50
|
+
params = self.class.add_audit_parameter_values_for_update(@params, @current_user, @current_key, @table_class)
|
51
|
+
model = @table_class.new params
|
52
|
+
|
53
|
+
password = params[:password]
|
54
|
+
if password
|
55
|
+
message = self.class.validate_password_message(password)
|
56
|
+
if message
|
57
|
+
self.class.validate_update(model, message)
|
58
|
+
raise JunglePath::Exceptions::InvalidPassword, "#{message}", caller
|
59
|
+
end
|
60
|
+
# todo: validate password strength, etc. here!
|
61
|
+
model.hash = JunglePath::Authentication::PasswordHash.createHash(password)
|
62
|
+
end
|
63
|
+
|
64
|
+
self.class.validate_update(model)
|
65
|
+
result = @db.update._model(model)
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.validate_hash_with_password(hash, password)
|
69
|
+
JunglePath::Authentication::PasswordHash.validatePassword(password, hash)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
def self.validate_password_message(password)
|
74
|
+
message = nil
|
75
|
+
# returns message if password is not a minimum strength...
|
76
|
+
message = "Password is either missing or too short." unless password and password.length > 0
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class Key < Base
|
81
|
+
def initialize(current_user, current_key, params, db)
|
82
|
+
super(current_user, current_key, params, db, JunglePath::Schema::Key)
|
83
|
+
end
|
84
|
+
|
85
|
+
def select_by_key(include_secure_columns: false)
|
86
|
+
JunglePath::SQL::Key.by_key(@db, @params[:key])
|
87
|
+
end
|
88
|
+
|
89
|
+
def select_by_user(include_secure_columns: false)
|
90
|
+
JunglePath::SQL::Key.by_user_id(@db, @params[:user_id])
|
91
|
+
end
|
92
|
+
|
93
|
+
def select_by_user_by_key_name(include_secure_columns: false)
|
94
|
+
JunglePath::SQL::Key.by_user_id_key_name(@db, @params[:user_id], @params[:name])
|
95
|
+
end
|
96
|
+
|
97
|
+
def select_default_by_user(include_secure_columns: false)
|
98
|
+
JunglePath::SQL::Key.default_by_user_id(@db, @params[:user_id])
|
99
|
+
end
|
100
|
+
|
101
|
+
#def select_by_user_by_application(include_secure_columns: false)
|
102
|
+
# @params = Controller::Base.transform(@params, Schema::Role.columns)
|
103
|
+
# SQL::Key.by_user_id_application_id(@db, @params[:user_id], @params[:application_id])
|
104
|
+
#end
|
105
|
+
#
|
106
|
+
#def select_default_by_user_by_application(include_secure_columns: false)
|
107
|
+
# @params = Controller::Base.transform(@params, Schema::Role.columns)
|
108
|
+
# SQL::Key.default_by_user_id_application_id(@db, @params[:user_id], @params[:application_id])
|
109
|
+
#end
|
110
|
+
|
111
|
+
def insert(include_secure_columns: false)
|
112
|
+
#puts "insert key!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
113
|
+
#already exists?
|
114
|
+
array = self.select_by_user_by_key_name
|
115
|
+
hash = array.first if array and array.length > 0
|
116
|
+
if hash #exists already, do update.
|
117
|
+
key = @table_class.new(hash) # get current values which includes primary key (pk is needed for an update).
|
118
|
+
key._consume_hash(@params) # overwrite current values with new values
|
119
|
+
@params = key.to_hash # put all in @params for update
|
120
|
+
update
|
121
|
+
key = @db.select._model(key) # return updated object from database.
|
122
|
+
else
|
123
|
+
@params[:key] = JunglePath::Authentication::Helpers.generate_api_key unless @params[:key] #create a new key_string unless one was passed in.
|
124
|
+
super
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
# controller.rb
|
2
|
+
require 'jungle_path/db_model'
|
3
|
+
require 'jungle_path/exceptions'
|
4
|
+
|
5
|
+
module JunglePath
|
6
|
+
module Controller
|
7
|
+
class Base
|
8
|
+
def initialize(current_user, current_key, params, db, table_class)
|
9
|
+
@current_user = current_user
|
10
|
+
@current_key = current_key
|
11
|
+
@db = db
|
12
|
+
@table_class = table_class
|
13
|
+
@params = self.class.transform(params.to_h, table_class.columns)
|
14
|
+
#puts "base @params: #{@params}."
|
15
|
+
end
|
16
|
+
|
17
|
+
def select(include_secure_columns: false, use_only_pk_columns_to_select_if_available: true)
|
18
|
+
if use_only_pk_columns_to_select_if_available and self.class.by_primary_key?(@params, @table_class.primary_key_columns)
|
19
|
+
#puts "a"
|
20
|
+
pk_hash = @table_class.new(@params)._primary_key
|
21
|
+
model = @table_class.new(pk_hash)
|
22
|
+
result = @db.select._model(model) # todo: use _model here instead?
|
23
|
+
elsif self.class.by_primary_key?(@params, @table_class.primary_key_columns)
|
24
|
+
#puts "b"
|
25
|
+
result = @db.select._model_by_any(@table_class.new(@params))
|
26
|
+
else
|
27
|
+
#puts "c"
|
28
|
+
result = @db.select._models(@table_class.new(@params))
|
29
|
+
end
|
30
|
+
result = self.class.handle_include_secure_columns_flag(result, include_secure_columns, @table_class)
|
31
|
+
end
|
32
|
+
|
33
|
+
def insert(include_secure_columns: false)
|
34
|
+
params = self.class.add_audit_parameter_values_for_insert(@params, @current_user, @current_key, @table_class)
|
35
|
+
model = @table_class.new params
|
36
|
+
self.class.validate_insert(model)
|
37
|
+
result = @db.insert._model(model)
|
38
|
+
result = self.class.handle_include_secure_columns_flag(result, include_secure_columns, @table_class)
|
39
|
+
end
|
40
|
+
|
41
|
+
def update
|
42
|
+
params = self.class.add_audit_parameter_values_for_update(@params, @current_user, @current_key, @table_class)
|
43
|
+
model = @table_class.new params
|
44
|
+
self.class.validate_update(model)
|
45
|
+
result = @db.update._model(model)
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete
|
49
|
+
model = @table_class.new @params
|
50
|
+
self.class.validate_delete(model)
|
51
|
+
result = @db.delete._model(model)
|
52
|
+
end
|
53
|
+
|
54
|
+
def delete_rows
|
55
|
+
model = @table_class.new @params
|
56
|
+
result = @db.delete._models(model, true)
|
57
|
+
end
|
58
|
+
|
59
|
+
def drop_table
|
60
|
+
@db.schema.drop_table @table_class
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_table
|
64
|
+
@db.schema.create_table @table_class
|
65
|
+
end
|
66
|
+
|
67
|
+
begin # class methods
|
68
|
+
def self.transform(params, columns)
|
69
|
+
DBModel::Params.transform(params, columns)
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.symbolize(params)
|
73
|
+
DBModel::Params.symbolize(params)
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.convert_to_type(params, columns)
|
77
|
+
DBModel::Params.convert_to_type(params, columns)
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.to_bool(value)
|
81
|
+
DBModel::Params.to_bool(value)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.validate_insert(model, additional_message=nil)
|
85
|
+
additional_message += " \n" if additional_message
|
86
|
+
missing = []
|
87
|
+
model._columns.values.each do |column|
|
88
|
+
required = false
|
89
|
+
if column.primary_key? and column.foreign_key?
|
90
|
+
required = true
|
91
|
+
elsif !column.calculated? and column.not_null?
|
92
|
+
required = true
|
93
|
+
end
|
94
|
+
#puts "#{column.name}: #{model._values[column.name]}." if required
|
95
|
+
missing << column.name if required and model._values[column.name] == nil
|
96
|
+
end
|
97
|
+
raise Exceptions::MissingRequiredFields, "#{additional_message}Missing values for: #{missing.join(', ')}.", caller if missing.length > 0
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.validate_update(model, additional_message=nil)
|
101
|
+
additional_message += " \n" if additional_message
|
102
|
+
missing = []
|
103
|
+
model._columns.values.each do |column|
|
104
|
+
required = false
|
105
|
+
if column.primary_key?
|
106
|
+
required = true
|
107
|
+
elsif !column.calculated? and column.not_null?
|
108
|
+
required = true
|
109
|
+
end
|
110
|
+
missing << column.name if required and model._modified.member?(column.name) and model._values[column.name] == nil
|
111
|
+
end
|
112
|
+
raise Exceptions::MissingRequiredFields, "#{additional_message}Missing values for: #{missing.join(', ')}.", caller if missing.length > 0
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.validate_delete(model, additional_message=nil)
|
116
|
+
additional_message += " \n" if additional_message
|
117
|
+
missing = []
|
118
|
+
model._columns.values.each do |column|
|
119
|
+
required = false
|
120
|
+
if column.primary_key?
|
121
|
+
required = true
|
122
|
+
end
|
123
|
+
missing << column.name if required and model._values[column.name] == nil
|
124
|
+
end
|
125
|
+
raise Exceptions::MissingRequiredFields, "#{additional_message}Missing values for: #{missing.join(', ')}.", caller if missing.length > 0
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.handle_include_secure_columns_flag(result, include_secure_columns_flag, table_class)
|
129
|
+
if include_secure_columns_flag
|
130
|
+
# mark instance #_secure = false to allow columns marked :secure to be exported as json or as a hash when #to_hash or #to_json is called.
|
131
|
+
if result.class == table_class
|
132
|
+
result._secure = false
|
133
|
+
return result
|
134
|
+
end
|
135
|
+
result.each do |item|
|
136
|
+
item._secure = false
|
137
|
+
end
|
138
|
+
end
|
139
|
+
result
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.by_primary_key?(params, primary_key_columns)
|
143
|
+
primary_key_columns.keys.each do |k|
|
144
|
+
return false unless params.include? k
|
145
|
+
end
|
146
|
+
true
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.add_audit_parameter_values_for_insert(params, current_user, current_key, table_class)
|
150
|
+
if table_class.columns.include?(:created_by_user_id)
|
151
|
+
params = add_audit_user_for_insert(params, current_user)
|
152
|
+
elsif table_class.columns.include?(:created_by_key_id)
|
153
|
+
params = add_audit_key_for_insert(params, current_key)
|
154
|
+
end
|
155
|
+
params
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.add_audit_parameter_values_for_update(params, current_user, current_key, table_class)
|
159
|
+
if table_class.columns.include?(:created_by_user_id)
|
160
|
+
params = add_audit_user_for_update(params, current_user)
|
161
|
+
elsif table_class.columns.include?(:created_by_key_id)
|
162
|
+
params = add_audit_key_for_update(params, current_key)
|
163
|
+
end
|
164
|
+
params
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.add_audit_user_for_insert(params, current_user, timestamp=Time.now.utc)
|
168
|
+
params[:created_at] = timestamp unless params[:created_at]
|
169
|
+
params[:created_by_user_id] = current_user.id unless params[:created_by_user_id]
|
170
|
+
add_audit_user_for_update(params, current_user, timestamp)
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.add_audit_user_for_update(params, current_user, timestamp=Time.now.utc)
|
174
|
+
params[:updated_at] = timestamp unless params[:updated_at]
|
175
|
+
params[:updated_by_user_id] = current_user.id unless params[:updated_by_user_id]
|
176
|
+
params
|
177
|
+
end
|
178
|
+
|
179
|
+
def self.add_audit_key_for_insert(params, current_key, timestamp=Time.now.utc)
|
180
|
+
params[:created_at] = timestamp unless params[:created_at]
|
181
|
+
params[:created_by_key_id] = current_key.id unless params[:created_by_key_id]
|
182
|
+
add_audit_key_for_update(params, current_key, timestamp)
|
183
|
+
end
|
184
|
+
|
185
|
+
def self.add_audit_key_for_update(params, current_key, timestamp=Time.now.utc)
|
186
|
+
params[:updated_at] = timestamp unless params[:updated_at]
|
187
|
+
params[:updated_by_key_id] = current_key.id unless params[:updated_by_key_id]
|
188
|
+
params
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module JunglePath
|
2
|
+
module Controller
|
3
|
+
module Helpers
|
4
|
+
module User
|
5
|
+
def initialize(current_user, current_key, params, db, model_class)
|
6
|
+
super(current_user, current_key, params, db, model_class)
|
7
|
+
end
|
8
|
+
|
9
|
+
def insert(include_secure_columns: false)
|
10
|
+
id = @params[:id]
|
11
|
+
user_name = @params[:user_name]
|
12
|
+
user = @db.select._model(@table_class.new({id: id})) if id
|
13
|
+
user = @db.select._model_by_any(@table_class.new({user_name: user_name})) if ((not user) and user_name)
|
14
|
+
if user #already exists?
|
15
|
+
puts "user #{user.user_name} already exists."
|
16
|
+
user._consume_hash(@params) # overwrite current values with new values
|
17
|
+
@params = user.to_hash # put all in @params for update
|
18
|
+
update
|
19
|
+
user = @db.select._model(user)
|
20
|
+
else
|
21
|
+
puts "super..."
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module Key
|
28
|
+
def initialize(current_user, current_key, params, db, model_class)
|
29
|
+
super(current_user, current_key, params, db, model_class)
|
30
|
+
end
|
31
|
+
|
32
|
+
def insert(include_secure_columns: false)
|
33
|
+
id = @params[:id]
|
34
|
+
key = @db.select._model(@table_class.new({id: id})) if id
|
35
|
+
if key #exists already, do update.
|
36
|
+
key._consume_hash(@params) # overwrite current values with new values
|
37
|
+
@params = key.to_hash # put all in @params for update
|
38
|
+
update
|
39
|
+
key = @db.select._model(key) # return updated object from database.
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<% #controller_template.erb %>
|
2
|
+
<%= "#This file was generated using the jungle_path/controller/controller_template.erb. Do not modify directly." %>
|
3
|
+
require_relative 'jungle_path/controller'
|
4
|
+
require_relative 'jungle_path/schema'
|
5
|
+
|
6
|
+
module <%= controller_name_space %>
|
7
|
+
<% for table in tables %>
|
8
|
+
class <%= table.name.split('::').last %> < JunglePath::Controller::Base
|
9
|
+
def initialize(current_user, current_key, params, db)
|
10
|
+
super(current_user, current_key, params, db, <%= table.name.to_s %>)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
<% end %>
|
14
|
+
end
|