otto 1.6.0 → 2.0.0.pre2
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 +4 -4
- data/.github/workflows/ci.yml +3 -2
- data/.github/workflows/claude-code-review.yml +53 -0
- data/.github/workflows/claude.yml +49 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +26 -344
- data/CHANGELOG.rst +131 -0
- data/CLAUDE.md +56 -0
- data/Gemfile +11 -4
- data/Gemfile.lock +38 -42
- data/README.md +2 -0
- data/bin/rspec +4 -4
- data/changelog.d/README.md +120 -0
- data/changelog.d/scriv.ini +5 -0
- data/docs/.gitignore +2 -0
- data/docs/migrating/v2.0.0-pre1.md +276 -0
- data/docs/migrating/v2.0.0-pre2.md +345 -0
- data/examples/.gitignore +1 -0
- data/examples/advanced_routes/README.md +33 -0
- data/examples/advanced_routes/app/controllers/handlers/async.rb +9 -0
- data/examples/advanced_routes/app/controllers/handlers/dynamic.rb +9 -0
- data/examples/advanced_routes/app/controllers/handlers/static.rb +9 -0
- data/examples/advanced_routes/app/controllers/modules/auth.rb +9 -0
- data/examples/advanced_routes/app/controllers/modules/transformer.rb +9 -0
- data/examples/advanced_routes/app/controllers/modules/validator.rb +9 -0
- data/examples/advanced_routes/app/controllers/routes_app.rb +232 -0
- data/examples/advanced_routes/app/controllers/v2/admin.rb +9 -0
- data/examples/advanced_routes/app/controllers/v2/config.rb +9 -0
- data/examples/advanced_routes/app/controllers/v2/settings.rb +9 -0
- data/examples/advanced_routes/app/logic/admin/logic/manager.rb +27 -0
- data/examples/advanced_routes/app/logic/admin/panel.rb +27 -0
- data/examples/advanced_routes/app/logic/analytics_processor.rb +25 -0
- data/examples/advanced_routes/app/logic/complex/business/handler.rb +27 -0
- data/examples/advanced_routes/app/logic/data_logic.rb +23 -0
- data/examples/advanced_routes/app/logic/data_processor.rb +25 -0
- data/examples/advanced_routes/app/logic/input_validator.rb +24 -0
- data/examples/advanced_routes/app/logic/nested/feature/logic.rb +27 -0
- data/examples/advanced_routes/app/logic/reports_generator.rb +27 -0
- data/examples/advanced_routes/app/logic/simple_logic.rb +25 -0
- data/examples/advanced_routes/app/logic/system/config/manager.rb +27 -0
- data/examples/advanced_routes/app/logic/test_logic.rb +23 -0
- data/examples/advanced_routes/app/logic/transform_logic.rb +23 -0
- data/examples/advanced_routes/app/logic/upload_logic.rb +23 -0
- data/examples/advanced_routes/app/logic/v2/logic/dashboard.rb +27 -0
- data/examples/advanced_routes/app/logic/v2/logic/processor.rb +27 -0
- data/examples/advanced_routes/app.rb +33 -0
- data/examples/advanced_routes/config.rb +23 -0
- data/examples/advanced_routes/config.ru +7 -0
- data/examples/advanced_routes/puma.rb +20 -0
- data/examples/advanced_routes/routes +167 -0
- data/examples/advanced_routes/run.rb +39 -0
- data/examples/advanced_routes/test.rb +58 -0
- data/examples/authentication_strategies/README.md +32 -0
- data/examples/authentication_strategies/app/auth.rb +68 -0
- data/examples/authentication_strategies/app/controllers/auth_controller.rb +29 -0
- data/examples/authentication_strategies/app/controllers/main_controller.rb +28 -0
- data/examples/authentication_strategies/config.ru +24 -0
- data/examples/authentication_strategies/routes +37 -0
- data/examples/basic/README.md +29 -0
- data/examples/basic/app.rb +7 -35
- data/examples/basic/routes +0 -9
- data/examples/mcp_demo/README.md +87 -0
- data/examples/mcp_demo/app.rb +29 -34
- data/examples/mcp_demo/config.ru +9 -60
- data/examples/security_features/README.md +46 -0
- data/examples/security_features/app.rb +23 -24
- data/examples/security_features/config.ru +8 -10
- data/lib/otto/core/configuration.rb +167 -0
- data/lib/otto/core/error_handler.rb +86 -0
- data/lib/otto/core/file_safety.rb +61 -0
- data/lib/otto/core/middleware_stack.rb +237 -0
- data/lib/otto/core/router.rb +184 -0
- data/lib/otto/core/uri_generator.rb +44 -0
- data/lib/otto/design_system.rb +7 -5
- data/lib/otto/env_keys.rb +114 -0
- data/lib/otto/helpers/base.rb +5 -21
- data/lib/otto/helpers/request.rb +10 -8
- data/lib/otto/helpers/response.rb +27 -4
- data/lib/otto/helpers/validation.rb +9 -7
- data/lib/otto/mcp/auth/token.rb +10 -9
- data/lib/otto/mcp/protocol.rb +24 -27
- data/lib/otto/mcp/rate_limiting.rb +8 -3
- data/lib/otto/mcp/registry.rb +7 -2
- data/lib/otto/mcp/route_parser.rb +10 -15
- data/lib/otto/mcp/{validation.rb → schema_validation.rb} +16 -11
- data/lib/otto/mcp/server.rb +45 -22
- data/lib/otto/response_handlers/auto.rb +39 -0
- data/lib/otto/response_handlers/base.rb +16 -0
- data/lib/otto/response_handlers/default.rb +16 -0
- data/lib/otto/response_handlers/factory.rb +39 -0
- data/lib/otto/response_handlers/json.rb +34 -0
- data/lib/otto/response_handlers/redirect.rb +25 -0
- data/lib/otto/response_handlers/view.rb +24 -0
- data/lib/otto/response_handlers.rb +9 -135
- data/lib/otto/route.rb +51 -55
- data/lib/otto/route_definition.rb +15 -18
- data/lib/otto/route_handlers/base.rb +121 -0
- data/lib/otto/route_handlers/class_method.rb +89 -0
- data/lib/otto/route_handlers/factory.rb +42 -0
- data/lib/otto/route_handlers/instance_method.rb +69 -0
- data/lib/otto/route_handlers/lambda.rb +59 -0
- data/lib/otto/route_handlers/logic_class.rb +93 -0
- data/lib/otto/route_handlers.rb +10 -405
- data/lib/otto/security/authentication/auth_strategy.rb +44 -0
- data/lib/otto/security/authentication/authentication_middleware.rb +140 -0
- data/lib/otto/security/authentication/failure_result.rb +44 -0
- data/lib/otto/security/authentication/route_auth_wrapper.rb +149 -0
- data/lib/otto/security/authentication/strategies/api_key_strategy.rb +40 -0
- data/lib/otto/security/authentication/strategies/noauth_strategy.rb +19 -0
- data/lib/otto/security/authentication/strategies/permission_strategy.rb +47 -0
- data/lib/otto/security/authentication/strategies/role_strategy.rb +57 -0
- data/lib/otto/security/authentication/strategies/session_strategy.rb +41 -0
- data/lib/otto/security/authentication/strategy_result.rb +337 -0
- data/lib/otto/security/authentication.rb +28 -282
- data/lib/otto/security/config.rb +14 -23
- data/lib/otto/security/configurator.rb +219 -0
- data/lib/otto/security/csrf.rb +8 -143
- data/lib/otto/security/middleware/csrf_middleware.rb +151 -0
- data/lib/otto/security/middleware/rate_limit_middleware.rb +54 -0
- data/lib/otto/security/middleware/validation_middleware.rb +252 -0
- data/lib/otto/security/rate_limiter.rb +86 -0
- data/lib/otto/security/rate_limiting.rb +10 -105
- data/lib/otto/security/validator.rb +8 -253
- data/lib/otto/static.rb +3 -0
- data/lib/otto/utils.rb +14 -0
- data/lib/otto/version.rb +3 -1
- data/lib/otto.rb +141 -498
- data/otto.gemspec +4 -2
- metadata +99 -18
- data/examples/dynamic_pages/app.rb +0 -115
- data/examples/dynamic_pages/config.ru +0 -30
- data/examples/dynamic_pages/routes +0 -21
- data/examples/helpers_demo/app.rb +0 -244
- data/examples/helpers_demo/config.ru +0 -26
- data/examples/helpers_demo/routes +0 -7
- data/lib/concurrent_cache_store.rb +0 -68
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'time'
|
|
5
|
+
|
|
6
|
+
# Main application class demonstrating advanced routes syntax
|
|
7
|
+
class RoutesApp
|
|
8
|
+
# ========================================
|
|
9
|
+
# BASIC ROUTES
|
|
10
|
+
# ========================================
|
|
11
|
+
|
|
12
|
+
def self.index
|
|
13
|
+
[200, { 'content-type' => 'text/html' }, ['<h1>Advanced Routes Syntax Example</h1><p>Otto v1.5.0+ Features</p>']]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.receive_feedback
|
|
17
|
+
[200, { 'content-type' => 'text/plain' }, ['Feedback received']]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# ========================================
|
|
21
|
+
# RESPONSE TYPE ROUTES
|
|
22
|
+
# ========================================
|
|
23
|
+
|
|
24
|
+
def self.list_users
|
|
25
|
+
users = [
|
|
26
|
+
{ id: 1, name: 'Alice', role: 'admin' },
|
|
27
|
+
{ id: 2, name: 'Bob', role: 'user' },
|
|
28
|
+
]
|
|
29
|
+
[200, { 'content-type' => 'application/json' }, [users.to_json]]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.create_user
|
|
33
|
+
[201, { 'content-type' => 'application/json' }, ['{"message": "User created", "id": 3}']]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.health_check
|
|
37
|
+
[200, { 'content-type' => 'application/json' }, ['{"status": "healthy", "timestamp": "' + Time.now.iso8601 + '"}']]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.update_user
|
|
41
|
+
[200, { 'content-type' => 'application/json' }, ['{"message": "User updated"}']]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.delete_user
|
|
45
|
+
[204, {}, ['']]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.dashboard
|
|
49
|
+
[200, { 'content-type' => 'text/html' }, ['<h1>Dashboard</h1><p>HTML view response</p>']]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.reports
|
|
53
|
+
[200, { 'content-type' => 'text/html' }, ['<h1>Reports</h1><p>View response type demonstration</p>']]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.admin_panel
|
|
57
|
+
[200, { 'content-type' => 'text/html' }, ['<h1>Admin Panel</h1><p>Administrative interface</p>']]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.login_redirect
|
|
61
|
+
[302, { 'location' => '/dashboard' }, ['']]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self.logout_redirect
|
|
65
|
+
[302, { 'location' => '/' }, ['']]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.home_redirect
|
|
69
|
+
[302, { 'location' => '/dashboard' }, ['']]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.flexible_data
|
|
73
|
+
data = { message: 'This is flexible data', timestamp: Time.now.iso8601 }
|
|
74
|
+
[200, { 'content-type' => 'application/json' }, [data.to_json]]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def self.flexible_content
|
|
78
|
+
[200, { 'content-type' => 'application/json' }, ['{"content": "Auto response type", "format": "negotiated"}']]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# ========================================
|
|
82
|
+
# CSRF ROUTES
|
|
83
|
+
# ========================================
|
|
84
|
+
|
|
85
|
+
def self.webhook_handler
|
|
86
|
+
[200, { 'content-type' => 'application/json' }, ['{"message": "Webhook processed (CSRF exempt)"}']]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def self.external_update
|
|
90
|
+
[200, { 'content-type' => 'application/json' }, ['{"message": "External update processed"}']]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def self.cleanup_data
|
|
94
|
+
[200, { 'content-type' => 'application/json' }, ['{"message": "Data cleanup completed"}']]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def self.sync_data
|
|
98
|
+
[200, { 'content-type' => 'application/json' }, ['{"message": "Data sync completed"}']]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def self.update_settings
|
|
102
|
+
[200, { 'content-type' => 'text/plain' }, ['Settings updated (CSRF protected)']]
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def self.change_password
|
|
106
|
+
[200, { 'content-type' => 'text/plain' }, ['Password changed (CSRF protected)']]
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def self.delete_profile
|
|
110
|
+
[204, {}, ['']]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# ========================================
|
|
114
|
+
# MULTIPLE PARAMETER COMBINATIONS
|
|
115
|
+
# ========================================
|
|
116
|
+
|
|
117
|
+
def self.api_data
|
|
118
|
+
[200, { 'content-type' => 'application/json' }, ['{"api": "v1", "data": "response"}']]
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def self.api_submit
|
|
122
|
+
[201, { 'content-type' => 'application/json' }, ['{"message": "API submission processed"}']]
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def self.api_update
|
|
126
|
+
[200, { 'content-type' => 'application/json' }, ['{"message": "API update completed"}']]
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def self.admin_dashboard
|
|
130
|
+
[200, { 'content-type' => 'text/html' }, ['<h1>Admin Dashboard</h1><p>Administrative view</p>']]
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def self.admin_settings
|
|
134
|
+
[200, { 'content-type' => 'text/html' }, ['<h1>Admin Settings</h1><p>Settings updated</p>']]
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def self.mixed_content
|
|
138
|
+
[200, { 'content-type' => 'application/json' }, ['{"type": "mixed", "csrf": "exempt", "response": "auto"}']]
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# ========================================
|
|
142
|
+
# CUSTOM PARAMETERS
|
|
143
|
+
# ========================================
|
|
144
|
+
|
|
145
|
+
def self.show_config
|
|
146
|
+
[200, { 'content-type' => 'application/json' }, ['{"environment": "production", "config": "displayed"}']]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def self.debug_info
|
|
150
|
+
[200, { 'content-type' => 'application/json' }, ['{"environment": "development", "debug": true}']]
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def self.update_config
|
|
154
|
+
[200, { 'content-type' => 'application/json' }, ['{"message": "Config updated", "environment": "production"}']]
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def self.feature_flags
|
|
158
|
+
[200, { 'content-type' => 'application/json' }, ['{"feature": "advanced", "mode": "enabled", "flags": []}']]
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def self.toggle_feature
|
|
162
|
+
[200, { 'content-type' => 'application/json' }, ['{"feature": "beta", "mode": "test", "toggled": true}']]
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# ========================================
|
|
166
|
+
# PARAMETER VALUE VARIATIONS
|
|
167
|
+
# ========================================
|
|
168
|
+
|
|
169
|
+
def self.api_v1
|
|
170
|
+
[200, { 'content-type' => 'application/json' }, ['{"version": "1.0", "api": "v1"}']]
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def self.api_v2
|
|
174
|
+
[200, { 'content-type' => 'application/json' }, ['{"version": "2.0", "api": "v2"}']]
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def self.api_legacy
|
|
178
|
+
[200, { 'content-type' => 'application/json' }, ['{"version": "legacy", "deprecated": true}']]
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def self.complex_query
|
|
182
|
+
[200, { 'content-type' => 'application/json' }, ['{"query": "complex", "filter": "key=value"}']]
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def self.config_db
|
|
186
|
+
[200, { 'content-type' => 'application/json' }, ['{"connection": "host=localhost", "configured": true}']]
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# ========================================
|
|
190
|
+
# ERROR HANDLERS
|
|
191
|
+
# ========================================
|
|
192
|
+
|
|
193
|
+
def self.not_found
|
|
194
|
+
[404, { 'content-type' => 'text/html' }, ['<h1>404 - Page Not Found</h1><p>Advanced routes syntax example</p>']]
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def self.server_error
|
|
198
|
+
[500, { 'content-type' => 'text/html' }, ['<h1>500 - Server Error</h1><p>Something went wrong</p>']]
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# ========================================
|
|
202
|
+
# TESTING ROUTES
|
|
203
|
+
# ========================================
|
|
204
|
+
|
|
205
|
+
def self.test_json
|
|
206
|
+
[200, { 'content-type' => 'application/json' }, ['{"test": "json", "response_type": "json"}']]
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def self.test_view
|
|
210
|
+
[200, { 'content-type' => 'text/html' }, ['<h1>Test View</h1><p>HTML view response</p>']]
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def self.test_redirect
|
|
214
|
+
[302, { 'location' => '/' }, ['']]
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def self.test_auto
|
|
218
|
+
[200, { 'content-type' => 'application/json' }, ['{"test": "auto", "response_type": "auto"}']]
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def self.test_csrf
|
|
222
|
+
[200, { 'content-type' => 'text/html' }, ['<h1>CSRF Test</h1><p>POST request (CSRF protected)</p>']]
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def self.test_no_csrf
|
|
226
|
+
[200, { 'content-type' => 'text/html' }, ['<h1>No CSRF Test</h1><p>POST request (CSRF exempt)</p>']]
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def self.test_everything
|
|
230
|
+
[200, { 'content-type' => 'application/json' }, ['{"message": "All parameters tested", "csrf": "exempt", "custom": "value"}']]
|
|
231
|
+
end
|
|
232
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Admin
|
|
4
|
+
module Logic
|
|
5
|
+
class Manager
|
|
6
|
+
attr_reader :context, :params, :locale
|
|
7
|
+
|
|
8
|
+
def initialize(context, params, locale)
|
|
9
|
+
@context = context
|
|
10
|
+
@params = params
|
|
11
|
+
@locale = locale
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def process
|
|
15
|
+
{
|
|
16
|
+
admin_manager: 'Active',
|
|
17
|
+
namespace: 'Admin::Logic',
|
|
18
|
+
management_tools: ['users', 'settings', 'logs'],
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def response_data
|
|
23
|
+
{ admin_logic_manager: process }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Admin
|
|
4
|
+
class Panel
|
|
5
|
+
attr_reader :context, :params, :locale
|
|
6
|
+
|
|
7
|
+
def initialize(context, params, locale)
|
|
8
|
+
@context = context
|
|
9
|
+
@params = params
|
|
10
|
+
@locale = locale
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def process
|
|
14
|
+
{
|
|
15
|
+
admin_panel: 'Logic processed',
|
|
16
|
+
namespace: 'Admin',
|
|
17
|
+
access_level: 'admin',
|
|
18
|
+
authenticated: @context.authenticated?,
|
|
19
|
+
has_admin_role: @context.has_role?('admin'),
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def response_data
|
|
24
|
+
{ admin_panel_logic: process }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Analytics
|
|
4
|
+
class Processor
|
|
5
|
+
attr_reader :context, :params, :locale
|
|
6
|
+
|
|
7
|
+
def initialize(context, params, locale)
|
|
8
|
+
@context = context
|
|
9
|
+
@params = params
|
|
10
|
+
@locale = locale
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def process
|
|
14
|
+
{
|
|
15
|
+
analytics: 'Processed',
|
|
16
|
+
metrics: { users: 123, events: 456 },
|
|
17
|
+
period: @params['period'] || 'today',
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def response_data
|
|
22
|
+
{ analytics_processor: process }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Complex
|
|
4
|
+
module Business
|
|
5
|
+
class Handler
|
|
6
|
+
attr_reader :context, :params, :locale
|
|
7
|
+
|
|
8
|
+
def initialize(context, params, locale)
|
|
9
|
+
@context = context
|
|
10
|
+
@params = params
|
|
11
|
+
@locale = locale
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def process
|
|
15
|
+
{
|
|
16
|
+
complex_business: 'Handled',
|
|
17
|
+
namespace: 'Complex::Business',
|
|
18
|
+
business_logic: 'executed',
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def response_data
|
|
23
|
+
{ complex_business_handler: process }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class DataLogic
|
|
4
|
+
attr_reader :context, :params, :locale
|
|
5
|
+
|
|
6
|
+
def initialize(context, params, locale)
|
|
7
|
+
@context = context
|
|
8
|
+
@params = params
|
|
9
|
+
@locale = locale
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def process
|
|
13
|
+
{
|
|
14
|
+
data_logic: 'Processed',
|
|
15
|
+
response_format: 'json',
|
|
16
|
+
input_data: @params,
|
|
17
|
+
}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def response_data
|
|
21
|
+
{ data_logic_result: process }
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class DataProcessor
|
|
4
|
+
attr_reader :context, :params, :locale
|
|
5
|
+
|
|
6
|
+
def initialize(context, params, locale)
|
|
7
|
+
@context = context
|
|
8
|
+
@params = params
|
|
9
|
+
@locale = locale
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def process
|
|
13
|
+
{
|
|
14
|
+
processed: 'Data processing complete',
|
|
15
|
+
input_params: @params.keys,
|
|
16
|
+
timestamp: Time.now.iso8601,
|
|
17
|
+
authenticated: @context.authenticated?,
|
|
18
|
+
user_id: @context.user_id,
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def response_data
|
|
23
|
+
{ data_processor: process }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class InputValidator
|
|
4
|
+
attr_reader :context, :params, :locale
|
|
5
|
+
|
|
6
|
+
def initialize(context, params, locale)
|
|
7
|
+
@context = context
|
|
8
|
+
@params = params
|
|
9
|
+
@locale = locale
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def process
|
|
13
|
+
{
|
|
14
|
+
validation: 'Input validated successfully',
|
|
15
|
+
validated_fields: @params.keys,
|
|
16
|
+
locale: @locale,
|
|
17
|
+
authenticated: @context.authenticated?,
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def response_data
|
|
22
|
+
{ validator: process }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Nested
|
|
4
|
+
module Feature
|
|
5
|
+
class Logic
|
|
6
|
+
attr_reader :context, :params, :locale
|
|
7
|
+
|
|
8
|
+
def initialize(context, params, locale)
|
|
9
|
+
@context = context
|
|
10
|
+
@params = params
|
|
11
|
+
@locale = locale
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def process
|
|
15
|
+
{
|
|
16
|
+
nested_feature: 'Processed',
|
|
17
|
+
depth: 3,
|
|
18
|
+
namespace: 'Nested::Feature',
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def response_data
|
|
23
|
+
{ nested_feature_logic: process }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Reports
|
|
4
|
+
class Generator
|
|
5
|
+
attr_reader :context, :params, :locale
|
|
6
|
+
|
|
7
|
+
def initialize(context, params, locale)
|
|
8
|
+
@context = context
|
|
9
|
+
@params = params
|
|
10
|
+
@locale = locale
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def process
|
|
14
|
+
{
|
|
15
|
+
report_generation: 'Complete',
|
|
16
|
+
namespace: 'Reports',
|
|
17
|
+
data_points: 100,
|
|
18
|
+
authenticated: @context.authenticated?,
|
|
19
|
+
user_permissions: @context.permissions,
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def response_data
|
|
24
|
+
{ report_generator: process }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class SimpleLogic
|
|
4
|
+
attr_reader :context, :params, :locale
|
|
5
|
+
|
|
6
|
+
def initialize(context, params, locale)
|
|
7
|
+
@context = context
|
|
8
|
+
@params = params
|
|
9
|
+
@locale = locale
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def process
|
|
13
|
+
{
|
|
14
|
+
message: 'Simple logic processed',
|
|
15
|
+
params: @params,
|
|
16
|
+
locale: @locale,
|
|
17
|
+
authenticated: @context.authenticated?,
|
|
18
|
+
user: @context.user_name,
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def response_data
|
|
23
|
+
{ simple_logic: process }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module System
|
|
4
|
+
module Config
|
|
5
|
+
class Manager
|
|
6
|
+
attr_reader :context, :params, :locale
|
|
7
|
+
|
|
8
|
+
def initialize(context, params, locale)
|
|
9
|
+
@context = context
|
|
10
|
+
@params = params
|
|
11
|
+
@locale = locale
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def process
|
|
15
|
+
{
|
|
16
|
+
system_config: 'Updated',
|
|
17
|
+
namespace: 'System::Config',
|
|
18
|
+
csrf_exempt: true,
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def response_data
|
|
23
|
+
{ system_config_manager: process }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class TestLogic
|
|
4
|
+
attr_reader :context, :params, :locale
|
|
5
|
+
|
|
6
|
+
def initialize(context, params, locale)
|
|
7
|
+
@context = context
|
|
8
|
+
@params = params
|
|
9
|
+
@locale = locale
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def process
|
|
13
|
+
{
|
|
14
|
+
test: 'Logic class test',
|
|
15
|
+
params_received: @params,
|
|
16
|
+
processing_complete: true,
|
|
17
|
+
}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def response_data
|
|
21
|
+
{ test_logic: process }
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class TransformLogic
|
|
4
|
+
attr_reader :context, :params, :locale
|
|
5
|
+
|
|
6
|
+
def initialize(context, params, locale)
|
|
7
|
+
@context = context
|
|
8
|
+
@params = params
|
|
9
|
+
@locale = locale
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def process
|
|
13
|
+
{
|
|
14
|
+
transformation: 'Complete',
|
|
15
|
+
input_size: @params.to_s.length,
|
|
16
|
+
output_format: 'json',
|
|
17
|
+
}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def response_data
|
|
21
|
+
{ transform_result: process }
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class UploadLogic
|
|
4
|
+
attr_reader :context, :params, :locale
|
|
5
|
+
|
|
6
|
+
def initialize(context, params, locale)
|
|
7
|
+
@context = context
|
|
8
|
+
@params = params
|
|
9
|
+
@locale = locale
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def process
|
|
13
|
+
{
|
|
14
|
+
upload: 'Processing complete',
|
|
15
|
+
csrf_exempt: true,
|
|
16
|
+
files_processed: @params.keys.count,
|
|
17
|
+
}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def response_data
|
|
21
|
+
{ upload_result: process }
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module V2
|
|
4
|
+
module Logic
|
|
5
|
+
class Dashboard
|
|
6
|
+
attr_reader :context, :params, :locale
|
|
7
|
+
|
|
8
|
+
def initialize(context, params, locale)
|
|
9
|
+
@context = context
|
|
10
|
+
@params = params
|
|
11
|
+
@locale = locale
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def process
|
|
15
|
+
{
|
|
16
|
+
v2_dashboard: 'Rendered',
|
|
17
|
+
version: '2.0',
|
|
18
|
+
features: ['metrics', 'charts', 'reports'],
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def response_data
|
|
23
|
+
{ v2_dashboard: process }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|