gloo 4.6.1 → 5.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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/gloo.gemspec +22 -11
  4. data/lib/VERSION +1 -1
  5. data/lib/VERSION_NOTES +12 -0
  6. data/lib/gloo/app/engine.rb +8 -1
  7. data/lib/gloo/app/running_app.rb +13 -0
  8. data/lib/gloo/app/settings.rb +5 -1
  9. data/lib/gloo/core/dictionary.rb +15 -2
  10. data/lib/gloo/objs/ctrl/each.rb +2 -2
  11. data/lib/gloo/plugin/base.rb +19 -0
  12. data/lib/gloo/plugin/callback.rb +33 -0
  13. data/lib/gloo/plugin/ext_manager.rb +90 -0
  14. data/lib/gloo/plugin/lib_manager.rb +97 -0
  15. data/lib/gloo/verbs/exists.rb +75 -0
  16. data/lib/gloo/verbs/help.rb +58 -1
  17. data/lib/gloo/verbs/load.rb +49 -5
  18. data/lib/gloo/verbs/redirect.rb +2 -1
  19. metadata +38 -166
  20. data/lib/gloo/objs/cli/colorize.rb +0 -73
  21. data/lib/gloo/objs/cli/confirm.rb +0 -96
  22. data/lib/gloo/objs/cli/menu.rb +0 -370
  23. data/lib/gloo/objs/cli/menu_item.rb +0 -95
  24. data/lib/gloo/objs/cli/prompt.rb +0 -110
  25. data/lib/gloo/objs/cli/select.rb +0 -127
  26. data/lib/gloo/objs/ctrl/each_repo.rb +0 -84
  27. data/lib/gloo/objs/data/markdown.rb +0 -133
  28. data/lib/gloo/objs/data/markdown_ext.rb +0 -260
  29. data/lib/gloo/objs/data/mysql.rb +0 -254
  30. data/lib/gloo/objs/data/pg.rb +0 -216
  31. data/lib/gloo/objs/data/query.rb +0 -269
  32. data/lib/gloo/objs/data/query_result.rb +0 -158
  33. data/lib/gloo/objs/data/sqlite.rb +0 -174
  34. data/lib/gloo/objs/data/table.rb +0 -267
  35. data/lib/gloo/objs/dev/git.rb +0 -140
  36. data/lib/gloo/objs/dev/stats.rb +0 -123
  37. data/lib/gloo/objs/system/ssh_exec.rb +0 -126
  38. data/lib/gloo/objs/web/slack.rb +0 -130
  39. data/lib/gloo/objs/web/teams.rb +0 -117
  40. data/lib/gloo/objs/web_svr/element.rb +0 -254
  41. data/lib/gloo/objs/web_svr/field.rb +0 -429
  42. data/lib/gloo/objs/web_svr/form.rb +0 -271
  43. data/lib/gloo/objs/web_svr/page.rb +0 -562
  44. data/lib/gloo/objs/web_svr/partial.rb +0 -210
  45. data/lib/gloo/objs/web_svr/svr.rb +0 -713
  46. data/lib/gloo/utils/stats.rb +0 -206
  47. data/lib/gloo/verbs/alert.rb +0 -79
  48. data/lib/gloo/verbs/beep.rb +0 -40
  49. data/lib/gloo/web_svr/asset.rb +0 -407
  50. data/lib/gloo/web_svr/asset_info.rb +0 -116
  51. data/lib/gloo/web_svr/config.rb +0 -56
  52. data/lib/gloo/web_svr/embedded_renderer.rb +0 -154
  53. data/lib/gloo/web_svr/handler.rb +0 -154
  54. data/lib/gloo/web_svr/request.rb +0 -143
  55. data/lib/gloo/web_svr/request_params.rb +0 -181
  56. data/lib/gloo/web_svr/response.rb +0 -177
  57. data/lib/gloo/web_svr/response_code.rb +0 -69
  58. data/lib/gloo/web_svr/routing/resource_router.rb +0 -47
  59. data/lib/gloo/web_svr/routing/router.rb +0 -232
  60. data/lib/gloo/web_svr/routing/show_routes.rb +0 -94
  61. data/lib/gloo/web_svr/server.rb +0 -105
  62. data/lib/gloo/web_svr/session.rb +0 -215
  63. data/lib/gloo/web_svr/table_renderer.rb +0 -151
  64. data/lib/gloo/web_svr/web_method.rb +0 -54
  65. /data/lib/gloo/objs/{security → str_utils}/cipher.rb +0 -0
  66. /data/lib/gloo/objs/{security → str_utils}/csrf_token.rb +0 -0
  67. /data/lib/gloo/objs/{security → str_utils}/password.rb +0 -0
  68. /data/lib/gloo/objs/{ror → system}/erb.rb +0 -0
  69. /data/lib/gloo/objs/{ror → system}/eval.rb +0 -0
@@ -1,154 +0,0 @@
1
- # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
- # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
- #
4
- # A helper class used to render parameters (ERB) in text.
5
- # Also uses helper functions to render.
6
- #
7
-
8
- module Gloo
9
- module WebSvr
10
- class EmbeddedRenderer
11
-
12
- HELPER = 'helper'.freeze
13
-
14
- attr_reader :engine, :log, :web_svr_obj
15
-
16
-
17
- # ---------------------------------------------------------------------
18
- # Initialization
19
- # ---------------------------------------------------------------------
20
-
21
- #
22
- # Set up the web server.
23
- #
24
- def initialize( engine, web_svr_obj )
25
- @engine = engine
26
- @log = @engine.log
27
-
28
- @web_svr_obj = web_svr_obj
29
- end
30
-
31
-
32
- # ---------------------------------------------------------------------
33
- # Tag Helpers
34
- # ---------------------------------------------------------------------
35
-
36
- #
37
- # Render a favicon tag.
38
- # By default the name is 'favicon.ico' and does not need to be provided
39
- # if that is the correct file name.
40
- #
41
- def favicon_tag( name = 'favicon.ico' )
42
- icon_path = "/#{Asset::ASSET_FOLDER}/#{Asset::IMAGE_FOLDER}/#{name}"
43
- published_name = @engine.running_app.obj.asset.published_name( icon_path )
44
- return "<link rel='shortcut icon' type='image/x-icon' href='#{published_name}' />"
45
- end
46
-
47
- #
48
- # Render a Apple Touch Icon tag.
49
- # By default the name is 'apple-touch-icon.png' and does not need to be provided
50
- # if that is the correct file name.
51
- #
52
- def apple_touch_icon_tag( name = 'apple-touch-icon.png', type = 'image/png' )
53
- icon_path = "/#{Asset::ASSET_FOLDER}/#{Asset::IMAGE_FOLDER}/#{name}"
54
- published_name = @engine.running_app.obj.asset.published_name( icon_path )
55
- return "<link rel='apple-touch-icon' type='#{type}' href='#{published_name}' />"
56
- end
57
-
58
- #
59
- # Render an image tag for the given image name.
60
- # Include optional proterties as part of the tag.
61
- #
62
- def image_tag( img_name, properties = '' )
63
- image_path = "/#{Asset::ASSET_FOLDER}/#{Asset::IMAGE_FOLDER}/#{img_name}"
64
- published_name = @engine.running_app.obj.asset.published_name( image_path )
65
- return "<image src='#{published_name}' #{properties} />"
66
- end
67
-
68
- #
69
- # Render a script tag for the given script name.
70
- #
71
- def js_tag( name )
72
- js_path = "/#{Asset::ASSET_FOLDER}/#{Asset::JAVASCRIPT_FOLDER}/#{name}"
73
- published_name = @engine.running_app.obj.asset.published_name( js_path )
74
- return "<script src='#{published_name}'></script>"
75
- end
76
-
77
- #
78
- # Render a stylesheet tag for the given stylesheet name.
79
- #
80
- def css_tag( name )
81
- css_path = "/#{Asset::ASSET_FOLDER}/#{Asset::STYLESHEET_FOLDER}/#{name}"
82
- published_name = @engine.running_app.obj.asset.published_name( css_path )
83
- return "<link rel='stylesheet' media='all' href='#{published_name}' />"
84
- end
85
-
86
- #
87
- # Embed a hidden field with the autenticity token.
88
- #
89
- def autenticity_token_tag
90
- session_id = @engine.running_app.obj&.session&.get_session_id
91
- return Gloo::Objs::CsrfToken.get_csrf_token_hidden_field( session_id )
92
- end
93
-
94
-
95
- # ---------------------------------------------------------------------
96
- # Obj Helper Functions
97
- # ---------------------------------------------------------------------
98
-
99
- #
100
- # Handle a missing method by looking for a helper function.
101
- # If there is one, then call it and return the result.
102
- # If not, log an error and return nil.
103
- #
104
- def method_missing( method_name, *args )
105
- @log.debug "missing method '#{method_name}' with args #{args}"
106
-
107
- helper_pn = "#{HELPER}.#{method_name}"
108
- @log.debug "looking for function: #{helper_pn}"
109
-
110
- pn = Gloo::Core::Pn.new( @engine, helper_pn )
111
- obj = pn.resolve
112
- if obj
113
- @log.debug "found obj: #{obj.pn}"
114
- return obj.invoke args
115
- else
116
- @log.error "Function not found: #{helper_pn}"
117
- end
118
-
119
- return nil
120
- end
121
-
122
-
123
- # ---------------------------------------------------------------------
124
- # Renderer
125
- # ---------------------------------------------------------------------
126
-
127
- #
128
- # Render content with the given params.
129
- # Params might be nil, in which case the content
130
- # is returned with no changes.
131
- #
132
- def render content, params
133
- # If the params is nil, let's make it an empty hash.
134
- params = {} unless params
135
-
136
- # Get the binding context for this render.
137
- b = binding
138
-
139
- # Add the params to the binding context.
140
- params.each_pair do |key, value|
141
- b.local_variable_set key.to_sym, value
142
- end
143
-
144
- # Render in the current binding content.
145
- renderer = ERB.new( content )
146
- content = renderer.result( b )
147
-
148
- return content
149
- end
150
-
151
- end
152
-
153
- end
154
- end
@@ -1,154 +0,0 @@
1
- # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
- # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
- #
4
- # Web application request handler.
5
- # Takes a request and does what is needed to create a response.
6
- #
7
-
8
- module Gloo
9
- module WebSvr
10
- class Handler
11
-
12
- attr_reader :server_obj
13
-
14
-
15
- # ---------------------------------------------------------------------
16
- # Initialization
17
- # ---------------------------------------------------------------------
18
-
19
- #
20
- # Set up the web server.
21
- #
22
- def initialize( engine, obj )
23
- @engine = engine
24
- @log = @engine.log
25
- @server_obj = obj
26
- end
27
-
28
-
29
- # ---------------------------------------------------------------------
30
- # Process Request
31
- # ---------------------------------------------------------------------
32
-
33
- #
34
- # Process the request and return a result.
35
- #
36
- def handle request
37
- @request = request
38
- page_obj = nil
39
- route_params = nil
40
-
41
- page, id, route_params = @server_obj.router.page_for_route( @request.path, @request.method )
42
- @engine.log.debug "Found Page: #{page&.name}" if page
43
-
44
- request.request_params.id = id
45
- request.request_params.route_params = route_params
46
- request.request_params.log_id_keys
47
-
48
- if page
49
- # Run the on_request script with the found page.
50
- @server_obj.run_on_request( page )
51
-
52
- if page.is_a? Gloo::Objs::FileHandle
53
- result = handle_file page
54
- else
55
- result = handle_page page
56
- page_obj = page
57
- end
58
- else
59
- result = server_error_result
60
- end
61
-
62
- return result, page_obj
63
- end
64
-
65
- #
66
- # Handle request for a page.
67
- # Render the page, with possible redirect.
68
- #
69
- def handle_page page
70
- result = page.render @request
71
- if redirect_hard_set?
72
- result = server_redirect_result
73
- @engine.running_app.obj.redirect_hard = nil
74
- elsif redirect_set?
75
- page = @engine.running_app.obj.redirect
76
- @log.debug "Redirecting to: #{page.pn}"
77
- @engine.running_app.obj.redirect = nil
78
- result = page.render
79
- end
80
- return result
81
- end
82
-
83
- #
84
- # Handle a request for a static file such as an image.
85
- #
86
- def handle_file file
87
- pn = @server_obj.asset.path_for_file file
88
-
89
- # Check to make sure it is a valid file
90
- # return error if it is not
91
- return file_error_result unless File.exist? pn
92
-
93
- return @server_obj.asset.render_file pn
94
- end
95
-
96
-
97
- # ---------------------------------------------------------------------
98
- # Errors
99
- # ---------------------------------------------------------------------
100
-
101
- #
102
- # Return a server error result.
103
- # Use the app's error if there is one, otherwise a generic message.
104
- #
105
- def server_error_result
106
- err_page = @server_obj.err_page
107
- return err_page.render if err_page
108
-
109
- # Last resort, just return a generic error message.
110
- return Gloo::WebSvr::Response.text_response( @engine,
111
- "Server error!", Gloo::WebSvr::ResponseCode::SERVER_ERR )
112
- end
113
-
114
- #
115
- # Get a file not found error result.
116
- #
117
- def file_error_result
118
- return Gloo::WebSvr::Response.text_response( @engine,
119
- "File not found!", Gloo::WebSvr::ResponseCode::NOT_FOUND )
120
- end
121
-
122
-
123
- # ---------------------------------------------------------------------
124
- # Redirect Helper functions
125
- # ---------------------------------------------------------------------
126
-
127
- #
128
- # Is there a redirect page set in the running app?
129
- #
130
- def redirect_set?
131
- return false unless @engine.app_running?
132
- return @engine.running_app.obj.redirect
133
- end
134
-
135
- #
136
- # Is there a redirect page set in the running app?
137
- #
138
- def redirect_hard_set?
139
- return false unless @engine.app_running?
140
- return @engine.running_app.obj.redirect_hard
141
- end
142
-
143
- #
144
- # Return a redirect result.
145
- #
146
- def server_redirect_result
147
- target = @engine.running_app.obj.redirect_hard
148
-
149
- return Gloo::WebSvr::Response.redirect_response( @engine, target )
150
- end
151
-
152
- end
153
- end
154
- end
@@ -1,143 +0,0 @@
1
- # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
- # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
- #
4
- # A web Request for a page, action, or static resource.
5
- #
6
- # Kinds of Resources
7
- # Web Page
8
- # Action - does something and redirects to a page (or returns nothing)
9
- # API - returns JSON instead of HTML (but is that different from Web Page?)
10
- # Static Resource - File, PDF, Image, etc.
11
- #
12
- #
13
- # See More doc here:
14
- # https://www.rubydoc.info/gems/rack/Rack/Request/Helpers#path-instance_method
15
- #
16
-
17
- module Gloo
18
- module WebSvr
19
- class Request
20
-
21
- REQUEST_METHOD = 'REQUEST_METHOD'.freeze
22
- REQUEST_PATH = 'REQUEST_PATH'.freeze
23
- HTTP_HOST = 'HTTP_HOST'.freeze
24
- QUERY_STRING = 'QUERY_STRING'.freeze
25
-
26
- attr_reader :method, :host, :path, :ip, :query
27
- attr_reader :db, :elapsed
28
- attr_accessor :request_params
29
-
30
-
31
- # ---------------------------------------------------------------------
32
- # Initialization
33
- # ---------------------------------------------------------------------
34
-
35
- #
36
- # Set up the web server.
37
- #
38
- def initialize( engine, handler, env = nil )
39
- @engine = engine
40
- @log = @engine.log
41
- @request_params = RequestParams.new( @log )
42
-
43
- @handler = handler
44
-
45
- @env = env
46
- detect_env
47
- end
48
-
49
-
50
- # ---------------------------------------------------------------------
51
- # Process Request
52
- # ---------------------------------------------------------------------
53
-
54
- #
55
- # Process the request and return a result.
56
- #
57
- def process
58
- start_timer
59
-
60
- # Run the on_request script if there is one.
61
- @handler.server_obj.set_request_data self
62
-
63
- # Check authenticity token if it's given.
64
- if @request_params.check_authenticity_token( @engine )
65
- result, page_obj = @handler.handle self
66
- else
67
- # Render the error page.
68
- result = @handler.server_error_result
69
- end
70
-
71
- finish_timer
72
-
73
- # Run the on_response script if there is one.
74
- @handler.server_obj.set_response_data( self, result, page_obj )
75
- @handler.server_obj.run_on_response
76
-
77
- return result
78
- end
79
-
80
-
81
- # ---------------------------------------------------------------------
82
- # ENV
83
- # ---------------------------------------------------------------------
84
-
85
- #
86
- # Write the request information to the log.
87
- #
88
- def detect_env
89
- req = Rack::Request.new( @env )
90
-
91
- @method = req.request_method
92
- @path = req.path
93
- @host = req.host_with_port
94
- @query = req.query_string
95
-
96
- @request_params.init_query_params( @query )
97
- @ip = req.ip
98
- @handler.server_obj.session.set_session_data_for_request( @env )
99
-
100
- @request_params.init_body_params( @env[ 'rack.input' ].read )
101
- @method = @request_params.get_body_method_override @method
102
- end
103
-
104
-
105
- # ---------------------------------------------------------------------
106
- # Request timer
107
- # ---------------------------------------------------------------------
108
-
109
- #
110
- # Keep track of the request start time.
111
- #
112
- def start_timer
113
- @start = Time.now
114
- @engine.running_app.reset_db_time
115
- end
116
-
117
- #
118
- # Write the request completion time to the log.
119
- #
120
- def finish_timer
121
- @finish = Time.now
122
- @elapsed = ( ( @finish - @start ) * 1000.0 ).round(2)
123
- @db = @engine.running_app.db_time
124
- @log.info "*** Web request complete. DB: #{@db} ms. Elapsed time: #{@elapsed} ms"
125
- end
126
-
127
-
128
- # ---------------------------------------------------------------------
129
- # Helper functions
130
- # ---------------------------------------------------------------------
131
-
132
- #
133
- # Write the request information to the log.
134
- #
135
- def log
136
- @log.info "#{@method} #{@host}#{@path}"
137
-
138
- @request_params.log_params
139
- end
140
-
141
- end
142
- end
143
- end
@@ -1,181 +0,0 @@
1
- # Author:: Eric Crane (mailto:eric.crane@mac.com)
2
- # Copyright:: Copyright (c) 2024 Eric Crane. All rights reserved.
3
- #
4
- # A Parameters associated with a request.
5
- #
6
- # Kinds of Params
7
- # Id - The entity id
8
- # Key - URL parameter key
9
- # URL Params - Parameters in the URL
10
- # Body Params - Data from the body of the request
11
- #
12
-
13
- module Gloo
14
- module WebSvr
15
- class RequestParams
16
-
17
- attr_accessor :id, :route_params
18
- attr_reader :query_params, :body_params, :body_binary
19
-
20
- # ---------------------------------------------------------------------
21
- # Initialization
22
- # ---------------------------------------------------------------------
23
-
24
- #
25
- # Set up the web server.
26
- #
27
- def initialize( log )
28
- @log = log
29
- end
30
-
31
-
32
- # ---------------------------------------------------------------------
33
- # Value Detection
34
- # ---------------------------------------------------------------------
35
-
36
- #
37
- # Detect the parameters from query string.
38
- #
39
- def init_query_params query_string
40
- if query_string
41
- @query_params = Rack::Utils.parse_query( query_string )
42
- else
43
- @query_params = {}
44
- end
45
- end
46
-
47
- #
48
- # Detect the parameters from the body of the request.
49
- #
50
- def init_body_params body
51
- if body && body.length > 0
52
- # if body is binary, then it is not a query string
53
- begin
54
- @body_params = Rack::Utils.parse_query body
55
- rescue => exception
56
- init_multipart body
57
- end
58
- else
59
- @body_params = {}
60
- end
61
- end
62
-
63
- #
64
- # Set the body to a binary file.
65
- #
66
- # TODO: find a lib or method to handle this.
67
- # This is very rough and will need to be fixed.
68
- #
69
- def init_multipart body
70
- # puts "*********** first lines: *********** "
71
- # body.lines[0..3].each { |line| puts line }
72
- # puts "*********** last lines: *********** "
73
- # body.lines.last(5).each { |line| puts line }
74
- # puts "************************************"
75
-
76
- # boundary = body.lines.first
77
- # puts "boundary: #{boundary}"
78
-
79
- header = body.lines[1..3].join
80
- # puts "header: #{header}"
81
-
82
- footer = body.lines.last(5).join
83
- # puts "footer: #{footer}"
84
-
85
- binary_data = body.lines[4..-6].join
86
- # puts "binary_data length: #{binary_data.length}"
87
- # puts "binary first line: #{binary_data.lines.first}"
88
- # puts "binary last line: #{binary_data.lines.last}"
89
-
90
- i = header.lines.first.index( 'filename=' )
91
- filename = header.lines.first[ i+10..-4 ]
92
- content_type = header.lines.second[14..-3]
93
- # puts "filename: #{filename}"
94
- # puts "content_type: #{content_type}"
95
-
96
- @body_binary = body
97
- @body_params = {}
98
- @body_params[ 'content_type' ] = content_type
99
- @body_params[ 'file_name' ] = filename
100
- @body_params[ 'file_size' ] = binary_data.length
101
- @body_params[ 'file_data' ] = binary_data
102
- end
103
-
104
-
105
- # ---------------------------------------------------------------------
106
- # Authenticity Token checking
107
- # ---------------------------------------------------------------------
108
-
109
- #
110
- # Check the authenticity token if it is present.
111
- # Returns true if it is present and valid, and
112
- # also if it is not present.
113
- # Returns false if it is present but not valid.
114
- #
115
- def check_authenticity_token engine
116
- auth_token = @query_params[ Gloo::Objs::CsrfToken::AUTHENTICITY_TOKEN ]
117
- if auth_token
118
- session_id = engine.running_app.obj&.session&.get_session_id
119
- return false unless session_id
120
-
121
- return Gloo::Objs::CsrfToken.valid_csrf_token?( session_id, auth_token )
122
- end
123
-
124
- return true
125
- end
126
-
127
-
128
- # ---------------------------------------------------------------------
129
- # Helper functions
130
- # ---------------------------------------------------------------------
131
-
132
- #
133
- # Check the body to see if there is a PATCH or a PUT in
134
- # the method override.
135
- #
136
- def get_body_method_override orig_method
137
- if @body_params[ '_method' ]
138
- return @body_params[ '_method' ].upcase
139
- end
140
- return orig_method
141
- end
142
-
143
- #
144
- # Write the querey and body params to the log.
145
- #
146
- def log_params
147
- return unless @log
148
-
149
- if @query_params && ! @query_params.empty?
150
- @log.info "--- Query Parameters: #{@query_params}"
151
- end
152
-
153
- if @body_params && ! @body_params.empty?
154
- if @body_params[ 'file_data' ]
155
- # exclude the file data from the params shown
156
- params = @body_params.dup
157
- params.delete( 'file_data' )
158
- params[ 'file_data' ] = '...'
159
- @log.info "--- Body Parameters: #{params}"
160
- else
161
- @log.info "--- Body Parameters: #{@body_params}"
162
- end
163
- end
164
- end
165
-
166
- #
167
- # Write the id and route params to the log.
168
- #
169
- def log_id_keys
170
- return unless @log
171
-
172
- @log.info "--- ID Parameter: #{@id}" if @id
173
-
174
- if @route_params && ! @route_params.empty?
175
- @log.info "--- Route Parameters: #{@route_params}"
176
- end
177
- end
178
-
179
- end
180
- end
181
- end