Module: Legion::API::Helpers
- Defined in:
- lib/legion/api/acp.rb,
lib/legion/api/helpers.rb
Defined Under Namespace
Modules: Acp
Instance Method Summary collapse
- #authenticated? ⇒ Boolean
- #build_schedule_attrs(body) ⇒ Object
- #build_schedule_updates(body) ⇒ Object
- #current_claims ⇒ Object
- #current_owner_msid ⇒ Object
- #current_worker_id ⇒ Object
- #find_extension_module(lex_name) ⇒ Object
- #find_or_halt(model_class, id) ⇒ Object
- #find_runner_info(ext_mod, runner_name) ⇒ Object
- #halt_not_found(message) ⇒ Object
- #json_collection(dataset, status_code: 200) ⇒ Object
- #json_error(code, message, status_code: 400) ⇒ Object
- #json_response(data, status_code: 200) ⇒ Object
- #parse_request_body ⇒ Object
- #redact_hash(hash, sensitive_keys: %i[password secret token key cert private_key api_key])) ⇒ Object
- #require_data! ⇒ Object
- #require_knowledge_ingest! ⇒ Object
- #require_knowledge_maintenance! ⇒ Object
- #require_knowledge_monitor! ⇒ Object
- #require_knowledge_query! ⇒ Object
- #require_mesh! ⇒ Object
- #require_scheduler! ⇒ Object
- #require_trace_search! ⇒ Object
- #runner_summaries(ext_mod) ⇒ Object
- #transport_subclasses(base_class) ⇒ Object
Instance Method Details
#authenticated? ⇒ Boolean
202 203 204 |
# File 'lib/legion/api/helpers.rb', line 202 def authenticated? !current_claims.nil? end |
#build_schedule_attrs(body) ⇒ Object
168 169 170 171 172 173 174 175 176 |
# File 'lib/legion/api/helpers.rb', line 168 def build_schedule_attrs(body) attrs = { function_id: body[:function_id].to_i, active: body.fetch(:active, true), last_run: Time.at(0) } attrs[:cron] = body[:cron] if body[:cron] attrs[:interval] = body[:interval].to_i if body[:interval] attrs[:task_ttl] = body[:task_ttl].to_i if body[:task_ttl] attrs[:payload] = Legion::JSON.dump(body[:payload] || {}) attrs[:transformation] = body[:transformation] if body[:transformation] attrs end |
#build_schedule_updates(body) ⇒ Object
178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/legion/api/helpers.rb', line 178 def build_schedule_updates(body) updates = {} updates[:cron] = body[:cron] if body.key?(:cron) updates[:interval] = body[:interval].to_i if body.key?(:interval) updates[:active] = body[:active] if body.key?(:active) updates[:task_ttl] = body[:task_ttl].to_i if body.key?(:task_ttl) updates[:function_id] = body[:function_id].to_i if body.key?(:function_id) updates[:payload] = Legion::JSON.dump(body[:payload]) if body.key?(:payload) updates[:transformation] = body[:transformation] if body.key?(:transformation) updates end |
#current_claims ⇒ Object
190 191 192 |
# File 'lib/legion/api/helpers.rb', line 190 def current_claims env['legion.auth'] end |
#current_owner_msid ⇒ Object
198 199 200 |
# File 'lib/legion/api/helpers.rb', line 198 def current_owner_msid env['legion.owner_msid'] end |
#current_worker_id ⇒ Object
194 195 196 |
# File 'lib/legion/api/helpers.rb', line 194 def current_worker_id env['legion.worker_id'] end |
#find_extension_module(lex_name) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/legion/api/helpers.rb', line 104 def find_extension_module(lex_name) short = lex_name.delete_prefix('lex-') short_no_sep = short.tr('-', '_').delete('_') Legion::Extensions.loaded_extension_modules.find do |mod| parts = mod.name&.split('::') mod_short = parts&.last&.downcase mod_short == short.tr('-', '_') || mod_short == short.delete('-') || mod_short == short_no_sep end end |
#find_or_halt(model_class, id) ⇒ Object
137 138 139 140 141 |
# File 'lib/legion/api/helpers.rb', line 137 def find_or_halt(model_class, id) record = model_class[id.to_i] halt 404, json_error('not_found', "#{model_class.name.split('::').last} #{id} not found", status_code: 404) if record.nil? record end |
#find_runner_info(ext_mod, runner_name) ⇒ Object
116 117 118 119 120 121 122 |
# File 'lib/legion/api/helpers.rb', line 116 def find_runner_info(ext_mod, runner_name) return nil unless ext_mod.respond_to?(:runners) ext_mod.runners.values.find do |r| r[:runner_name].to_s.downcase == runner_name.downcase end end |
#halt_not_found(message) ⇒ Object
133 134 135 |
# File 'lib/legion/api/helpers.rb', line 133 def halt_not_found() halt 404, json_error('not_found', , status_code: 404) end |
#json_collection(dataset, status_code: 200) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/legion/api/helpers.rb', line 15 def json_collection(dataset, status_code: 200) content_type :json status status_code paginated = paginate(dataset) items = paginated.respond_to?(:all) ? paginated.all : Array(paginated) total = collection_total(dataset, items) = .merge( count: items.length, limit: page_limit, offset: page_offset ) [:total] = total unless total.nil? [:has_more] = collection_has_more?(items, total) Legion::JSON.dump({ data: items.map { |r| r.respond_to?(:values) ? r.values : r }, meta: }) end |
#json_error(code, message, status_code: 400) ⇒ Object
36 37 38 39 40 41 42 43 |
# File 'lib/legion/api/helpers.rb', line 36 def json_error(code, , status_code: 400) content_type :json status status_code Legion::JSON.dump({ error: { code: code, message: }, meta: }) end |
#json_response(data, status_code: 200) ⇒ Object
6 7 8 9 10 11 12 13 |
# File 'lib/legion/api/helpers.rb', line 6 def json_response(data, status_code: 200) content_type :json status status_code Legion::JSON.dump({ data: data, meta: }) end |
#parse_request_body ⇒ Object
94 95 96 97 98 99 100 101 102 |
# File 'lib/legion/api/helpers.rb', line 94 def parse_request_body body = request.body.read return {} if body.nil? || body.empty? Legion::JSON.load(body).transform_keys(&:to_sym) rescue StandardError => e Legion::Logging.warn "API#parse_request_body failed to parse JSON: #{e.}" if defined?(Legion::Logging) halt 400, json_error('invalid_json', 'request body is not valid JSON', status_code: 400) end |
#redact_hash(hash, sensitive_keys: %i[password secret token key cert private_key api_key])) ⇒ Object
143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/legion/api/helpers.rb', line 143 def redact_hash(hash, sensitive_keys: %i[password secret token key cert private_key api_key]) return hash unless hash.is_a?(Hash) hash.each_with_object({}) do |(k, v), result| key_sym = k.to_sym result[k] = if v.is_a?(Hash) redact_hash(v, sensitive_keys: sensitive_keys) elsif sensitive_keys.any? { |s| key_sym.to_s.include?(s.to_s) } '[REDACTED]' else v end end end |
#require_data! ⇒ Object
45 46 47 48 49 |
# File 'lib/legion/api/helpers.rb', line 45 def require_data! return if Legion::Settings[:data][:connected] halt 503, json_error('data_unavailable', 'legion-data is not connected', status_code: 503) end |
#require_knowledge_ingest! ⇒ Object
64 65 66 67 68 |
# File 'lib/legion/api/helpers.rb', line 64 def require_knowledge_ingest! return if defined?(Legion::Extensions::Knowledge::Runners::Ingest) halt 503, json_error('knowledge_unavailable', 'lex-knowledge is not loaded', status_code: 503) end |
#require_knowledge_maintenance! ⇒ Object
70 71 72 73 74 |
# File 'lib/legion/api/helpers.rb', line 70 def require_knowledge_maintenance! return if defined?(Legion::Extensions::Knowledge::Runners::Maintenance) halt 503, json_error('knowledge_unavailable', 'lex-knowledge is not loaded', status_code: 503) end |
#require_knowledge_monitor! ⇒ Object
76 77 78 79 80 |
# File 'lib/legion/api/helpers.rb', line 76 def require_knowledge_monitor! return if defined?(Legion::Extensions::Knowledge::Runners::Monitor) halt 503, json_error('knowledge_unavailable', 'lex-knowledge is not loaded', status_code: 503) end |
#require_knowledge_query! ⇒ Object
58 59 60 61 62 |
# File 'lib/legion/api/helpers.rb', line 58 def require_knowledge_query! return if defined?(Legion::Extensions::Knowledge::Runners::Query) halt 503, json_error('knowledge_unavailable', 'lex-knowledge is not loaded', status_code: 503) end |
#require_mesh! ⇒ Object
82 83 84 85 86 |
# File 'lib/legion/api/helpers.rb', line 82 def require_mesh! return if defined?(Legion::Extensions::Mesh) halt 503, json_error('mesh_unavailable', 'lex-mesh is not loaded', status_code: 503) end |
#require_scheduler! ⇒ Object
51 52 53 54 55 56 |
# File 'lib/legion/api/helpers.rb', line 51 def require_scheduler! require_data! return if defined?(Legion::Extensions::Scheduler) halt 503, json_error('scheduler_unavailable', 'lex-scheduler is not loaded', status_code: 503) end |
#require_trace_search! ⇒ Object
88 89 90 91 92 |
# File 'lib/legion/api/helpers.rb', line 88 def require_trace_search! return if defined?(Legion::TraceSearch) && defined?(Legion::LLM) halt 503, json_error('trace_search_unavailable', 'TraceSearch requires LLM subsystem', status_code: 503) end |
#runner_summaries(ext_mod) ⇒ Object
124 125 126 127 128 129 130 131 |
# File 'lib/legion/api/helpers.rb', line 124 def runner_summaries(ext_mod) return [] unless ext_mod.respond_to?(:runners) ext_mod.runners.values.map do |r| functions = r[:runner_module]&.instance_methods(false)&.map(&:to_s) || [] { name: r[:runner_name], runner_class: r[:runner_class], functions: functions } end end |
#transport_subclasses(base_class) ⇒ Object
158 159 160 161 162 163 164 165 166 |
# File 'lib/legion/api/helpers.rb', line 158 def transport_subclasses(base_class) ObjectSpace.each_object(Class) .select { |klass| klass < base_class } .map { |klass| { name: klass.name } } .sort_by { |h| h[:name].to_s } rescue NameError => e Legion::Logging.debug "API#transport_subclasses failed for #{base_class}: #{e.}" if defined?(Legion::Logging) [] end |