has_helpers 5.0.2

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 (748) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +38 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +10 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/.tekton/Chart.yaml +14 -0
  8. data/.tekton/templates/pipelinerun.yaml +44 -0
  9. data/.tekton/values-main.yaml +53 -0
  10. data/.tekton/values-pr.yaml +40 -0
  11. data/.tekton/values.yaml +17 -0
  12. data/.tool-versions +1 -0
  13. data/CHANGELOG.md +204 -0
  14. data/Gemfile +25 -0
  15. data/README.md +76 -0
  16. data/Rakefile +46 -0
  17. data/app/api/has_helpers/rack_api.rb +116 -0
  18. data/app/api/has_helpers/search_api.rb +173 -0
  19. data/app/assets/stylesheets/has_helpers/base.scss +5 -0
  20. data/app/assets/stylesheets/has_helpers/color_palette.scss +33 -0
  21. data/app/assets/stylesheets/has_helpers/color_palettes/default.scss +11 -0
  22. data/app/assets/stylesheets/has_helpers/components/dataset.scss +43 -0
  23. data/app/assets/stylesheets/has_helpers/mixins.scss +149 -0
  24. data/app/commands/has_helpers/cards/available_cards_command.rb +98 -0
  25. data/app/commands/has_helpers/cards/card_data_command.rb +1062 -0
  26. data/app/commands/reports/base_options.rb +79 -0
  27. data/app/commands/reports/belongs_to_options.rb +178 -0
  28. data/app/commands/reports/constant_options.rb +66 -0
  29. data/app/commands/reports/external_graphql_client.rb +116 -0
  30. data/app/commands/reports/fill_dates.rb +65 -0
  31. data/app/commands/reports/filter_option_generator.rb +186 -0
  32. data/app/commands/reports/generator.rb +310 -0
  33. data/app/commands/reports/has_many_options.rb +105 -0
  34. data/app/commands/reports/importer.rb +132 -0
  35. data/app/commands/reports/nested_attribute_options.rb +134 -0
  36. data/app/constants/color.rb +9 -0
  37. data/app/constants/file_format.rb +12 -0
  38. data/app/constants/has_helpers/cards/card_custom_field.rb +12 -0
  39. data/app/constants/has_helpers/cards/card_data_type.rb +11 -0
  40. data/app/constants/has_helpers/cards/card_identifier.rb +10 -0
  41. data/app/constants/has_helpers/cards/card_layout_type.rb +11 -0
  42. data/app/constants/has_helpers/cards/card_variant_type.rb +12 -0
  43. data/app/constants/has_helpers/link_type.rb +10 -0
  44. data/app/constants/has_helpers/notification_alert_status.rb +14 -0
  45. data/app/constants/has_helpers/notification_alert_type.rb +10 -0
  46. data/app/constants/has_helpers/operation.rb +11 -0
  47. data/app/constants/has_helpers/resource_type.rb +25 -0
  48. data/app/constants/icon.rb +22 -0
  49. data/app/constants/logical_operator.rb +7 -0
  50. data/app/constants/option.rb +10 -0
  51. data/app/constants/time_zone.rb +12 -0
  52. data/app/constructors/has_helpers/base_constructor.rb +62 -0
  53. data/app/controllers/concerns/has_helpers/service_trust/authenticated_as_service.rb +51 -0
  54. data/app/controllers/concerns/has_helpers/service_trust/graphql_authentication.rb +57 -0
  55. data/app/controllers/has_helpers/controller.rb +63 -0
  56. data/app/controllers/has_helpers/factory_controller.rb +261 -0
  57. data/app/controllers/has_helpers/graphql_extensions.rb +83 -0
  58. data/app/controllers/has_helpers/health_check_controller.rb +46 -0
  59. data/app/controllers/has_helpers/search_extensions.rb +92 -0
  60. data/app/controllers/has_helpers/service_trust/jwks_controller.rb +20 -0
  61. data/app/controllers/has_helpers/xlsx_export.rb +115 -0
  62. data/app/controllers/search_extensions.rb +5 -0
  63. data/app/graphql/has_helpers/base_type.rb +13 -0
  64. data/app/graphql/has_helpers/base_union.rb +9 -0
  65. data/app/graphql/has_helpers/enums/resource_enum.rb +24 -0
  66. data/app/graphql/has_helpers/middleware/application_access.rb +26 -0
  67. data/app/graphql/has_helpers/mutations/base.rb +27 -0
  68. data/app/graphql/has_helpers/mutations/external_data_sync.rb +72 -0
  69. data/app/graphql/has_helpers/mutations/mark_individual_alert_read.rb +31 -0
  70. data/app/graphql/has_helpers/mutations/mark_notifications_read.rb +50 -0
  71. data/app/graphql/has_helpers/mutations/toggle_favorite.rb +39 -0
  72. data/app/graphql/has_helpers/resolvers/app_nav.rb +107 -0
  73. data/app/graphql/has_helpers/resolvers/base.rb +27 -0
  74. data/app/graphql/has_helpers/resolvers/cards/available_cards.rb +31 -0
  75. data/app/graphql/has_helpers/resolvers/cards/card_data.rb +74 -0
  76. data/app/graphql/has_helpers/resolvers/cards/hover_card_data.rb +153 -0
  77. data/app/graphql/has_helpers/resolvers/favorite.rb +62 -0
  78. data/app/graphql/has_helpers/resolvers/internal/roles.rb +54 -0
  79. data/app/graphql/has_helpers/resolvers/is_favorite.rb +24 -0
  80. data/app/graphql/has_helpers/resolvers/list_notification_alerts.rb +47 -0
  81. data/app/graphql/has_helpers/resolvers/lookup.rb +36 -0
  82. data/app/graphql/has_helpers/resolvers/recently_viewed.rb +54 -0
  83. data/app/graphql/has_helpers/resolvers/resource_tab.rb +22 -0
  84. data/app/graphql/has_helpers/resolvers/search.rb +18 -0
  85. data/app/graphql/has_helpers/resolvers/search_query.rb +38 -0
  86. data/app/graphql/has_helpers/resolvers/user_application_order.rb +35 -0
  87. data/app/graphql/has_helpers/resources/organization_option_resource.rb +28 -0
  88. data/app/graphql/has_helpers/resources/organization_resource_resource.rb +18 -0
  89. data/app/graphql/has_helpers/resources/resource_group_resource.rb +10 -0
  90. data/app/graphql/has_helpers/resources/resource_resource.rb +21 -0
  91. data/app/graphql/has_helpers/resources/user_role_resource.rb +9 -0
  92. data/app/graphql/has_helpers/types/application_order_type.rb +18 -0
  93. data/app/graphql/has_helpers/types/cards/available_card_type.rb +20 -0
  94. data/app/graphql/has_helpers/types/cards/card_badge_type.rb +12 -0
  95. data/app/graphql/has_helpers/types/cards/card_config_type.rb +18 -0
  96. data/app/graphql/has_helpers/types/cards/card_data_type.rb +13 -0
  97. data/app/graphql/has_helpers/types/cards/card_entry_field_type.rb +21 -0
  98. data/app/graphql/has_helpers/types/cards/card_entry_type.rb +12 -0
  99. data/app/graphql/has_helpers/types/cards/card_field_config_type.rb +17 -0
  100. data/app/graphql/has_helpers/types/layouts/app_nav/link_section_type.rb +17 -0
  101. data/app/graphql/has_helpers/types/layouts/app_nav/link_type.rb +20 -0
  102. data/app/graphql/has_helpers/types/layouts/app_nav/sub_link_type.rb +17 -0
  103. data/app/graphql/has_helpers/types/layouts/app_nav/type.rb +16 -0
  104. data/app/graphql/has_helpers/types/lookup.rb +16 -0
  105. data/app/graphql/has_helpers/types/resource_tab/type.rb +15 -0
  106. data/app/graphql/has_helpers/types/role_type.rb +13 -0
  107. data/app/graphql/has_helpers/types/search/detail_badge_type.rb +15 -0
  108. data/app/graphql/has_helpers/types/search/detail_item_type.rb +14 -0
  109. data/app/graphql/has_helpers/types/search/detail_type.rb +16 -0
  110. data/app/graphql/has_helpers/types/search/filter_operation_enum.rb +19 -0
  111. data/app/graphql/has_helpers/types/search/input_type.rb +16 -0
  112. data/app/graphql/has_helpers/types/search/result_type.rb +72 -0
  113. data/app/graphql/has_helpers/types/search/search_filter_input_type.rb +17 -0
  114. data/app/graphql/has_helpers/types/search/type.rb +17 -0
  115. data/app/importers/has_helpers/cards/importer.rb +1223 -0
  116. data/app/lib/has_helpers/application_helper.rb +21 -0
  117. data/app/lib/has_helpers/dn/processor.rb +55 -0
  118. data/app/lib/has_helpers/dn/refresh.rb +13 -0
  119. data/app/lib/has_helpers/dn/utils/backfill_utils.rb +80 -0
  120. data/app/lib/has_helpers/dn/utils/query_utils.rb +216 -0
  121. data/app/lib/has_helpers/feature.rb +88 -0
  122. data/app/lib/has_helpers/hq_exception.rb +18 -0
  123. data/app/lib/has_helpers/index.rb +890 -0
  124. data/app/lib/has_helpers/organization_merge.rb +128 -0
  125. data/app/lib/has_helpers/query/elasticsearch.rb +20 -0
  126. data/app/lib/has_helpers/query/provider.rb +105 -0
  127. data/app/lib/has_helpers/query/sql.rb +133 -0
  128. data/app/lib/has_helpers/query.rb +14 -0
  129. data/app/lib/has_helpers/search/elasticsearch.rb +41 -0
  130. data/app/lib/has_helpers/search/elasticsearch_shared.rb +70 -0
  131. data/app/lib/has_helpers/search/provider.rb +149 -0
  132. data/app/lib/has_helpers/search/search_utils.rb +74 -0
  133. data/app/lib/has_helpers/search/sql_search.rb +219 -0
  134. data/app/lib/has_helpers/search.rb +46 -0
  135. data/app/models/ability.rb +233 -0
  136. data/app/models/has_helpers/application.rb +47 -0
  137. data/app/models/has_helpers/application_record.rb +7 -0
  138. data/app/models/has_helpers/cards/card_builder/base.rb +74 -0
  139. data/app/models/has_helpers/cards/card_builder/card_definition_builder.rb +486 -0
  140. data/app/models/has_helpers/cards/card_builder/definition_context.rb +82 -0
  141. data/app/models/has_helpers/cards/card_builder/field_builder.rb +142 -0
  142. data/app/models/has_helpers/cards/card_builder/resource_builder.rb +34 -0
  143. data/app/models/has_helpers/cards/card_definition.rb +41 -0
  144. data/app/models/has_helpers/cards/card_definition_resource.rb +19 -0
  145. data/app/models/has_helpers/cards/card_field.rb +39 -0
  146. data/app/models/has_helpers/cards/registry.rb +115 -0
  147. data/app/models/has_helpers/cards/role_card_field.rb +28 -0
  148. data/app/models/has_helpers/cards/role_resource_card.rb +41 -0
  149. data/app/models/has_helpers/dn_utils.rb +61 -0
  150. data/app/models/has_helpers/favorite.rb +20 -0
  151. data/app/models/has_helpers/master_record.rb +18 -0
  152. data/app/models/has_helpers/notification_alert.rb +52 -0
  153. data/app/models/has_helpers/organization.rb +16 -0
  154. data/app/models/has_helpers/organization_link.rb +92 -0
  155. data/app/models/has_helpers/organization_methods.rb +62 -0
  156. data/app/models/has_helpers/organization_option.rb +31 -0
  157. data/app/models/has_helpers/organization_resource.rb +45 -0
  158. data/app/models/has_helpers/pending_db_operation.rb +31 -0
  159. data/app/models/has_helpers/recently_viewed.rb +34 -0
  160. data/app/models/has_helpers/reindex_queue.rb +43 -0
  161. data/app/models/has_helpers/resource.rb +38 -0
  162. data/app/models/has_helpers/resource_group.rb +15 -0
  163. data/app/models/has_helpers/restriction.rb +15 -0
  164. data/app/models/has_helpers/restriction_operation.rb +13 -0
  165. data/app/models/has_helpers/role.rb +20 -0
  166. data/app/models/has_helpers/service_trust/audit_log.rb +20 -0
  167. data/app/models/has_helpers/service_trust/key.rb +56 -0
  168. data/app/models/has_helpers/stat.rb +13 -0
  169. data/app/models/has_helpers/user.rb +18 -0
  170. data/app/models/has_helpers/user_methods.rb +184 -0
  171. data/app/models/has_helpers/user_organization.rb +33 -0
  172. data/app/models/has_helpers/user_role.rb +27 -0
  173. data/app/models/has_helpers/user_session.rb +19 -0
  174. data/app/presenters/has_helpers/barcode_base_presenter.rb +113 -0
  175. data/app/presenters/has_helpers/base_presenter.rb +100 -0
  176. data/app/presenters/has_helpers/cacheable_item.rb +28 -0
  177. data/app/presenters/has_helpers/item_presenter.rb +52 -0
  178. data/app/presenters/has_helpers/items_presenter.rb +33 -0
  179. data/app/presenters/has_helpers/resource/action_presenter.rb +8 -0
  180. data/app/presenters/has_helpers/resource/cell_presenter.rb +52 -0
  181. data/app/presenters/has_helpers/resource/email_presenter.rb +34 -0
  182. data/app/presenters/has_helpers/resource/form_presenter.rb +76 -0
  183. data/app/presenters/has_helpers/resource/info_collection_presenter.rb +33 -0
  184. data/app/presenters/has_helpers/resource/info_presenter.rb +34 -0
  185. data/app/presenters/has_helpers/resource/list_presenter.rb +120 -0
  186. data/app/presenters/has_helpers/resource/note_presenter.rb +14 -0
  187. data/app/presenters/has_helpers/resource/row_presenter.rb +25 -0
  188. data/app/presenters/has_helpers/resource/tag_presenter.rb +31 -0
  189. data/app/presenters/has_helpers/search_presenter.rb +230 -0
  190. data/app/triggers/has_helpers/erase_denormalized_belongs_to_column_trigger.rb +85 -0
  191. data/app/triggers/has_helpers/limit_favorites.rb +97 -0
  192. data/app/utils/has_helpers/redis_configurable.rb +79 -0
  193. data/app/utils/has_helpers/sync_utils.rb +234 -0
  194. data/app/views/has_helpers/actions/_action.html.erb +31 -0
  195. data/app/views/has_helpers/alerts/_alert.html.erb +3 -0
  196. data/app/views/has_helpers/barcodes.html.erb +36 -0
  197. data/app/views/has_helpers/containers/_container.html.erb +3 -0
  198. data/app/views/has_helpers/email_notifier/system.html.erb +8 -0
  199. data/app/views/has_helpers/email_notifier/system.text.erb +7 -0
  200. data/app/views/has_helpers/enumerables/_enumerable.html.erb +1 -0
  201. data/app/views/has_helpers/icons/_icon.html.erb +1 -0
  202. data/app/views/has_helpers/render_objects/_render_object.html.erb +1 -0
  203. data/app/views/has_helpers/services/_service.html.erb +1 -0
  204. data/app/views/has_helpers/text_nodes/_text_node.html.erb +4 -0
  205. data/app/views/has_helpers/ui_attributes/_html_attrs.html.erb +1 -0
  206. data/app/workers/elasticsearch_process_queue.rb +11 -0
  207. data/app/workers/elasticsearch_reindex.rb +11 -0
  208. data/app/workers/elasticsearch_reindex_scheduler.rb +35 -0
  209. data/app/workers/good_job/configurable_backfill.rb +64 -0
  210. data/app/workers/good_job/cron_denormalization_stats_manager.rb +39 -0
  211. data/app/workers/good_job/denormalization_stats_worker.rb +57 -0
  212. data/app/workers/good_job/dn_update_worker.rb +30 -0
  213. data/app/workers/good_job/dn_worker.rb +47 -0
  214. data/app/workers/good_job/elasticsearch_old_index_cleaner_worker.rb +113 -0
  215. data/app/workers/good_job/elasticsearch_on_finish_reindex.rb +26 -0
  216. data/app/workers/good_job/elasticsearch_process_batch.rb +78 -0
  217. data/app/workers/good_job/elasticsearch_process_change_logs_master_worker.rb +27 -0
  218. data/app/workers/good_job/elasticsearch_process_change_logs_worker.rb +155 -0
  219. data/app/workers/good_job/elasticsearch_process_queue.rb +50 -0
  220. data/app/workers/good_job/elasticsearch_reindex.rb +31 -0
  221. data/app/workers/has_helpers/cards/orphan_card_sweeper.rb +28 -0
  222. data/app/workers/has_helpers/db_operations/clean_stats_worker.rb +42 -0
  223. data/app/workers/has_helpers/db_operations/helper_worker.rb +131 -0
  224. data/app/workers/has_helpers/db_operations/main_worker.rb +164 -0
  225. data/app/workers/has_helpers/db_operations/operations.rb +134 -0
  226. data/app/workers/has_helpers/db_operations/update_operations_stats_resume_worker.rb +35 -0
  227. data/app/workers/has_helpers/default_worker.rb +17 -0
  228. data/app/workers/has_helpers/good_job/notification_alert_cleanup_worker.rb +43 -0
  229. data/app/workers/has_helpers/service_trust/audit_log_cleanup_worker.rb +19 -0
  230. data/app/workers/sidekiq/elasticsearch_old_index_cleaner_worker.rb +112 -0
  231. data/app/workers/sidekiq/elasticsearch_process_batch.rb +87 -0
  232. data/app/workers/sidekiq/elasticsearch_process_queue.rb +40 -0
  233. data/app/workers/sidekiq/elasticsearch_reindex.rb +53 -0
  234. data/config/initializers/action_view.rb +7 -0
  235. data/config/initializers/inflections.rb +24 -0
  236. data/config/initializers/marginalia.rb +8 -0
  237. data/config/initializers/mime_types.rb +6 -0
  238. data/config/initializers/opentelemetry.rb +12 -0
  239. data/config/initializers/redis_conf.rb +40 -0
  240. data/config/initializers/searchkick.rb +9 -0
  241. data/config/initializers/will_paginate.rb +39 -0
  242. data/config/redis.yml +12 -0
  243. data/config/routes.rb +27 -0
  244. data/config/service_trust_routes.rb +5 -0
  245. data/config.ru +9 -0
  246. data/db/migrate/20230127194725_create_organization_table.rb +25 -0
  247. data/db/migrate/20230127194726_validate_organization_foreign_keys.rb +7 -0
  248. data/db/migrate/20230206141413_create_security_models.rb +42 -0
  249. data/db/migrate/20230206141513_create_restriction_model.rb +20 -0
  250. data/db/migrate/20230206142613_add_security_indexes.rb +14 -0
  251. data/db/migrate/20230206143513_security_model_constants_seed.rb +8 -0
  252. data/db/migrate/20230206161513_add_organization_to_security_models.rb +13 -0
  253. data/db/migrate/20230209121019_create_search_group_models.rb +36 -0
  254. data/db/migrate/20230209122919_add_search_group_indexes.rb +21 -0
  255. data/db/migrate/20230209181832_add_search_group_resources_type_constraint_trigger.rb +61 -0
  256. data/db/migrate/20230313220337_create_table_user_sessions.rb +31 -0
  257. data/db/migrate/20230517141106_update_resource_types.rb +12 -0
  258. data/db/migrate/20230518194611_add_resources_contraints.rb +17 -0
  259. data/db/migrate/20230518194642_create_nested_resource_model.rb +21 -0
  260. data/db/migrate/20230518194645_validate_security_models_constraints.rb +23 -0
  261. data/db/migrate/20230608125037_add_inactive_field_to_user_sessions.rb +7 -0
  262. data/db/migrate/20230919191525_add_parent_id_to_resources.rb +8 -0
  263. data/db/migrate/20230919191535_validate_parent_id_fk_resources.rb +7 -0
  264. data/db/migrate/20230919210456_drop_nested_resources.rb +7 -0
  265. data/db/migrate/20231222135620_add_user_role.rb +19 -0
  266. data/db/migrate/20240108172021_create_favorites_table.rb +20 -0
  267. data/db/migrate/20240108190209_create_organization_link_table_if_doesnt_exists.rb +31 -0
  268. data/db/migrate/20240109211445_validate_fks_org_links.rb +9 -0
  269. data/db/migrate/20240110135440_create_recently_vieweds.rb +20 -0
  270. data/db/migrate/20240112185312_link_type_options_seed.rb +7 -0
  271. data/db/migrate/20240116173201_organization_link_resource_tab_constraints.rb +19 -0
  272. data/db/migrate/20240131160949_add_user_organizations_table.rb +32 -0
  273. data/db/migrate/20240212132519_add_organization_in_user_sessions.rb +13 -0
  274. data/db/migrate/20240227135052_add_user_organization_composite_fks.rb +32 -0
  275. data/db/migrate/20240312193501_update_organization_links.rb +11 -0
  276. data/db/migrate/20240426185902_add_user_organizations_current_organization_column.rb +12 -0
  277. data/db/migrate/20240429214601_add_primary_trigger.rb +10 -0
  278. data/db/migrate/20241112131819_add_json_file_format_seed.rb +7 -0
  279. data/db/migrate/20250520133417_create_restriction_operations.rb +18 -0
  280. data/db/migrate/20250520133420_validate_create_restriction_operations.rb +8 -0
  281. data/db/migrate/20250520140642_add_indexes_to_restrictions.rb +9 -0
  282. data/db/migrate/20250529130741_create_notification_alerts_table.rb +28 -0
  283. data/db/migrate/20250530223332_create_data_migrations_table.rb +19 -0
  284. data/db/migrate/20250605121622_seed_notification_alert_status.rb +7 -0
  285. data/db/migrate/20250605131439_seed_notification_alert_types.rb +7 -0
  286. data/db/migrate/20250606173128_update_notification_alert_length_constraint.rb +18 -0
  287. data/db/migrate/20250606174043_validate_notification_alert_length_constraints.rb +8 -0
  288. data/db/migrate/20250624183000_add_data_import_alert_type.rb +11 -0
  289. data/db/migrate/20250722183935_create_organization_options_table.rb +38 -0
  290. data/db/migrate/20250722192724_validate_organization_options_fks_and_constraints.rb +32 -0
  291. data/db/migrate/20250722192936_add_indexes_to_organization_options_table.rb +15 -0
  292. data/db/migrate/20250915132448_add_column_restrictions_hash.rb +7 -0
  293. data/db/migrate/20250917143211_add_column_permissions_hash.rb +7 -0
  294. data/db/migrate/20251001145950_add_trust_this_device.rb +7 -0
  295. data/db/migrate/20251021130835_add_backend_urls_to_applications_table.rb +13 -0
  296. data/db/migrate/20251021172715_validate_backend_urls_constraints_in_applications.rb +9 -0
  297. data/db/migrate/20251030200020_create_card_definitions.rb +23 -0
  298. data/db/migrate/20251030201012_create_card_definition_resources.rb +24 -0
  299. data/db/migrate/20251030201236_create_card_fields.rb +34 -0
  300. data/db/migrate/20251103194317_create_role_resource_cards.rb +37 -0
  301. data/db/migrate/20251103194426_create_role_card_fields.rb +34 -0
  302. data/db/migrate/20251107173218_validate_columns_from_cards.rb +17 -0
  303. data/db/migrate/20251111173212_add_column_application_array.rb +7 -0
  304. data/db/migrate/20251112203326_add_card_types.rb +10 -0
  305. data/db/migrate/20251115120000_add_virtual_cards_support.rb +28 -0
  306. data/db/migrate/20251202231256_add_org_scoped_fk_role_resource_cards_to_roles.rb +14 -0
  307. data/db/migrate/20260105134504_add_accessor_field_resource_type.rb +7 -0
  308. data/db/migrate/20260115123000_add_default_visibility_to_card_definitions.rb +9 -0
  309. data/db/migrate/20260120175037_is_new_admin.rb +9 -0
  310. data/db/migrate/20260122392008_add_stats_table.rb +17 -0
  311. data/db/migrate/20260414204718_add_index_to_stats_table.rb +10 -0
  312. data/db/migrate/20260509120000_create_service_trust_keys.rb +25 -0
  313. data/db/migrate/20260509120001_create_service_trust_audit_logs.rb +26 -0
  314. data/db/migrate/20260511120000_add_direction_to_service_trust_audit_logs.rb +17 -0
  315. data/db/migrate/20260511121000_remove_role_fk_from_role_resource_cards.rb +19 -0
  316. data/db/migrate/20260511121001_add_disabled_at_to_role_resource_cards.rb +10 -0
  317. data/db/migrate/20260605120100_seed_hover_card_options.rb +8 -0
  318. data/db/migrate/20260608120000_seed_badge_list_card_data_type.rb +7 -0
  319. data/db/migrate/20260727000000_add_two_factor_trust_id_to_user_sessions.rb +11 -0
  320. data/db/seeds.rb +14 -0
  321. data/docs/Elasticsearch.md +23 -0
  322. data/docs/Search_API.md +126 -0
  323. data/docs/cards_role_proxy.md +107 -0
  324. data/docs/factory_api.md +135 -0
  325. data/has-helpers-pr-289-pipeline.yaml +16 -0
  326. data/has-helpers-pr-298-pipeline.yaml +15 -0
  327. data/has_helpers.gemspec +68 -0
  328. data/lib/active_record/migration/active_migration_patch.rb +123 -0
  329. data/lib/generators/has_helpers/install/USAGE +8 -0
  330. data/lib/generators/has_helpers/install/install_generator.rb +22 -0
  331. data/lib/generators/has_helpers/install/templates/migrate/has_helpers_initial_setup.rb +26 -0
  332. data/lib/has_helpers/active_record/base.rb +50 -0
  333. data/lib/has_helpers/active_record/date_range.rb +228 -0
  334. data/lib/has_helpers/active_record/nested_resource.rb +58 -0
  335. data/lib/has_helpers/active_record/validation.rb +63 -0
  336. data/lib/has_helpers/active_record.rb +520 -0
  337. data/lib/has_helpers/app/command.rb +107 -0
  338. data/lib/has_helpers/app.rb +10 -0
  339. data/lib/has_helpers/assets_precompile_helper.rb +20 -0
  340. data/lib/has_helpers/attributes.rb +196 -0
  341. data/lib/has_helpers/aws.rb +67 -0
  342. data/lib/has_helpers/cards/cache.rb +49 -0
  343. data/lib/has_helpers/cards/config.rb +42 -0
  344. data/lib/has_helpers/cards/remote_role.rb +27 -0
  345. data/lib/has_helpers/cards/remote_roles.rb +75 -0
  346. data/lib/has_helpers/cards/roles.rb +55 -0
  347. data/lib/has_helpers/cards.rb +34 -0
  348. data/lib/has_helpers/concerns/hydrate_concern.rb +76 -0
  349. data/lib/has_helpers/concerns/importable_accessors.rb +25 -0
  350. data/lib/has_helpers/concerns/restrictions_parseable.rb +51 -0
  351. data/lib/has_helpers/config.rb +11 -0
  352. data/lib/has_helpers/constant.rb +578 -0
  353. data/lib/has_helpers/constraints.rb +10 -0
  354. data/lib/has_helpers/core_ext/array.rb +28 -0
  355. data/lib/has_helpers/core_ext/date/infinity.rb +25 -0
  356. data/lib/has_helpers/core_ext/date.rb +39 -0
  357. data/lib/has_helpers/core_ext/enumerable.rb +20 -0
  358. data/lib/has_helpers/core_ext/false_class.rb +14 -0
  359. data/lib/has_helpers/core_ext/float.rb +18 -0
  360. data/lib/has_helpers/core_ext/hash.rb +71 -0
  361. data/lib/has_helpers/core_ext/integer.rb +18 -0
  362. data/lib/has_helpers/core_ext/nil_class.rb +30 -0
  363. data/lib/has_helpers/core_ext/object.rb +60 -0
  364. data/lib/has_helpers/core_ext/proc.rb +16 -0
  365. data/lib/has_helpers/core_ext/string.rb +81 -0
  366. data/lib/has_helpers/core_ext/symbol.rb +17 -0
  367. data/lib/has_helpers/core_ext/true_class.rb +14 -0
  368. data/lib/has_helpers/cursor.rb +46 -0
  369. data/lib/has_helpers/data_migration/base.rb +293 -0
  370. data/lib/has_helpers/data_migration/large_worker.rb +20 -0
  371. data/lib/has_helpers/data_migration/master_worker.rb +33 -0
  372. data/lib/has_helpers/data_migration/migrator.rb +83 -0
  373. data/lib/has_helpers/data_migration/model.rb +18 -0
  374. data/lib/has_helpers/data_migration/small_worker.rb +20 -0
  375. data/lib/has_helpers/data_migration.rb +8 -0
  376. data/lib/has_helpers/engine.rb +47 -0
  377. data/lib/has_helpers/extensions.rb +17 -0
  378. data/lib/has_helpers/factory_api.rb +47 -0
  379. data/lib/has_helpers/factory_scenario/definition.rb +33 -0
  380. data/lib/has_helpers/factory_scenario/dsl.rb +80 -0
  381. data/lib/has_helpers/factory_scenario/factory_bot_override.rb +53 -0
  382. data/lib/has_helpers/factory_scenario/registry.rb +31 -0
  383. data/lib/has_helpers/factory_scenario/runner.rb +285 -0
  384. data/lib/has_helpers/factory_scenario.rb +27 -0
  385. data/lib/has_helpers/fixed_expiration_time_cache_session_store.rb +20 -0
  386. data/lib/has_helpers/flattener/association.rb +140 -0
  387. data/lib/has_helpers/flattener/attribute.rb +42 -0
  388. data/lib/has_helpers/flattener/base.rb +428 -0
  389. data/lib/has_helpers/flattener/column/types.rb +71 -0
  390. data/lib/has_helpers/flattener/column.rb +97 -0
  391. data/lib/has_helpers/flattener/pivot.rb +49 -0
  392. data/lib/has_helpers/flattener/reset.rb +33 -0
  393. data/lib/has_helpers/flattener/resource.rb +114 -0
  394. data/lib/has_helpers/flattener/resource_generator.rb +21 -0
  395. data/lib/has_helpers/flattener/utils.rb +14 -0
  396. data/lib/has_helpers/flattener.rb +53 -0
  397. data/lib/has_helpers/hash_accessors.rb +62 -0
  398. data/lib/has_helpers/helpers/application.rb +291 -0
  399. data/lib/has_helpers/index/config.rb +15 -0
  400. data/lib/has_helpers/lazy_config.rb +61 -0
  401. data/lib/has_helpers/resource_importer.rb +260 -0
  402. data/lib/has_helpers/resources.rb +127 -0
  403. data/lib/has_helpers/rspec/constants.rb +61 -0
  404. data/lib/has_helpers/rspec/factories.rb +11 -0
  405. data/lib/has_helpers/rspec.rb +22 -0
  406. data/lib/has_helpers/sentry/graphql_trace.rb +37 -0
  407. data/lib/has_helpers/serializer.rb +41 -0
  408. data/lib/has_helpers/service_trust/audit.rb +45 -0
  409. data/lib/has_helpers/service_trust/authorization.rb +34 -0
  410. data/lib/has_helpers/service_trust/bearer_token.rb +23 -0
  411. data/lib/has_helpers/service_trust/capability.rb +32 -0
  412. data/lib/has_helpers/service_trust/client/response.rb +13 -0
  413. data/lib/has_helpers/service_trust/client/retry.rb +35 -0
  414. data/lib/has_helpers/service_trust/client.rb +128 -0
  415. data/lib/has_helpers/service_trust/configuration.rb +76 -0
  416. data/lib/has_helpers/service_trust/engine.rb +10 -0
  417. data/lib/has_helpers/service_trust/errors.rb +32 -0
  418. data/lib/has_helpers/service_trust/graphql/authorizable.rb +72 -0
  419. data/lib/has_helpers/service_trust/graphql_client.rb +54 -0
  420. data/lib/has_helpers/service_trust/jwks_client.rb +133 -0
  421. data/lib/has_helpers/service_trust/jwt_codec.rb +45 -0
  422. data/lib/has_helpers/service_trust/key_manager.rb +160 -0
  423. data/lib/has_helpers/service_trust/rate_limiter.rb +27 -0
  424. data/lib/has_helpers/service_trust/replay_cache.rb +26 -0
  425. data/lib/has_helpers/service_trust/signer.rb +47 -0
  426. data/lib/has_helpers/service_trust/test.rb +60 -0
  427. data/lib/has_helpers/service_trust/verifier.rb +85 -0
  428. data/lib/has_helpers/service_trust/verify_middleware.rb +55 -0
  429. data/lib/has_helpers/service_trust.rb +51 -0
  430. data/lib/has_helpers/test_helpers/factory_data/unit_addresses.rb +42 -0
  431. data/lib/has_helpers/test_helpers/factory_data/unit_advisors.rb +272 -0
  432. data/lib/has_helpers/test_helpers/factory_data/unit_emails.rb +37 -0
  433. data/lib/has_helpers/test_helpers/factory_data/unit_organizations.rb +48 -0
  434. data/lib/has_helpers/test_helpers/factory_data/unit_people.rb +34 -0
  435. data/lib/has_helpers/test_helpers/factory_data/unit_phones.rb +41 -0
  436. data/lib/has_helpers/test_helpers/factory_data/unit_states.rb +26 -0
  437. data/lib/has_helpers/test_helpers/factory_data/unit_webs.rb +31 -0
  438. data/lib/has_helpers/test_helpers/shoulda_helpers.rb +249 -0
  439. data/lib/has_helpers/ui_attributes.rb +39 -0
  440. data/lib/has_helpers/utils/action.rb +87 -0
  441. data/lib/has_helpers/utils/active_record_utils.rb +40 -0
  442. data/lib/has_helpers/utils/alert.rb +42 -0
  443. data/lib/has_helpers/utils/container.rb +46 -0
  444. data/lib/has_helpers/utils/dataset.rb +34 -0
  445. data/lib/has_helpers/utils/email_notifier.rb +15 -0
  446. data/lib/has_helpers/utils/icon.rb +66 -0
  447. data/lib/has_helpers/utils/input.rb +45 -0
  448. data/lib/has_helpers/utils/log_notifier.rb +79 -0
  449. data/lib/has_helpers/utils/render_object.rb +32 -0
  450. data/lib/has_helpers/utils/s3_utils.rb +37 -0
  451. data/lib/has_helpers/utils/service.rb +87 -0
  452. data/lib/has_helpers/utils/slack_conf.rb +31 -0
  453. data/lib/has_helpers/utils/slack_notifier.rb +42 -0
  454. data/lib/has_helpers/utils/text_node.rb +34 -0
  455. data/lib/has_helpers/utils/user_restrictions.rb +266 -0
  456. data/lib/has_helpers/utils.rb +19 -0
  457. data/lib/has_helpers/version.rb +6 -0
  458. data/lib/has_helpers/web_socket_publisher.rb +20 -0
  459. data/lib/has_helpers/webhook.rb +17 -0
  460. data/lib/has_helpers.rb +63 -0
  461. data/lib/hq/resource.rb +55 -0
  462. data/lib/hq/structure/inserts.rb +176 -0
  463. data/lib/hq/structure.rb +115 -0
  464. data/lib/tasks/has_helpers/service_trust.rake +39 -0
  465. data/script/rails +10 -0
  466. data/sorbet/config +5 -0
  467. data/sorbet/rbi/gems/actionpack.rbi +1361 -0
  468. data/sorbet/rbi/gems/activemodel.rbi +755 -0
  469. data/sorbet/rbi/gems/activerecord.rbi +4713 -0
  470. data/sorbet/rbi/gems/activesupport.rbi +1970 -0
  471. data/sorbet/rbi/gems/barby.rbi +129 -0
  472. data/sorbet/rbi/gems/better_errors.rbi +155 -0
  473. data/sorbet/rbi/gems/binding_of_caller.rbi +22 -0
  474. data/sorbet/rbi/gems/byebug.rbi +19 -0
  475. data/sorbet/rbi/gems/chronic.rbi +480 -0
  476. data/sorbet/rbi/gems/chunky_png.rbi +510 -0
  477. data/sorbet/rbi/gems/climate_control.rbi +45 -0
  478. data/sorbet/rbi/gems/coderay.rbi +91 -0
  479. data/sorbet/rbi/gems/concurrent-ruby.rbi +1587 -0
  480. data/sorbet/rbi/gems/debug_inspector.rbi +18 -0
  481. data/sorbet/rbi/gems/erubi.rbi +26 -0
  482. data/sorbet/rbi/gems/holidays.rbi +362 -0
  483. data/sorbet/rbi/gems/i18n.rbi +132 -0
  484. data/sorbet/rbi/gems/method_source.rbi +63 -0
  485. data/sorbet/rbi/gems/mime-types-data.rbi +16 -0
  486. data/sorbet/rbi/gems/mime-types.rbi +217 -0
  487. data/sorbet/rbi/gems/mimemagic.rbi +36 -0
  488. data/sorbet/rbi/gems/minitest.rbi +282 -0
  489. data/sorbet/rbi/gems/mustache.rbi +151 -0
  490. data/sorbet/rbi/gems/paperclip.rbi +644 -0
  491. data/sorbet/rbi/gems/parallel.rbi +81 -0
  492. data/sorbet/rbi/gems/parallel_tests.rbi +27 -0
  493. data/sorbet/rbi/gems/pry-rails.rbi +71 -0
  494. data/sorbet/rbi/gems/pry.rbi +1964 -0
  495. data/sorbet/rbi/gems/rack.rbi +228 -0
  496. data/sorbet/rbi/gems/railties.rbi +364 -0
  497. data/sorbet/rbi/gems/rspec-core.rbi +1704 -0
  498. data/sorbet/rbi/gems/rspec-expectations.rbi +389 -0
  499. data/sorbet/rbi/gems/rspec-support.rbi +206 -0
  500. data/sorbet/rbi/gems/rspec.rbi +14 -0
  501. data/sorbet/rbi/gems/spreadsheet_architect.rbi +10 -0
  502. data/sorbet/rbi/gems/sprockets.rbi +659 -0
  503. data/sorbet/rbi/gems/terrapin.rbi +115 -0
  504. data/sorbet/rbi/gems/testhq.rbi +14 -0
  505. data/sorbet/rbi/gems/thor.rbi +482 -0
  506. data/sorbet/rbi/gems/thread_safe.rbi +81 -0
  507. data/sorbet/rbi/gems/tzinfo.rbi +407 -0
  508. data/sorbet/rbi/gems/zeitwerk.rbi +131 -0
  509. data/sorbet/rbi/hidden-definitions/errors.txt +35111 -0
  510. data/sorbet/rbi/hidden-definitions/hidden.rbi +59974 -0
  511. data/sorbet/rbi/sorbet-typed/lib/actionmailer/all/actionmailer.rbi +13 -0
  512. data/sorbet/rbi/sorbet-typed/lib/actionpack/all/actionpack.rbi +855 -0
  513. data/sorbet/rbi/sorbet-typed/lib/actionview/all/actionview.rbi +314 -0
  514. data/sorbet/rbi/sorbet-typed/lib/activemodel/all/activemodel.rbi +423 -0
  515. data/sorbet/rbi/sorbet-typed/lib/activerecord/>=5.2/activerecord.rbi +17 -0
  516. data/sorbet/rbi/sorbet-typed/lib/activerecord/all/activerecord.rbi +1415 -0
  517. data/sorbet/rbi/sorbet-typed/lib/activerecord/~>6.0.0/activerecord.rbi +475 -0
  518. data/sorbet/rbi/sorbet-typed/lib/activestorage/>=6.0.0/activestorage.rbi +19 -0
  519. data/sorbet/rbi/sorbet-typed/lib/activestorage/all/activestorage.rbi +173 -0
  520. data/sorbet/rbi/sorbet-typed/lib/activesupport/>=6.0.0.rc1/activesupport.rbi +23 -0
  521. data/sorbet/rbi/sorbet-typed/lib/activesupport/all/activesupport.rbi +625 -0
  522. data/sorbet/rbi/sorbet-typed/lib/bundler/all/bundler.rbi +8684 -0
  523. data/sorbet/rbi/sorbet-typed/lib/minitest/all/minitest.rbi +99 -0
  524. data/sorbet/rbi/sorbet-typed/lib/railties/all/railties.rbi +25 -0
  525. data/sorbet/rbi/sorbet-typed/lib/rainbow/all/rainbow.rbi +254 -0
  526. data/sorbet/rbi/sorbet-typed/lib/ruby/all/gem.rbi +4222 -0
  527. data/sorbet/rbi/sorbet-typed/lib/ruby/all/open3.rbi +111 -0
  528. data/sorbet/rbi/sorbet-typed/lib/ruby/all/resolv.rbi +543 -0
  529. data/sorbet/rbi/todo.rbi +244 -0
  530. data/spec/commands/cards/available_cards_command_spec.rb +90 -0
  531. data/spec/commands/cards/card_data_command_spec.rb +1048 -0
  532. data/spec/constructors/has_helpers/base_constructor_spec.rb +49 -0
  533. data/spec/controllers/has_helpers/controller_spec.rb +71 -0
  534. data/spec/controllers/has_helpers/xlsx_export_spec.rb +96 -0
  535. data/spec/factories/advisors.rb +20 -0
  536. data/spec/factories/anonymous_cowards.rb +5 -0
  537. data/spec/factories/applications.rb +5 -0
  538. data/spec/factories/appointments.rb +6 -0
  539. data/spec/factories/attachment.rb +15 -0
  540. data/spec/factories/audits.rb +5 -0
  541. data/spec/factories/basic_schedules.rb +12 -0
  542. data/spec/factories/cards/card_definition_resources.rb +7 -0
  543. data/spec/factories/cards/card_definitions.rb +11 -0
  544. data/spec/factories/cards/card_fields.rb +22 -0
  545. data/spec/factories/cards/role_card_fields.rb +17 -0
  546. data/spec/factories/cards/role_resource_cards.rb +12 -0
  547. data/spec/factories/constant_definition.rb +7 -0
  548. data/spec/factories/contracts.rb +10 -0
  549. data/spec/factories/data_migration_models.rb +9 -0
  550. data/spec/factories/demographics.rb +22 -0
  551. data/spec/factories/events.rb +21 -0
  552. data/spec/factories/firms.rb +21 -0
  553. data/spec/factories/imports.rb +9 -0
  554. data/spec/factories/meetups.rb +13 -0
  555. data/spec/factories/organizations.rb +13 -0
  556. data/spec/factories/policies.rb +7 -0
  557. data/spec/factories/policy_notes.rb +9 -0
  558. data/spec/factories/read_only_values.rb +7 -0
  559. data/spec/factories/resources.rb +7 -0
  560. data/spec/factories/roles.rb +11 -0
  561. data/spec/factories/schedules.rb +13 -0
  562. data/spec/factories/shared/flattener/attributes.rb +10 -0
  563. data/spec/factories/shared/flattener/columns.rb +6 -0
  564. data/spec/factories/shared/flattener/resources.rb +5 -0
  565. data/spec/factories/templates.rb +12 -0
  566. data/spec/factories/user_organizations.rb +23 -0
  567. data/spec/factories/user_session.rb +11 -0
  568. data/spec/factories/users.rb +55 -0
  569. data/spec/fixtures/sample_config.yml +3 -0
  570. data/spec/graphql/has_helpers/mutations/external_data_sync_spec.rb +101 -0
  571. data/spec/graphql/has_helpers/resolvers/cards/available_cards_spec.rb +36 -0
  572. data/spec/graphql/has_helpers/resolvers/cards/card_data_spec.rb +42 -0
  573. data/spec/graphql/has_helpers/resolvers/cards/hover_card_data_spec.rb +59 -0
  574. data/spec/has_helpers/cards/cache_spec.rb +58 -0
  575. data/spec/has_helpers/cards/config_spec.rb +68 -0
  576. data/spec/has_helpers/cards/orphan_card_sweeper_spec.rb +97 -0
  577. data/spec/has_helpers/cards/remote_role_spec.rb +17 -0
  578. data/spec/has_helpers/cards/remote_roles_spec.rb +97 -0
  579. data/spec/has_helpers/cards/roles_spec.rb +52 -0
  580. data/spec/has_helpers/cards/smoke_spec.rb +168 -0
  581. data/spec/has_helpers/cards/support.rb +52 -0
  582. data/spec/has_helpers/resolvers/internal/roles_spec.rb +73 -0
  583. data/spec/has_helpers/service_trust/audit_log_cleanup_worker_spec.rb +33 -0
  584. data/spec/has_helpers/service_trust/audit_spec.rb +70 -0
  585. data/spec/has_helpers/service_trust/authenticated_as_service_spec.rb +65 -0
  586. data/spec/has_helpers/service_trust/authorization_spec.rb +37 -0
  587. data/spec/has_helpers/service_trust/capability_spec.rb +35 -0
  588. data/spec/has_helpers/service_trust/client_spec.rb +129 -0
  589. data/spec/has_helpers/service_trust/configuration_spec.rb +35 -0
  590. data/spec/has_helpers/service_trust/engine_spec.rb +13 -0
  591. data/spec/has_helpers/service_trust/errors_spec.rb +23 -0
  592. data/spec/has_helpers/service_trust/graphql_authentication_spec.rb +59 -0
  593. data/spec/has_helpers/service_trust/graphql_authorizable_spec.rb +91 -0
  594. data/spec/has_helpers/service_trust/graphql_client_spec.rb +47 -0
  595. data/spec/has_helpers/service_trust/jwks_client_spec.rb +85 -0
  596. data/spec/has_helpers/service_trust/jwks_controller_spec.rb +47 -0
  597. data/spec/has_helpers/service_trust/jwt_codec_spec.rb +30 -0
  598. data/spec/has_helpers/service_trust/key_manager_spec.rb +80 -0
  599. data/spec/has_helpers/service_trust/key_spec.rb +52 -0
  600. data/spec/has_helpers/service_trust/rake_tasks_spec.rb +58 -0
  601. data/spec/has_helpers/service_trust/rate_limiter_spec.rb +31 -0
  602. data/spec/has_helpers/service_trust/replay_cache_spec.rb +29 -0
  603. data/spec/has_helpers/service_trust/signer_verifier_spec.rb +159 -0
  604. data/spec/has_helpers/service_trust/smoke_spec.rb +216 -0
  605. data/spec/has_helpers/service_trust/support.rb +121 -0
  606. data/spec/has_helpers/service_trust/test_module_spec.rb +39 -0
  607. data/spec/has_helpers/service_trust/verify_middleware_spec.rb +82 -0
  608. data/spec/helpers/application_spec.rb +155 -0
  609. data/spec/importers/cards/importer_spec.rb +861 -0
  610. data/spec/internal/app/assets/config/manifest.js +0 -0
  611. data/spec/internal/app/constants/cat_egory.rb +33 -0
  612. data/spec/internal/app/constants/color.rb +19 -0
  613. data/spec/internal/app/constants/exclude_group_nil_constant.rb +5 -0
  614. data/spec/internal/app/constants/foo.rb +6 -0
  615. data/spec/internal/app/constants/fruit.rb +3 -0
  616. data/spec/internal/app/constants/generic_group_example.rb +12 -0
  617. data/spec/internal/app/constants/my_constant.rb +4 -0
  618. data/spec/internal/app/constants/product.rb +3 -0
  619. data/spec/internal/app/constants/shirt_size.rb +18 -0
  620. data/spec/internal/app/constants/simple_option.rb +14 -0
  621. data/spec/internal/app/constants/status.rb +5 -0
  622. data/spec/internal/app/constructors/organization_constructor.rb +4 -0
  623. data/spec/internal/app/controllers/application_controller.rb +27 -0
  624. data/spec/internal/app/controllers/search_extensions.rb +3 -0
  625. data/spec/internal/app/indices/advisor_index.rb +35 -0
  626. data/spec/internal/app/indices/contract_index.rb +52 -0
  627. data/spec/internal/app/indices/firm_index.rb +16 -0
  628. data/spec/internal/app/indices/policy_index.rb +20 -0
  629. data/spec/internal/app/models/advisor.rb +24 -0
  630. data/spec/internal/app/models/agency.rb +3 -0
  631. data/spec/internal/app/models/anonymous_coward.rb +5 -0
  632. data/spec/internal/app/models/another_event.rb +2 -0
  633. data/spec/internal/app/models/appointment.rb +3 -0
  634. data/spec/internal/app/models/attachment.rb +10 -0
  635. data/spec/internal/app/models/basic_schedule.rb +6 -0
  636. data/spec/internal/app/models/beneficiary.rb +6 -0
  637. data/spec/internal/app/models/client.rb +5 -0
  638. data/spec/internal/app/models/contract.rb +9 -0
  639. data/spec/internal/app/models/demographic.rb +4 -0
  640. data/spec/internal/app/models/division.rb +3 -0
  641. data/spec/internal/app/models/event.rb +10 -0
  642. data/spec/internal/app/models/event_template.rb +1 -0
  643. data/spec/internal/app/models/firm.rb +18 -0
  644. data/spec/internal/app/models/has_audits/audit.rb +15 -0
  645. data/spec/internal/app/models/import.rb +7 -0
  646. data/spec/internal/app/models/meetup.rb +8 -0
  647. data/spec/internal/app/models/organization.rb +17 -0
  648. data/spec/internal/app/models/organization_event.rb +5 -0
  649. data/spec/internal/app/models/policy.rb +16 -0
  650. data/spec/internal/app/models/policy_holder.rb +7 -0
  651. data/spec/internal/app/models/policy_note.rb +8 -0
  652. data/spec/internal/app/models/project.rb +3 -0
  653. data/spec/internal/app/models/read_only_value.rb +8 -0
  654. data/spec/internal/app/models/schedule.rb +12 -0
  655. data/spec/internal/app/models/template.rb +9 -0
  656. data/spec/internal/app/models/user.rb +31 -0
  657. data/spec/internal/app/models/user_organization.rb +17 -0
  658. data/spec/internal/app/views/has_lists/lists/_table.html.erb +1 -0
  659. data/spec/internal/config/database-standard.yml +24 -0
  660. data/spec/internal/config/initializers/resources.rb +19 -0
  661. data/spec/internal/config/routes.rb +19 -0
  662. data/spec/internal/config/storage.yml +3 -0
  663. data/spec/internal/db/good_job_schema.rb +141 -0
  664. data/spec/internal/db/schema.rb +334 -0
  665. data/spec/internal/log/.gitignore +1 -0
  666. data/spec/internal/public/favicon.ico +0 -0
  667. data/spec/lib/flattener/base_spec.rb +93 -0
  668. data/spec/lib/flattener/column/types_spec.rb +65 -0
  669. data/spec/lib/has_helpers/active_record/base_spec.rb +53 -0
  670. data/spec/lib/has_helpers/active_record/date_range_spec.rb +498 -0
  671. data/spec/lib/has_helpers/active_record/lookup_model_spec.rb +408 -0
  672. data/spec/lib/has_helpers/active_record/nested_resource_spec.rb +43 -0
  673. data/spec/lib/has_helpers/app/command/reports/generator_specs.rb +887 -0
  674. data/spec/lib/has_helpers/app/command_spec.rb +117 -0
  675. data/spec/lib/has_helpers/app/support/mocks/graphql_reports_helpers.rb +96 -0
  676. data/spec/lib/has_helpers/app/support/mocks/reports_api_mock.rb +47 -0
  677. data/spec/lib/has_helpers/attributes_spec.rb +220 -0
  678. data/spec/lib/has_helpers/aws_spec.rb +126 -0
  679. data/spec/lib/has_helpers/concerns/hydrate_concern_spec.rb +473 -0
  680. data/spec/lib/has_helpers/constant/definition_spec.rb +128 -0
  681. data/spec/lib/has_helpers/constant_spec.rb +432 -0
  682. data/spec/lib/has_helpers/core_ext/array_spec.rb +22 -0
  683. data/spec/lib/has_helpers/core_ext/date/infinity_spec.rb +67 -0
  684. data/spec/lib/has_helpers/core_ext/date_spec.rb +27 -0
  685. data/spec/lib/has_helpers/core_ext/false_class_spec.rb +7 -0
  686. data/spec/lib/has_helpers/core_ext/float_spec.rb +9 -0
  687. data/spec/lib/has_helpers/core_ext/hash_spec.rb +48 -0
  688. data/spec/lib/has_helpers/core_ext/integer_spec.rb +9 -0
  689. data/spec/lib/has_helpers/core_ext/nil_class_spec.rb +17 -0
  690. data/spec/lib/has_helpers/core_ext/object_spec.rb +54 -0
  691. data/spec/lib/has_helpers/core_ext/proc_spec.rb +24 -0
  692. data/spec/lib/has_helpers/core_ext/string_spec.rb +154 -0
  693. data/spec/lib/has_helpers/core_ext/true_class_spec.rb +7 -0
  694. data/spec/lib/has_helpers/data_migration/base_spec.rb +470 -0
  695. data/spec/lib/has_helpers/data_migration/large_worker_spec.rb +34 -0
  696. data/spec/lib/has_helpers/data_migration/master_worker_spec.rb +51 -0
  697. data/spec/lib/has_helpers/data_migration/migrator_spec.rb +113 -0
  698. data/spec/lib/has_helpers/data_migration/model_spec.rb +52 -0
  699. data/spec/lib/has_helpers/data_migration/small_worker_spec.rb +34 -0
  700. data/spec/lib/has_helpers/good_job/notification_alert_cleanup_worker_spec.rb +89 -0
  701. data/spec/lib/has_helpers/hash_accessors_spec.rb +66 -0
  702. data/spec/lib/has_helpers/index_spec.rb +442 -0
  703. data/spec/lib/has_helpers/lazy_config_spec.rb +31 -0
  704. data/spec/lib/has_helpers/organization_merge_spec.rb +88 -0
  705. data/spec/lib/has_helpers/resource_importer_spec.rb +119 -0
  706. data/spec/lib/has_helpers/rspec_spec.rb +16 -0
  707. data/spec/lib/has_helpers/search/provider_spec.rb +26 -0
  708. data/spec/lib/has_helpers/search/search_utils_spec.rb +134 -0
  709. data/spec/lib/has_helpers/sentry/graphql_trace_spec.rb +140 -0
  710. data/spec/lib/has_helpers/ui_attributes_spec.rb +42 -0
  711. data/spec/lib/has_helpers/utils/action_spec.rb +49 -0
  712. data/spec/lib/has_helpers/utils/alert_spec.rb +33 -0
  713. data/spec/lib/has_helpers/utils/dataset_spec.rb +10 -0
  714. data/spec/lib/has_helpers/utils/icon_spec.rb +23 -0
  715. data/spec/lib/has_helpers/utils/input_spec.rb +40 -0
  716. data/spec/lib/has_helpers/utils/log_notifier_spec.rb +25 -0
  717. data/spec/lib/has_helpers/utils/render_object_spec.rb +17 -0
  718. data/spec/lib/has_helpers/utils/s3_utils_spec.rb +78 -0
  719. data/spec/lib/has_helpers/utils/service_spec.rb +79 -0
  720. data/spec/lib/has_helpers/utils/slack_notifier_spec.rb +70 -0
  721. data/spec/lib/has_helpers/utils/user_restrictions_spec.rb +343 -0
  722. data/spec/lib/hq/structure/inserts_spec.rb +152 -0
  723. data/spec/lib/hq/structure_spec.rb +12 -0
  724. data/spec/models/cards/base_spec.rb +149 -0
  725. data/spec/models/cards/card_definition_resource_spec.rb +103 -0
  726. data/spec/models/cards/card_definition_spec.rb +50 -0
  727. data/spec/models/cards/card_field_spec.rb +46 -0
  728. data/spec/models/cards/field_builder_spec.rb +318 -0
  729. data/spec/models/cards/registry_spec.rb +147 -0
  730. data/spec/models/cards/role_card_field_spec.rb +111 -0
  731. data/spec/models/cards/role_resource_card_spec.rb +112 -0
  732. data/spec/models/has_helpers/master_record_spec.rb +20 -0
  733. data/spec/models/has_helpers/user_organization_spec.rb +28 -0
  734. data/spec/models/has_helpers/user_session_spec.rb +16 -0
  735. data/spec/presenters/base_presenter_spec.rb +166 -0
  736. data/spec/rails_helper.rb +119 -0
  737. data/spec/requests/has_helpers/factory_controller_spec.rb +159 -0
  738. data/spec/requests/has_helpers/health_check_controller_spec.rb +37 -0
  739. data/spec/scenarios/empty_setup.rb +6 -0
  740. data/spec/spec_helper.rb +22 -0
  741. data/spec/support/has_helpers/database_helpers.rb +12 -0
  742. data/spec/utils/sync_utils_spec.rb +233 -0
  743. data/spec/workers/goodjob/elasticsearch_process_batch_spec.rb +94 -0
  744. data/spec/workers/goodjob/elasticsearch_process_change_logs_master_worker_spec.rb +40 -0
  745. data/spec/workers/goodjob/elasticsearch_process_change_logs_worker_spec.rb +82 -0
  746. data/spec/workers/goodjob/elasticsearch_process_queue_spec.rb +89 -0
  747. data/spec/workers/goodjob/elasticsearch_reindex_spec.rb +49 -0
  748. metadata +1593 -0
@@ -0,0 +1,23 @@
1
+ # Elasticsearch
2
+
3
+ ## Setup
4
+
5
+ * Install Elasticsearch `brew install elasticsearch`.
6
+ * Use `brew info elasticsearch` for instructions on starting.
7
+ * Run `rake search:views` to create the views used for indexing.
8
+
9
+ ## Indexing
10
+
11
+ * Make sure sidekiq is running, and `rake search:views` has been run.
12
+ * Run `rake search:reindex` to reindex all classes. Note that this rake task
13
+ can only be run in the development environment. Indexes should always be
14
+ run individually in production.
15
+ * To index one class, run `index_class.reindex`.
16
+ * To reindex one record, run `record.reindex`. This may fail in development
17
+ if the index class has not yet been loaded.
18
+
19
+ ## Common Resolutions to Issues
20
+
21
+ * If seeing errors about a view not existing, run `rake search:views`.
22
+ * If seeing errors from elasticsearch about field types, run `rake search:clean`,
23
+ then `rake search:reindex`.
@@ -0,0 +1,126 @@
1
+ # Search API
2
+
3
+ ## Set up
4
+
5
+ * Application resources
6
+
7
+ Queries must be made against a resource or set of resources. Each `HasHelpers::Application` has a set of
8
+ `HasHelpers::Resource` records. These are used to determine whether the current user can search the specified resource(
9
+ s), so you should define them appropriately.
10
+
11
+ * Mount the SearchAPI Rack Application
12
+
13
+ Just add a new line to your routes file to mount `HasHelpers::SearchAPI`. You can just copy and paste this if you want:
14
+
15
+ ```ruby
16
+ mount ::HasHelpers::SearchAPI => "/search" # You can customize the URL.
17
+ ```
18
+
19
+ * Search Providers
20
+
21
+ Framework ships with search providers (currently the two options are SQL and Sphinx) and defaults to SQL searches. SQL
22
+ searches can be customized and Sphinx will need some further setup. Read about how to do those things and more about
23
+ providers in the [Search Providers](#search-provider) section below.
24
+
25
+ ## Requests
26
+
27
+ Requests should be made to the path which was specified when mounting the SearchAPI Rack application.
28
+
29
+ ### Request Format
30
+
31
+ Currently only JSON requests are accepted.
32
+
33
+ ### Responses
34
+
35
+ All responses will return a JSON body.
36
+
37
+ A successful response will return a payload with the results and pagination information. These will be wrapped in a
38
+ top-level object which will have the following keys: `"resources"`, `"current_page"`, `"per_page"`, and
39
+ `"total_entries"`.
40
+
41
+ #### Errors
42
+
43
+ If an error response was received with a status in the 4xx-5xx range then the response body will included a top level
44
+ object with an "errors" key and follows the [JSONAPI standard](http://jsonapi.org/format/).
45
+
46
+ ```json
47
+ {
48
+ "errors": [
49
+ {
50
+ "title": "Something went wrong."
51
+ }
52
+ ]
53
+ }
54
+ ```
55
+
56
+ ### Query Parameters
57
+
58
+ | Parameter | Description |
59
+ |-----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
60
+ | `query` | What you want to search for. I'm pretty sure you already understood this. |
61
+ | `resource` (optional) | A comma-separated list of resource types. Resources must be from the set which configured for the current application. E.g. `Advisor` or `Client,Firm`. Omitting this parameter will cause the query to search all resources. _Currently SQL searches do not support multiple resources and will only use the first resource which is specified._ |
62
+ | `with` (optional) | A common-separated list of key value pairs where each key and value are separated by a colon (`:`), e.g. `firm_id:123,carrier_id:456`. _Currently "with" options only have an effect for Sphinx searches._ |
63
+
64
+ An example search URL might look something like this:
65
+ `http://example.com/search?resource=Advisor,Client&query=Fredo&with=firm_id`
66
+
67
+ ## Search Providers
68
+
69
+ HasHelpers ships with search providers out of the box. Currently those are SQL (`HasHelpers::Query::SQL`) and Sphinx (
70
+ `HasHelpers::Query::Sphinx`). SQL search is the default.
71
+
72
+ ### SQL Search
73
+
74
+ Out of the box you should be able to use SQL searches as long as your resource tables each have a `name` column. You may
75
+ specify your own method to perform SQL searches by defining class-level method named `sql_search` to your resource
76
+ model. Note that custom SQL searches are responsible for querying and paginating records.
77
+
78
+ Here is a very simple example of a custom sql_search method:
79
+
80
+ ```ruby
81
+ # MyResource
82
+ def self.sql_search(query, options)
83
+ where(options)
84
+ .where(name: query)
85
+ .page(options[:page] || 1)
86
+ .per_page(options[:per_page] || 15)
87
+ end
88
+ ```
89
+
90
+ ### Sphinx Search
91
+
92
+ You will need to add `sphinx` and the `thinking-sphinx` gems to your application if you want to use Sphinx searches.
93
+
94
+ ### Accessing and Setting the Search Provider
95
+
96
+ The current search provider is accessible and may be set at the application level through `HasHelpers::Query` methods.
97
+
98
+ Accessing the current provider:
99
+
100
+ ```ruby
101
+ HasHelpers::Query.provider # => HasHelpers::Query::Sphinx
102
+ ```
103
+
104
+ Setting the current provider:
105
+
106
+ ```ruby
107
+ HasHelpers::Query.provider = HasHelpers::Query::SQL
108
+ ```
109
+
110
+ You can also set the provider to a proc to provide a dynamic way of getting a provider.
111
+
112
+ ```ruby
113
+ HasHelpers::Query.provider = -> {
114
+ HasHelpers::Application.current_application.search_provider # Look up the search provider dynamically
115
+ }
116
+ ```
117
+
118
+ ### Adding a Custom Search Provider
119
+
120
+ The recommended way is to create a class which includes `HasHelpers::Query::Provider`. Then override the `exec_query`
121
+ instance method.
122
+
123
+ Bare bones way: Create a provider class which has a `search` method that accepts `:query`, `:resource`, and `:options`
124
+ keyword arguments. You are on your own after that!
125
+
126
+ Take a look at the stock provider classes if you need some guidance.
@@ -0,0 +1,107 @@
1
+ # Cards Role Proxy
2
+
3
+ Cards can resolve role visibility through `HasHelpers::Cards::Roles` instead of reading `HasHelpers::Role` directly. This lets admin apps keep the authoritative `roles` table while consumer apps render cards against remote role data.
4
+
5
+ The proxy is built on top of `HasHelpers::ServiceTrust`, so both apps must configure ServiceTrust before configuring Cards. `issuer` and `audience` in `Cards.config` must match the values used in ServiceTrust on each side.
6
+
7
+ ## ServiceTrust configuration
8
+
9
+ Admin/server app — trusts the consumer to call `roles:read`:
10
+
11
+ ```ruby
12
+ ::HasHelpers::ServiceTrust.configure do |config|
13
+ config.issuer = "hqadmin"
14
+ config.environment = Rails.env
15
+ config.trusted_issuers do |_env, register|
16
+ register.call("hqadmin", url: ENV.fetch("AGENCIESHQ_URL"), allowed_capabilities: "roles:read")
17
+ end
18
+ end
19
+ ```
20
+
21
+ Consumer/client app — points at the admin's JWKS:
22
+
23
+ ```ruby
24
+ ::HasHelpers::ServiceTrust.configure do |config|
25
+ config.issuer = "agencieshq"
26
+ config.environment = Rails.env
27
+ config.trusted_issuers do |_env, register|
28
+ register.call("hqadmin", url: ENV.fetch("HQADMIN_URL"))
29
+ end
30
+ end
31
+ ```
32
+
33
+ Each app generates and persists its own signing keypair (`HasHelpers::ServiceTrust::KeyManager.current_signing_key`) on first boot; the keypair is encrypted at rest via the Rails master key.
34
+
35
+ ## Cards configuration
36
+
37
+ Admin/server app:
38
+
39
+ ```ruby
40
+ HasHelpers::Cards.configure do |config|
41
+ config.mode = :server
42
+ config.issuer = "hqadmin"
43
+ end
44
+ ```
45
+
46
+ Consumer/client app:
47
+
48
+ ```ruby
49
+ HasHelpers::Cards.configure do |config|
50
+ config.mode = :client
51
+ config.issuer = "agencieshq"
52
+ config.audience = "hqadmin"
53
+ config.base_url = ENV.fetch("HQADMIN_URL")
54
+ config.redis = RedisConf.current
55
+ end
56
+ ```
57
+
58
+ Client mode requires Redis.
59
+
60
+ ## Admin GraphQL
61
+
62
+ Mount the internal role fields in the admin app's service-trust-gated internal schema and put it behind `VerifyMiddleware`:
63
+
64
+ ```ruby
65
+ class InternalQuery < GraphQL::Schema::Object
66
+ HasHelpers::Resolvers::Internal::Roles.mount(self)
67
+ end
68
+
69
+ class InternalSchema < GraphQL::Schema
70
+ query InternalQuery
71
+ end
72
+
73
+ # config/routes.rb (admin app)
74
+ mount HasHelpers::ServiceTrust::VerifyMiddleware.new(
75
+ ->(env) { InternalSchema.execute(...).to_h.then { |r| [200, {}, [r.to_json]] } },
76
+ paths: %r{\A/internal_graphql\z}
77
+ ), at: "/internal_graphql"
78
+ ```
79
+
80
+ The resolver enforces the `roles:read` ServiceTrust capability declared via `Authorizable`.
81
+
82
+ ## Consumer API
83
+
84
+ Use the facade:
85
+
86
+ ```ruby
87
+ HasHelpers::Cards::Roles.find(role_id)
88
+ HasHelpers::Cards::Roles.all
89
+ HasHelpers::Cards::Roles.where(ids: role_ids)
90
+ ```
91
+
92
+ `RoleResourceCard#role` also routes through the facade.
93
+
94
+ ## Orphan Sweeper
95
+
96
+ Register the sweeper in the consumer app's GoodJob cron configuration:
97
+
98
+ ```ruby
99
+ config.good_job.cron = {
100
+ cards_orphan_card_sweeper: {
101
+ cron: "0 3 * * *",
102
+ class: "HasHelpers::Cards::OrphanCardSweeper"
103
+ }
104
+ }
105
+ ```
106
+
107
+ The sweeper runs only in `:client` mode and soft-disables orphaned role cards by setting `disabled_at`.
@@ -0,0 +1,135 @@
1
+ # Factory API (test-only)
2
+
3
+ This API is meant for e2e/tests only and is disabled in production. It lives under the HasHelpers engine mount (e.g., `/has_helpers`).
4
+
5
+ All requests must include:
6
+
7
+ - `X-Factory-Api-Key`: must equal `TEST_FACTORY_API_KEY`.
8
+
9
+ The API is enabled when `Rails.env.test?` and `TEST_FACTORY_API_ENABLED=true`.
10
+
11
+ ## Endpoints
12
+
13
+ ### POST /test/factory/create
14
+
15
+ Create & persist via FactoryBot.
16
+
17
+ - Params: `resource` (required), `traits` [array], `payload` [hash], `include` (see Includes).
18
+ - Response: `201` with `{ id, attributes: { … } }`.
19
+
20
+ Example:
21
+
22
+ ```bash
23
+ curl -X POST /has_helpers/test/factory/create \
24
+ -H "Content-Type: application/json" \
25
+ -H "X-Factory-Api-Key: $TEST_FACTORY_API_KEY" \
26
+ -d '{"resource":"user","traits":["with_org"],"payload":{"username":"api_user@example.com"},"include":["organization"]}'
27
+ ```
28
+
29
+ ### POST /test/factory/build
30
+
31
+ Build (not persisted).
32
+
33
+ - Params: same as `create`.
34
+ - Response: `200` with `{ id, attributes: { … }, persisted: false }`.
35
+
36
+ Example:
37
+
38
+ ```bash
39
+ curl -X POST /has_helpers/test/factory/build \
40
+ -H "Content-Type: application/json" \
41
+ -H "X-Factory-Api-Key: $TEST_FACTORY_API_KEY" \
42
+ -d '{"resource":"user","include":["organization"]}'
43
+ ```
44
+
45
+ ### POST /test/factory/seed
46
+
47
+ Bulk create.
48
+
49
+ - Params: same as `create` plus `count` (required, >0).
50
+ - Response: `201` with an array of serialized records.
51
+
52
+ Example:
53
+
54
+ ```bash
55
+ curl -X POST /has_helpers/test/factory/seed \
56
+ -H "Content-Type: application/json" \
57
+ -H "X-Factory-Api-Key: $TEST_FACTORY_API_KEY" \
58
+ -d '{"resource":"user","count":3,"traits":["with_org"]}'
59
+ ```
60
+
61
+ ### GET /test/factory/:resource/:id
62
+
63
+ Fetch a persisted record.
64
+
65
+ - Query params: `include` supported.
66
+ - Response: `200` with serialized record; `404` if missing; `400` if factory unknown.
67
+
68
+ Example:
69
+
70
+ ```bash
71
+ curl -G /has_helpers/test/factory/advisor/123 \
72
+ -H "X-Factory-Api-Key: $TEST_FACTORY_API_KEY" \
73
+ --data-urlencode 'include=["organization"]'
74
+ ```
75
+
76
+ ## Includes (embedding associations)
77
+
78
+ Works on all endpoints; passed directly to `as_json(include: ...)`.
79
+
80
+ Accepted forms (JSON or native objects):
81
+
82
+ - Flat: `"include": ["organization","demographic"]`
83
+ - Nested: `"include": [{"organization":["firm"]},"demographic"]`
84
+ - Deep: `"include": [{"organization":{"firm":{"region":{}}}}]`
85
+ - Single: `"include": "organization"`
86
+
87
+ Meaning: each key is an association; nested values describe further includes for that association.
88
+
89
+ Examples:
90
+
91
+ ```bash
92
+ # advisor -> organization
93
+ --data-urlencode 'include=["organization"]'
94
+
95
+ # advisor -> organization -> firm, plus demographic
96
+ --data-urlencode 'include=[{"organization":["firm"]},"demographic"]'
97
+
98
+ # advisor -> organization -> firm -> region
99
+ --data-urlencode 'include=[{"organization":{"firm":{"region":{}}}}]'
100
+
101
+ ## POST /test/factory/scenario
102
+ Run a predefined FactoryScenario (Ruby DSL) with optional overrides/additions.
103
+
104
+ - Params:
105
+ - `scenario` (required): scenario name, e.g., `commissions/scenario_1`.
106
+ - `objects` (hash): keyed by alias. For aliases defined in the scenario, entries act as overrides; for unknown aliases, entries are created as new factories.
107
+ - `traits`: array of traits
108
+ - `attributes`: hash of overrides; supports references like `@alias` or `@alias.id`.
109
+ - `factory`: only needed for aliases not defined in the scenario (extras).
110
+ - `activate`: array of aliases to force-load if they aren't referenced elsewhere (optional).
111
+ - `include`: per-object only; provide a hash keyed by alias, where each value is an include spec.
112
+ - `response`: array of aliases to include in the response body. If omitted, only the aliases built during execution are returned.
113
+ - Response: `200` with a hash keyed by alias.
114
+
115
+ Example:
116
+
117
+ ```bash
118
+ curl -X POST /has_helpers/test/factory/scenario \
119
+ -H "Content-Type: application/json" \
120
+ -H "X-Factory-Api-Key: $TEST_FACTORY_API_KEY" \
121
+ -d '{
122
+ "scenario": "commissions/scenario_1",
123
+ "objects": {
124
+ "policy": { "traits": ["with_number"], "attributes": { "face_amount": 500000 } },
125
+ "advisor_3": { "traits": ["with_org"], "attributes": { "name": "Override Name" } },
126
+ "extra_schedule": {
127
+ "factory": "commission_schedule",
128
+ "traits": ["for_percent_of_premium"],
129
+ "attributes": { "organization": "@organization", "rate_percent": 77 }
130
+ }
131
+ },
132
+ "include": ["organization", {"policy": ["product","carrier"]}]
133
+ }'
134
+ ```
135
+ ```
@@ -0,0 +1,16 @@
1
+ USER-SUPPLIED VALUES:
2
+ gem-delivery:
3
+ rbac:
4
+ - role: edit
5
+ subjects:
6
+ - kind: Group
7
+ name: hq-product
8
+ git:
9
+ organization: OneHQ
10
+ ref: refs/pull/289/head
11
+ repository: has_helpers
12
+ sha: 09b2b7caa1e381e37a595753d47e27e523e5e53c
13
+ global:
14
+ taskAnnotations:
15
+ vault.security.banzaicloud.io/vault-role: has-helpers-pr-289-pipeline
16
+ publish: false
@@ -0,0 +1,15 @@
1
+ USER-SUPPLIED VALUES:
2
+ git:
3
+ organization: OneHQ
4
+ ref: refs/pull/289/head
5
+ repository: has_helpers
6
+ sha: 04a21aedd9d9e8d60e1672957c54d16b32732764
7
+ global:
8
+ taskAnnotations:
9
+ vault.security.banzaicloud.io/vault-role: has-helpers-pr-289-pipeline
10
+ publish: false
11
+ rbac:
12
+ - role: edit
13
+ subjects:
14
+ - kind: Group
15
+ name: hq-product
@@ -0,0 +1,68 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ $:.push File.expand_path("../lib", __FILE__)
5
+ require "has_helpers/version"
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "has_helpers"
9
+ s.version = HasHelpers::VERSION
10
+ s.required_ruby_version = ">= 3.4.0", "< 4.0.0"
11
+ s.summary = "HelpersHQ"
12
+ s.description = "Ruby helpers."
13
+ s.authors = ["Kyle J. Ginavan"]
14
+ s.email = ["kyle@onehq.com"]
15
+ s.homepage = "https://github.com/OneHQ/has_helpers"
16
+ s.licenses = ["HQ"]
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "aws-sdk-s3", "~> 1.46"
23
+ s.add_dependency "aws-sdk-sqs", "~> 1.22"
24
+ s.add_dependency "barby", "~> 0.6.8" # barcode generation
25
+ s.add_dependency "cancancan", "~> 3.0" # authorization (UserRestrictions is a CanCan::Ability)
26
+ s.add_dependency "chronic", "0.10.2"
27
+ s.add_dependency "chunky_png", "~> 1.3" # barcode generation to png
28
+ s.add_dependency "flipper", "~> 0.16"
29
+ s.add_dependency "flipper-redis", "~> 0.16"
30
+ s.add_dependency "flipper-ui", "~> 0.16"
31
+ s.add_dependency "holidays", "~> 8.4"
32
+ s.add_dependency "humanize", "~> 2.0"
33
+ s.add_dependency "jwt", "~> 2.7"
34
+ s.add_dependency "marginalia", "~> 1.8" # Insert comments into ActiveRecord queries. Useful for disabling pgpool.
35
+ # This is a workaround to avoid date format issues with Searchkick.indexer. TODO: Remove this multi_json version limit when elasticsearch-rails is updated to 8.x.
36
+ s.add_dependency "csv", "~> 3.3"
37
+ s.add_dependency "multi_json", ">= 1.11", "<= 1.17"
38
+ s.add_dependency "mustache", "~> 1.0"
39
+ s.add_dependency "observer", "~> 0.1"
40
+ s.add_dependency "opentelemetry-exporter-otlp", "~> 0.24"
41
+ s.add_dependency "opentelemetry-instrumentation-all", "~> 0.27"
42
+ s.add_dependency "opentelemetry-sdk", "~> 1.5"
43
+ s.add_dependency "rails", ">= 6.0", "< 7.2.4"
44
+ s.add_dependency "redcarpet", "~> 3.0"
45
+ s.add_dependency "searchkick", "~> 4.1"
46
+ s.add_dependency "sidekiq", "~> 6.0"
47
+ s.add_dependency "sidekiq-ent", "~> 2.0"
48
+ s.add_dependency "sidekiq-pro", "~> 5.0"
49
+ s.add_dependency "slack-ruby-client", "~> 1.0"
50
+ s.add_dependency "sorbet-runtime", "~> 0.0"
51
+ s.add_dependency "spreadsheet_architect", "~> 4.1"
52
+ s.add_dependency "strong_migrations", "~> 2.5" # helps ensure bad things don't happen in migrations
53
+ s.add_dependency "wicked_pdf", "~> 1.4"
54
+ s.add_dependency "will_paginate", "~> 3.1"
55
+
56
+ s.add_development_dependency "kt-paperclip", "~> 7.2"
57
+ s.add_development_dependency "sorbet", "~> 0.6"
58
+ s.add_development_dependency "sprockets", "~> 3.0"
59
+
60
+ # hq
61
+ s.add_dependency "has_owner", "~> 5.0.0"
62
+ s.add_dependency "has_utils", "~> 5.0.0"
63
+ s.add_dependency "has_validated_attributes", "~> 5.0.0"
64
+ s.add_dependency "hq-graphql", "~> 5.0.0"
65
+ s.add_dependency "psql_hq", "~> 5.0.0"
66
+
67
+ s.add_development_dependency "testhq", "~> 5.0.0"
68
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ # If you would like to use these methods in a Rails migration, make sure you
4
+ # add this require line at the top of your migration file:
5
+ # require "active_migration_patch"
6
+ class ActiveRecord::Migration
7
+ def conditionally_add_index(table, columns, opts = {})
8
+ add_index(table, columns, opts) unless index_exists?(table, columns, opts)
9
+ end
10
+
11
+ # Adds a foreign key based on the arguments passed in. If organization_id is
12
+ # not already part of the from_columns, it adds it to both the from_columns
13
+ # and to_columns. The default foreign key name will use the same format we
14
+ # used in our data migrations to initially update all foreign keys to include
15
+ # organization_id.
16
+ # from_table: name of the table the fk constraint is on (symbol or string)
17
+ # to_table: name of the table the fk references (symbol or string)
18
+ # from_columns (optional): name of the fk column(s) in from_table; defaults
19
+ # to using the standard foreign key name for the to_table - e.g.,
20
+ # "client_id" if the to_table is "clients" (symbol, string, or array of
21
+ # symbols and/or strings)
22
+ # to_columns (optional): name of the referenced column(s) in to_table;
23
+ # defaults to "id" (symbol, string, or array of symbols and/or strings)
24
+ # name (optional): name for the foreign key constraint
25
+ # If you pass in from_columns and to_columns, the columns should be ordered
26
+ # so the first references the first, the second references the second etc.
27
+ #
28
+ # EXAMPLES:
29
+ # add_org_scoped_foreign_key(from_table: :trustees, to_table: :clients)
30
+ # add_org_scoped_foreign_key(
31
+ # from_table: :advisors,
32
+ # to_table: :users,
33
+ # from_columns: :created_by_id
34
+ # )
35
+ # add_org_scoped_foreign_key(
36
+ # from_table: :toys,
37
+ # to_table: "factories",
38
+ # from_columns: [:factory_id, "toy_category_id"]
39
+ # to_columns: ["id", :toy_category_id]
40
+ # )
41
+ def add_org_scoped_foreign_key(from_table:, to_table:, from_columns: nil, to_columns: nil, name: nil, validate: true)
42
+ from_columns, to_columns = foreign_key_columns(to_table: to_table, from_columns: from_columns, to_columns: to_columns)
43
+ add_compound_foreign_key(
44
+ from_table: from_table,
45
+ to_table: to_table,
46
+ from_columns: from_columns,
47
+ to_columns: to_columns,
48
+ name: name,
49
+ validate: validate
50
+ )
51
+ end
52
+
53
+ def validate_org_scoped_foreign_key(from_table:, to_table:, from_columns: nil, to_columns: nil, name: nil)
54
+ from_columns, to_columns = foreign_key_columns(to_table: to_table, from_columns: from_columns, to_columns: to_columns)
55
+ name ||= compound_foreign_key_name(
56
+ from_table: from_table,
57
+ to_table: to_table,
58
+ from_columns: from_columns,
59
+ to_columns: to_columns
60
+ )
61
+
62
+ ActiveRecord::Base.connection_pool.with_connection do |conn|
63
+ conn.execute <<-END_OF_SQL
64
+ ALTER TABLE #{from_table}
65
+ VALIDATE CONSTRAINT #{name};
66
+ END_OF_SQL
67
+ end
68
+ end
69
+
70
+ # Adds a compound foreign key based on the arguments passed in.
71
+ # from_table: name of the table the fk constraint is on (symbol or string)
72
+ # to_table: name of the table the fk references (symbol or string)
73
+ # from_columns (optional): name of the fk column(s) in from_table; defaults
74
+ # to using the standard foreign key name for the to_table - e.g.,
75
+ # "client_id" if the to_table is "clients" (symbol, string, or array of
76
+ # symbols and/or strings)
77
+ # to_columns (optional): name of the referenced column(s) in to_table;
78
+ # defaults to "id" (symbol, string, or array of symbols and/or strings)
79
+ # name (optional): name for the foreign key constraint
80
+ # If you pass in from_columns and to_columns, the columns should be ordered
81
+ # so the first references the first, the second references the second etc.
82
+ def add_compound_foreign_key(from_table:, to_table:, from_columns:, to_columns:, name: nil, validate: true)
83
+ name ||= compound_foreign_key_name(
84
+ from_table: from_table,
85
+ to_table: to_table,
86
+ from_columns: from_columns,
87
+ to_columns: to_columns
88
+ )
89
+
90
+ ActiveRecord::Base.connection_pool.with_connection do |conn|
91
+ conn.execute <<-END_OF_SQL
92
+ ALTER TABLE #{from_table}
93
+ ADD CONSTRAINT #{name}
94
+ FOREIGN KEY (#{from_columns.join(",")})
95
+ REFERENCES #{to_table} (#{to_columns.join(",")})
96
+ #{"NOT VALID" unless validate}
97
+ DEFERRABLE INITIALLY DEFERRED;
98
+ END_OF_SQL
99
+ end
100
+ end
101
+
102
+ # Returns a name for the foreign key constraint. If the from_columns include
103
+ # organization_id, the name begins with "org_id_fk_"; otherwise, it starts with "compound_fk_".
104
+ def compound_foreign_key_name(from_table:, to_table:, from_columns:, to_columns:)
105
+ from_columns = from_columns.map(&:to_s)
106
+ to_columns = to_columns.map(&:to_s)
107
+ prefix = from_columns.include?("organization_id") ? "org_id" : "compound"
108
+
109
+ "#{prefix}_fk_#{::Digest::MD5.hexdigest([from_table.to_s, from_columns, to_table.to_s, to_columns].flatten.join("."))}"
110
+ end
111
+
112
+ def foreign_key_columns(to_table:, from_columns: nil, to_columns: nil)
113
+ from_columns = from_columns.blank? ? [to_table.to_s.singularize.foreign_key] : Array(from_columns)
114
+ to_columns = to_columns.blank? ? ["id"] : Array(to_columns)
115
+
116
+ unless from_columns.map(&:to_s).include?("organization_id")
117
+ from_columns << "organization_id"
118
+ to_columns << "organization_id"
119
+ end
120
+
121
+ return from_columns, to_columns
122
+ end
123
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Installs necessary files for using HasHelpers.
3
+
4
+ Example:
5
+ rails generate has_helpers:install
6
+
7
+ This will create (or modify):
8
+ db/migrate/?_has_helpers_initial_setup.rb
@@ -0,0 +1,22 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ require "rails/generators/active_record"
5
+
6
+ class HasHelpers::InstallGenerator < Rails::Generators::Base
7
+ include Rails::Generators::Migration
8
+
9
+ source_root File.expand_path("../templates", __FILE__)
10
+ class_option :skip_migrations, type: :boolean, default: false, description: "Copies migration files for HasHelpers models."
11
+
12
+ def self.next_migration_number(path)
13
+ ActiveRecord::Generators::Base.next_migration_number(path)
14
+ end
15
+
16
+ def copy_migrations
17
+ return if options.skip_migrations?
18
+ Dir["#{File.expand_path('../templates', __FILE__)}/migrate/*.rb"].each do |migration|
19
+ migration_template "migrate/#{File.basename(migration)}", "db/migrate/#{File.basename(migration)}"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ class HasHelpersInitialSetup < ActiveRecord::Migration
5
+ def change
6
+ #################
7
+ #### Options ####
8
+ #################
9
+ create_table :options do |t|
10
+ t.string :type, limit: 63, null: false
11
+ t.string :name, limit: 127, null: false
12
+ t.timestamps null: false
13
+ end
14
+ add_index :options, [:type, :name], unique: true
15
+ add_index :options, :name
16
+
17
+ ####################
18
+ #### Time Zones ####
19
+ ####################
20
+ create_table :time_zones do |t|
21
+ t.string :name, limit: 127, null: false
22
+ t.string :pg_timezone_name, limit: 127, null: false
23
+ t.timestamps null: false
24
+ end
25
+ end
26
+ end