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.
Files changed (129) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +22 -0
  6. data/README.md +5 -0
  7. data/jungle_path.gemspec +43 -0
  8. data/lib/jungle_path/api/helpers/auth.rb +45 -0
  9. data/lib/jungle_path/api/helpers/auth_local_user.rb +284 -0
  10. data/lib/jungle_path/api/helpers/auth_old.rb +232 -0
  11. data/lib/jungle_path/api/helpers/data_cache.rb +20 -0
  12. data/lib/jungle_path/api/helpers/defaults.rb +83 -0
  13. data/lib/jungle_path/api/helpers/logging.rb +36 -0
  14. data/lib/jungle_path/api/helpers/query_filters.rb +15 -0
  15. data/lib/jungle_path/api/helpers/rescues.rb +15 -0
  16. data/lib/jungle_path/api/helpers/result.rb +16 -0
  17. data/lib/jungle_path/api/helpers/standard_apis.rb +280 -0
  18. data/lib/jungle_path/api/helpers.rb +16 -0
  19. data/lib/jungle_path/api/template.erb +35 -0
  20. data/lib/jungle_path/api.rb +5 -0
  21. data/lib/jungle_path/app/a.gitignore +1 -0
  22. data/lib/jungle_path/app/api/server_base.rb +95 -0
  23. data/lib/jungle_path/app/api/server_custom.rb +121 -0
  24. data/lib/jungle_path/app/api/server_gen.rb +11 -0
  25. data/lib/jungle_path/app/auth/authorization.rb +96 -0
  26. data/lib/jungle_path/app/config/a.gitignore +1 -0
  27. data/lib/jungle_path/app/config/config.rb +240 -0
  28. data/lib/jungle_path/app/config/override.rb +3 -0
  29. data/lib/jungle_path/app/config.ru +28 -0
  30. data/lib/jungle_path/app/logs/log_files_go_here +0 -0
  31. data/lib/jungle_path/app/run.sh +4 -0
  32. data/lib/jungle_path/app/schemas/schema.rb +21 -0
  33. data/lib/jungle_path/app/schemas/schema_all_in_one.rb +181 -0
  34. data/lib/jungle_path/app.rb +8 -0
  35. data/lib/jungle_path/authentication/auth_provider/default.rb +83 -0
  36. data/lib/jungle_path/authentication/auth_provider.rb +7 -0
  37. data/lib/jungle_path/authentication/data_provider/default.rb +144 -0
  38. data/lib/jungle_path/authentication/data_provider.rb +7 -0
  39. data/lib/jungle_path/authentication/helpers.rb +19 -0
  40. data/lib/jungle_path/authentication/identity.rb +30 -0
  41. data/lib/jungle_path/authentication/password_hash.rb +124 -0
  42. data/lib/jungle_path/authentication.rb +9 -0
  43. data/lib/jungle_path/authorization/filter.rb +106 -0
  44. data/lib/jungle_path/authorization/paths.rb +71 -0
  45. data/lib/jungle_path/authorization.rb +5 -0
  46. data/lib/jungle_path/cache.rb +36 -0
  47. data/lib/jungle_path/config.rb +65 -0
  48. data/lib/jungle_path/controller/authentication.rb +129 -0
  49. data/lib/jungle_path/controller/base.rb +193 -0
  50. data/lib/jungle_path/controller/helpers.rb +47 -0
  51. data/lib/jungle_path/controller/template.erb +14 -0
  52. data/lib/jungle_path/controller.rb +7 -0
  53. data/lib/jungle_path/db_access/import/db_dir.rb +74 -0
  54. data/lib/jungle_path/db_access/import/delete.rb +30 -0
  55. data/lib/jungle_path/db_access/import/insert.rb +168 -0
  56. data/lib/jungle_path/db_access/import/schema.rb +34 -0
  57. data/lib/jungle_path/db_access/import/select.rb +68 -0
  58. data/lib/jungle_path/db_access/import.rb +15 -0
  59. data/lib/jungle_path/db_access/io/chunked_file_reader.rb +62 -0
  60. data/lib/jungle_path/db_access/io/config.rb +19 -0
  61. data/lib/jungle_path/db_access/io/copy.rb +73 -0
  62. data/lib/jungle_path/db_access/io/db.rb +82 -0
  63. data/lib/jungle_path/db_access/io/delete.rb +23 -0
  64. data/lib/jungle_path/db_access/io/init_db.rb +39 -0
  65. data/lib/jungle_path/db_access/io/insert.rb +24 -0
  66. data/lib/jungle_path/db_access/io/schema.rb +21 -0
  67. data/lib/jungle_path/db_access/io/select.rb +44 -0
  68. data/lib/jungle_path/db_access/io/update.rb +36 -0
  69. data/lib/jungle_path/db_access/io.rb +104 -0
  70. data/lib/jungle_path/db_model/column.rb +186 -0
  71. data/lib/jungle_path/db_model/params.rb +60 -0
  72. data/lib/jungle_path/db_model/schema.rb +100 -0
  73. data/lib/jungle_path/db_model/string.rb +9 -0
  74. data/lib/jungle_path/db_model/table.rb +307 -0
  75. data/lib/jungle_path/db_model.rb +34 -0
  76. data/lib/jungle_path/exceptions.rb +10 -0
  77. data/lib/jungle_path/gen/api.rb +52 -0
  78. data/lib/jungle_path/gen/controller.rb +0 -0
  79. data/lib/jungle_path/gen/db.rb +0 -0
  80. data/lib/jungle_path/gen/schema.rb +47 -0
  81. data/lib/jungle_path/gen/schema_tree/filter.rb +33 -0
  82. data/lib/jungle_path/gen/schema_tree/match_columns.rb +54 -0
  83. data/lib/jungle_path/gen/schema_tree/match_table_data.rb +22 -0
  84. data/lib/jungle_path/gen/schema_tree/match_tables.rb +70 -0
  85. data/lib/jungle_path/gen/schema_tree/node.rb +39 -0
  86. data/lib/jungle_path/gen/schema_tree.rb +105 -0
  87. data/lib/jungle_path/gen.rb +9 -0
  88. data/lib/jungle_path/json/base.rb +29 -0
  89. data/lib/jungle_path/json/time.rb +8 -0
  90. data/lib/jungle_path/json.rb +6 -0
  91. data/lib/jungle_path/logging.rb +23 -0
  92. data/lib/jungle_path/query/alias_info.rb +16 -0
  93. data/lib/jungle_path/query/engine.rb +878 -0
  94. data/lib/jungle_path/query/entity.rb +141 -0
  95. data/lib/jungle_path/query/field.rb +28 -0
  96. data/lib/jungle_path/query/field_primary_key.rb +27 -0
  97. data/lib/jungle_path/query/filter.rb +34 -0
  98. data/lib/jungle_path/query/float_value.rb +16 -0
  99. data/lib/jungle_path/query/from.rb +33 -0
  100. data/lib/jungle_path/query/int_value.rb +16 -0
  101. data/lib/jungle_path/query/limit.rb +19 -0
  102. data/lib/jungle_path/query/nested_hash_sorter.rb +94 -0
  103. data/lib/jungle_path/query/operator.rb +17 -0
  104. data/lib/jungle_path/query/query.rb +23 -0
  105. data/lib/jungle_path/query/sort_field.rb +34 -0
  106. data/lib/jungle_path/query/sql_string.rb +145 -0
  107. data/lib/jungle_path/query/string_value.rb +16 -0
  108. data/lib/jungle_path/query.rb +19 -0
  109. data/lib/jungle_path/rack/basic_credentials.rb +70 -0
  110. data/lib/jungle_path/rack/json_body_parser.rb +41 -0
  111. data/lib/jungle_path/rack.rb +6 -0
  112. data/lib/jungle_path/schema/auth.rb +83 -0
  113. data/lib/jungle_path/schema/base.rb +6 -0
  114. data/lib/jungle_path/schema/db.rb +10 -0
  115. data/lib/jungle_path/schema/version.rb +19 -0
  116. data/lib/jungle_path/schema.rb +8 -0
  117. data/lib/jungle_path/sql/auth_local_user.rb +5 -0
  118. data/lib/jungle_path/sql/general.rb +10 -0
  119. data/lib/jungle_path/sql/helpers.rb +11 -0
  120. data/lib/jungle_path/sql/key.rb +107 -0
  121. data/lib/jungle_path/sql/query_filter.rb +5 -0
  122. data/lib/jungle_path/sql/role.rb +5 -0
  123. data/lib/jungle_path/sql/user.rb +35 -0
  124. data/lib/jungle_path/sql/user_role.rb +5 -0
  125. data/lib/jungle_path/sql.rb +12 -0
  126. data/lib/jungle_path.rb +13 -0
  127. data/test.rb +33 -0
  128. data/test2.rb +15 -0
  129. 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,5 @@
1
+ module JunglePath
2
+ module Authorization
3
+ require 'jungle_path/authorization/filter'
4
+ end
5
+ 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
@@ -0,0 +1,7 @@
1
+ module JunglePath
2
+ module Controller
3
+ require 'jungle_path/controller/base'
4
+ require 'jungle_path/controller/authentication'
5
+ require 'jungle_path/controller/helpers'
6
+ end
7
+ end