glib-web 0.5.97 → 0.5.98

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 (192) hide show
  1. checksums.yaml +4 -4
  2. data/app/channels/glib/channel/is_typing_channel.rb +34 -34
  3. data/app/channels/glib/channel/online_channel.rb +36 -36
  4. data/app/controllers/concerns/glib/analytics/funnel.rb +61 -61
  5. data/app/controllers/concerns/glib/auth/policy.rb +149 -149
  6. data/app/controllers/concerns/glib/json/dynamic_text.rb +126 -126
  7. data/app/controllers/concerns/glib/json/libs.rb +149 -149
  8. data/app/controllers/concerns/glib/json/new_dynamic_text.rb +122 -122
  9. data/app/controllers/concerns/glib/json/transformation.rb +11 -11
  10. data/app/controllers/concerns/glib/json/traversal.rb +92 -92
  11. data/app/controllers/concerns/glib/json/ui.rb +88 -88
  12. data/app/controllers/concerns/glib/json/validation.rb +13 -13
  13. data/app/controllers/glib/home_controller.rb +54 -54
  14. data/app/helpers/glib/app_feature_support_helper.rb +16 -16
  15. data/app/helpers/glib/dynamic_images_helper.rb +55 -55
  16. data/app/helpers/glib/dynamic_texts_helper.rb +42 -42
  17. data/app/helpers/glib/enum_helper.rb +18 -18
  18. data/app/helpers/glib/forms_helper.rb +15 -15
  19. data/app/helpers/glib/json_ui/abstract_builder.rb +309 -309
  20. data/app/helpers/glib/json_ui/action_builder/dialogs.rb +58 -58
  21. data/app/helpers/glib/json_ui/action_builder/http.rb +39 -39
  22. data/app/helpers/glib/json_ui/action_builder/iap.rb +15 -15
  23. data/app/helpers/glib/json_ui/action_builder/panels.rb +14 -14
  24. data/app/helpers/glib/json_ui/action_builder/sheets.rb +15 -15
  25. data/app/helpers/glib/json_ui/action_builder/snackbars.rb +41 -41
  26. data/app/helpers/glib/json_ui/action_builder/windows.rb +38 -38
  27. data/app/helpers/glib/json_ui/action_builder.rb +140 -140
  28. data/app/helpers/glib/json_ui/analytics_helper.rb +17 -17
  29. data/app/helpers/glib/json_ui/dynamic_field_builders.rb +25 -25
  30. data/app/helpers/glib/json_ui/generic_builders.rb +28 -28
  31. data/app/helpers/glib/json_ui/list_builders.rb +110 -110
  32. data/app/helpers/glib/json_ui/menu_builder.rb +96 -96
  33. data/app/helpers/glib/json_ui/page_helper.rb +221 -221
  34. data/app/helpers/glib/json_ui/response_helper.rb +25 -25
  35. data/app/helpers/glib/json_ui/styling_helper.rb +55 -55
  36. data/app/helpers/glib/json_ui/table_builders.rb +74 -74
  37. data/app/helpers/glib/json_ui/view_builder/banners.rb +26 -26
  38. data/app/helpers/glib/json_ui/view_builder/charts.rb +49 -49
  39. data/app/helpers/glib/json_ui/view_builder/fields.rb +296 -296
  40. data/app/helpers/glib/json_ui/view_builder/iap.rb +11 -11
  41. data/app/helpers/glib/json_ui/view_builder/panels.rb +262 -262
  42. data/app/helpers/glib/json_ui/view_builder.rb +256 -253
  43. data/app/helpers/glib/urls_helper.rb +12 -12
  44. data/app/models/concerns/glib/soft_deletable.rb +73 -73
  45. data/app/models/glib/active_storage/attachment.rb +9 -9
  46. data/app/models/glib/active_storage/blob.rb +9 -9
  47. data/app/models/glib/application_record.rb +18 -18
  48. data/app/models/glib/dynamic_text_record.rb +9 -9
  49. data/app/models/glib/text.rb +95 -95
  50. data/app/policies/glib/application_policy.rb +191 -191
  51. data/app/validators/email_typo_validator.rb +38 -38
  52. data/app/validators/email_validator.rb +7 -7
  53. data/app/validators/url_validator.rb +20 -20
  54. data/app/views/json_ui/garage/_nav_menu.json.jbuilder +72 -72
  55. data/app/views/json_ui/garage/actions/_dialogs.json.jbuilder +104 -104
  56. data/app/views/json_ui/garage/actions/_http.json.jbuilder +24 -24
  57. data/app/views/json_ui/garage/actions/_panels.json.jbuilder +18 -18
  58. data/app/views/json_ui/garage/actions/_reload.json.jbuilder +17 -17
  59. data/app/views/json_ui/garage/actions/_sheets.json.jbuilder +18 -18
  60. data/app/views/json_ui/garage/actions/_snackbars.json.jbuilder +33 -33
  61. data/app/views/json_ui/garage/actions/_timeouts.json.jbuilder +24 -24
  62. data/app/views/json_ui/garage/actions/_windows.json.jbuilder +24 -24
  63. data/app/views/json_ui/garage/actions/dialogs_oauth_post.json.jbuilder +6 -6
  64. data/app/views/json_ui/garage/actions/index.json.jbuilder +24 -24
  65. data/app/views/json_ui/garage/forms/_alert_post_data.json.jbuilder +10 -10
  66. data/app/views/json_ui/garage/forms/basic.json.jbuilder +21 -21
  67. data/app/views/json_ui/garage/forms/basic_post.json.jbuilder +8 -8
  68. data/app/views/json_ui/garage/forms/checkboxes.json.jbuilder +27 -27
  69. data/app/views/json_ui/garage/forms/conditional_value.json.jbuilder +38 -38
  70. data/app/views/json_ui/garage/forms/dynamic_group.json.jbuilder +39 -39
  71. data/app/views/json_ui/garage/forms/dynamic_select.json.jbuilder +24 -24
  72. data/app/views/json_ui/garage/forms/dynamic_select_data.json.jbuilder +38 -38
  73. data/app/views/json_ui/garage/forms/file_upload.json.jbuilder +37 -37
  74. data/app/views/json_ui/garage/forms/floating_submit.json.jbuilder +19 -19
  75. data/app/views/json_ui/garage/forms/generic_post.json.jbuilder +3 -3
  76. data/app/views/json_ui/garage/forms/get_request.json.jbuilder +27 -27
  77. data/app/views/json_ui/garage/forms/index.json.jbuilder +120 -120
  78. data/app/views/json_ui/garage/forms/new_rich_text.json.jbuilder +40 -40
  79. data/app/views/json_ui/garage/forms/online_participant1.json.jbuilder +25 -25
  80. data/app/views/json_ui/garage/forms/online_participant2.json.jbuilder +25 -25
  81. data/app/views/json_ui/garage/forms/payments.json.jbuilder +34 -34
  82. data/app/views/json_ui/garage/forms/pickers.json.jbuilder +89 -89
  83. data/app/views/json_ui/garage/forms/ratings.json.jbuilder +49 -49
  84. data/app/views/json_ui/garage/forms/rich_text.json.jbuilder +40 -40
  85. data/app/views/json_ui/garage/forms/selects.json.jbuilder +91 -91
  86. data/app/views/json_ui/garage/forms/show_hide.json.jbuilder +150 -150
  87. data/app/views/json_ui/garage/forms/styled_boxes.json.jbuilder +35 -35
  88. data/app/views/json_ui/garage/forms/submission_flow.json.jbuilder +17 -17
  89. data/app/views/json_ui/garage/forms/submission_flow_post.json.jbuilder +26 -26
  90. data/app/views/json_ui/garage/forms/submission_indicator.json.jbuilder +63 -63
  91. data/app/views/json_ui/garage/forms/submission_indicator_post.json.jbuilder +25 -25
  92. data/app/views/json_ui/garage/forms/submit_on_change.json.jbuilder +28 -28
  93. data/app/views/json_ui/garage/forms/text_validation.json.jbuilder +65 -65
  94. data/app/views/json_ui/garage/forms/timers.json.jbuilder +120 -120
  95. data/app/views/json_ui/garage/home/blank.json.jbuilder +10 -10
  96. data/app/views/json_ui/garage/home/index.json.jbuilder +36 -36
  97. data/app/views/json_ui/garage/home/slow.json.jbuilder +11 -11
  98. data/app/views/json_ui/garage/lists/_autoload_section.json.jbuilder +30 -30
  99. data/app/views/json_ui/garage/lists/autoload_all.json.jbuilder +32 -32
  100. data/app/views/json_ui/garage/lists/autoload_as_needed.json.jbuilder +35 -35
  101. data/app/views/json_ui/garage/lists/autoload_as_needed_responsive_columns.json.jbuilder +27 -27
  102. data/app/views/json_ui/garage/lists/chat_ui.json.jbuilder +94 -94
  103. data/app/views/json_ui/garage/lists/edit_actions.json.jbuilder +62 -62
  104. data/app/views/json_ui/garage/lists/fab.json.jbuilder +12 -12
  105. data/app/views/json_ui/garage/lists/index.json.jbuilder +41 -41
  106. data/app/views/json_ui/garage/lists/reordering.json.jbuilder +34 -34
  107. data/app/views/json_ui/garage/lists/templating.json.jbuilder +35 -35
  108. data/app/views/json_ui/garage/notifications/action_cable.json.jbuilder +114 -114
  109. data/app/views/json_ui/garage/notifications/android_post.json.jbuilder +48 -48
  110. data/app/views/json_ui/garage/notifications/index.json.jbuilder +36 -36
  111. data/app/views/json_ui/garage/notifications/web_socket.json.jbuilder +60 -60
  112. data/app/views/json_ui/garage/pages/flat_centered.json.jbuilder +29 -29
  113. data/app/views/json_ui/garage/pages/full_width.json.jbuilder +29 -29
  114. data/app/views/json_ui/garage/pages/full_width_height.json.jbuilder +16 -16
  115. data/app/views/json_ui/garage/pages/index.json.jbuilder +62 -62
  116. data/app/views/json_ui/garage/pages/layout.json.jbuilder +18 -18
  117. data/app/views/json_ui/garage/pages/lifecycle_hooks.json.jbuilder +13 -13
  118. data/app/views/json_ui/garage/pages/loading_indicator.json.jbuilder +10 -10
  119. data/app/views/json_ui/garage/pages/nav_buttons.json.jbuilder +21 -21
  120. data/app/views/json_ui/garage/pages/nested_scroll.json.jbuilder +40 -40
  121. data/app/views/json_ui/garage/pages/tab_bar.json.jbuilder +92 -92
  122. data/app/views/json_ui/garage/panels/_styled.json.jbuilder +78 -78
  123. data/app/views/json_ui/garage/panels/card.json.jbuilder +4 -4
  124. data/app/views/json_ui/garage/panels/carousel.json.jbuilder +38 -38
  125. data/app/views/json_ui/garage/panels/custom.json.jbuilder +17 -17
  126. data/app/views/json_ui/garage/panels/flow.json.jbuilder +59 -59
  127. data/app/views/json_ui/garage/panels/horizontal.json.jbuilder +101 -101
  128. data/app/views/json_ui/garage/panels/index.json.jbuilder +138 -138
  129. data/app/views/json_ui/garage/panels/outlined.json.jbuilder +4 -4
  130. data/app/views/json_ui/garage/panels/responsive.json.jbuilder +98 -98
  131. data/app/views/json_ui/garage/panels/split.json.jbuilder +182 -182
  132. data/app/views/json_ui/garage/panels/ul.json.jbuilder +33 -33
  133. data/app/views/json_ui/garage/panels/vertical.json.jbuilder +55 -55
  134. data/app/views/json_ui/garage/panels/web.json.jbuilder +15 -15
  135. data/app/views/json_ui/garage/services/dynamic_text.json.jbuilder +13 -13
  136. data/app/views/json_ui/garage/services/image.json.jbuilder +47 -47
  137. data/app/views/json_ui/garage/services/index.json.jbuilder +17 -17
  138. data/app/views/json_ui/garage/tables/_autoload_section.json.jbuilder +16 -16
  139. data/app/views/json_ui/garage/tables/autoload_all.json.jbuilder +43 -43
  140. data/app/views/json_ui/garage/tables/autoload_as_needed.json.jbuilder +50 -50
  141. data/app/views/json_ui/garage/tables/export_import.json.jbuilder +29 -29
  142. data/app/views/json_ui/garage/tables/horizontal_scroll.json.jbuilder +26 -26
  143. data/app/views/json_ui/garage/tables/index.json.jbuilder +25 -25
  144. data/app/views/json_ui/garage/tables/layout.json.jbuilder +40 -40
  145. data/app/views/json_ui/garage/views/_chart_data.json.jbuilder +17 -17
  146. data/app/views/json_ui/garage/views/banners.json.jbuilder +67 -67
  147. data/app/views/json_ui/garage/views/calendar_data.json.jbuilder +30 -30
  148. data/app/views/json_ui/garage/views/charts.json.jbuilder +125 -125
  149. data/app/views/json_ui/garage/views/controls.json.jbuilder +60 -60
  150. data/app/views/json_ui/garage/views/iap.json.jbuilder +21 -21
  151. data/app/views/json_ui/garage/views/icon_names.json.jbuilder +1450 -1450
  152. data/app/views/json_ui/garage/views/icons.json.jbuilder +15 -15
  153. data/app/views/json_ui/garage/views/images.json.jbuilder +89 -89
  154. data/app/views/json_ui/garage/views/index.json.jbuilder +83 -83
  155. data/app/views/json_ui/garage/views/links.json.jbuilder +70 -70
  156. data/app/views/json_ui/garage/views/map_cluster_data.json.jbuilder +41 -41
  157. data/app/views/json_ui/garage/views/map_data.json.jbuilder +51 -51
  158. data/app/views/json_ui/garage/views/maps.json.jbuilder +31 -31
  159. data/app/views/json_ui/garage/views/markdowns.json.jbuilder +41 -41
  160. data/app/views/json_ui/garage/views/misc.json.jbuilder +34 -34
  161. data/app/views/json_ui/garage/views/progress.json.jbuilder +31 -31
  162. data/app/views/json_ui/garage/views/texts.json.jbuilder +35 -35
  163. data/app/views/layouts/json_ui/renderer.html.erb +35 -35
  164. data/config/routes.rb +7 -7
  165. data/lib/generators/glib/install_generator.rb +24 -24
  166. data/lib/generators/templates/20191017062519_create_texts.rb +12 -12
  167. data/lib/generators/templates/20191024063257_add_scope_to_texts.rb +7 -7
  168. data/lib/generators/templates/20191112095018_add_lang_to_texts.rb +7 -7
  169. data/lib/generators/templates/20191126071051_create_active_storage_tables.active_storage.rb +27 -27
  170. data/lib/generators/templates/database.yml +107 -107
  171. data/lib/generators/templates/dynamic_text.rb +2 -2
  172. data/lib/glib/crypt/utils.rb +26 -26
  173. data/lib/glib/dynamic_text/config.rb +21 -21
  174. data/lib/glib/engine.rb +7 -7
  175. data/lib/glib/json_crawler/action_crawler.rb +23 -23
  176. data/lib/glib/json_crawler/action_crawlers/action_http.rb +11 -11
  177. data/lib/glib/json_crawler/action_crawlers/forms_submit.rb +48 -48
  178. data/lib/glib/json_crawler/action_crawlers/menu.rb +12 -12
  179. data/lib/glib/json_crawler/action_crawlers/nav_initiate.rb +19 -19
  180. data/lib/glib/json_crawler/action_crawlers/run_multiple.rb +13 -13
  181. data/lib/glib/json_crawler/action_crawlers/windows_open.rb +33 -33
  182. data/lib/glib/json_crawler/coverage.rb +20 -20
  183. data/lib/glib/json_crawler/http.rb +120 -120
  184. data/lib/glib/json_crawler/router.rb +90 -90
  185. data/lib/glib/json_crawler.rb +11 -11
  186. data/lib/glib/mailer_tester.rb +36 -36
  187. data/lib/glib/test_helpers.rb +52 -52
  188. data/lib/glib/value.rb +7 -7
  189. data/lib/glib/version.rb +5 -5
  190. data/lib/glib-web.rb +9 -9
  191. data/lib/tasks/db.rake +95 -95
  192. metadata +2 -3
@@ -1,9 +1,9 @@
1
- module Glib
2
- module ActiveStorage
3
- class Attachment < ::ActiveStorage::Attachment
4
- if Glib::DynamicText::Config.database_url.present?
5
- connects_to database: { writing: :dynamic_text, reading: :dynamic_text }
6
- end
7
- end
8
- end
9
- end
1
+ module Glib
2
+ module ActiveStorage
3
+ class Attachment < ::ActiveStorage::Attachment
4
+ if Glib::DynamicText::Config.database_url.present?
5
+ connects_to database: { writing: :dynamic_text, reading: :dynamic_text }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,9 +1,9 @@
1
- module Glib
2
- module ActiveStorage
3
- class Blob < ::ActiveStorage::Blob
4
- if Glib::DynamicText::Config.database_url.present?
5
- connects_to database: { writing: :dynamic_text, reading: :dynamic_text }
6
- end
7
- end
8
- end
9
- end
1
+ module Glib
2
+ module ActiveStorage
3
+ class Blob < ::ActiveStorage::Blob
4
+ if Glib::DynamicText::Config.database_url.present?
5
+ connects_to database: { writing: :dynamic_text, reading: :dynamic_text }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,18 +1,18 @@
1
- module Glib
2
- class ApplicationRecord < ActiveRecord::Base
3
- self.abstract_class = true
4
-
5
- scope :created_asc, -> { order(created_at: :asc) }
6
- scope :created_desc, -> { order(created_at: :desc) }
7
-
8
- def glib_enum_humanize(enum_name, default_value = nil)
9
- self.class.glib_enum_humanize(enum_name, send(enum_name), default_value)
10
- end
11
-
12
- def self.glib_enum_humanize(enum_name, enum_value, default_value = nil)
13
- if enum_value
14
- I18n.t("activerecord.attributes.#{model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{enum_value}", default: default_value)
15
- end
16
- end
17
- end
18
- end
1
+ module Glib
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+
5
+ scope :created_asc, -> { order(created_at: :asc) }
6
+ scope :created_desc, -> { order(created_at: :desc) }
7
+
8
+ def glib_enum_humanize(enum_name, default_value = nil)
9
+ self.class.glib_enum_humanize(enum_name, send(enum_name), default_value)
10
+ end
11
+
12
+ def self.glib_enum_humanize(enum_name, enum_value, default_value = nil)
13
+ if enum_value
14
+ I18n.t("activerecord.attributes.#{model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{enum_value}", default: default_value)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,9 +1,9 @@
1
- module Glib
2
- class DynamicTextRecord < ActiveRecord::Base
3
- self.abstract_class = true
4
-
5
- if Glib::DynamicText::Config.database_url.present?
6
- connects_to database: { writing: :dynamic_text, reading: :dynamic_text }
7
- end
8
- end
9
- end
1
+ module Glib
2
+ class DynamicTextRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+
5
+ if Glib::DynamicText::Config.database_url.present?
6
+ connects_to database: { writing: :dynamic_text, reading: :dynamic_text }
7
+ end
8
+ end
9
+ end
@@ -1,96 +1,96 @@
1
- module Glib
2
- class Text < Glib::DynamicTextRecord
3
- class << self
4
- def dt_has_many_attached(name, dependent: :purge_later)
5
- generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
6
- def #{name}
7
- @active_storage_attached_#{name} ||= ::ActiveStorage::Attached::Many.new("#{name}", self)
8
- end
9
-
10
- def #{name}=(attachables)
11
- if ActiveStorage.replace_on_assign_to_many
12
- attachment_changes["#{name}"] =
13
- if Array(attachables).none?
14
- ::ActiveStorage::Attached::Changes::DeleteMany.new("#{name}", self)
15
- else
16
- ::ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, attachables)
17
- end
18
- else
19
- if Array(attachables).any?
20
- attachment_changes["#{name}"] =
21
- ::ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, #{name}.blobs + attachables)
22
- end
23
- end
24
- end
25
- CODE
26
-
27
- has_many :"#{name}_attachments", -> { where(name: name) }, as: :record, class_name: "Glib::ActiveStorage::Attachment", inverse_of: :record, dependent: :destroy do
28
- def purge
29
- each(&:purge)
30
- reset
31
- end
32
-
33
- def purge_later
34
- each(&:purge_later)
35
- reset
36
- end
37
- end
38
- has_many :"#{name}_blobs", through: :"#{name}_attachments", class_name: "Glib::ActiveStorage::Blob", source: :blob
39
-
40
- scope :"with_attached_#{name}", -> { includes("#{name}_attachments": :blob) }
41
-
42
- after_save { attachment_changes[name.to_s]&.save }
43
-
44
- after_commit(on: %i[ create update ]) { attachment_changes.delete(name.to_s).try(:upload) }
45
-
46
- ActiveRecord::Reflection.add_attachment_reflection(
47
- self,
48
- name,
49
- ActiveRecord::Reflection.create(:has_many_attached, name, nil, { dependent: dependent }, self)
50
- )
51
- end
52
- end
53
-
54
- dt_has_many_attached :images
55
-
56
- validates :scope, presence: true
57
- validates :lang, presence: true
58
- validates :key, presence: true, uniqueness: { scope: [:scope, :lang] }
59
- validates :content, presence: true
60
-
61
- after_save :update_to_redis
62
-
63
- def self.redis
64
- Glib::DynamicText::Config.redis
65
- end
66
-
67
- def self.get_content(key, default_value, options:)
68
- scope_key = "#{options[:scope]}.#{options[:lang]}.#{key}"
69
-
70
- content = redis.get(scope_key)
71
- text = find_by(scope: options[:scope], lang: options[:lang], key: key)
72
-
73
- if !(content && text)
74
- if text = find_by(scope: options[:scope], lang: options[:lang], key: key)
75
- update_content(scope_key, text.content)
76
- content = text.content
77
- else
78
- text = create(scope: options[:scope], lang: options[:lang], key: key, content: default_value)
79
- update_content(scope_key, default_value)
80
- content = default_value
81
- end
82
- end
83
-
84
- [content, text]
85
- end
86
-
87
- private
88
- def self.update_content(scope_key, content)
89
- redis.set(scope_key, content)
90
- end
91
-
92
- def update_to_redis
93
- Glib::Text.update_content("#{scope}.#{lang}.#{key}", content)
94
- end
95
- end
1
+ module Glib
2
+ class Text < Glib::DynamicTextRecord
3
+ class << self
4
+ def dt_has_many_attached(name, dependent: :purge_later)
5
+ generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
6
+ def #{name}
7
+ @active_storage_attached_#{name} ||= ::ActiveStorage::Attached::Many.new("#{name}", self)
8
+ end
9
+
10
+ def #{name}=(attachables)
11
+ if ActiveStorage.replace_on_assign_to_many
12
+ attachment_changes["#{name}"] =
13
+ if Array(attachables).none?
14
+ ::ActiveStorage::Attached::Changes::DeleteMany.new("#{name}", self)
15
+ else
16
+ ::ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, attachables)
17
+ end
18
+ else
19
+ if Array(attachables).any?
20
+ attachment_changes["#{name}"] =
21
+ ::ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, #{name}.blobs + attachables)
22
+ end
23
+ end
24
+ end
25
+ CODE
26
+
27
+ has_many :"#{name}_attachments", -> { where(name: name) }, as: :record, class_name: "Glib::ActiveStorage::Attachment", inverse_of: :record, dependent: :destroy do
28
+ def purge
29
+ each(&:purge)
30
+ reset
31
+ end
32
+
33
+ def purge_later
34
+ each(&:purge_later)
35
+ reset
36
+ end
37
+ end
38
+ has_many :"#{name}_blobs", through: :"#{name}_attachments", class_name: "Glib::ActiveStorage::Blob", source: :blob
39
+
40
+ scope :"with_attached_#{name}", -> { includes("#{name}_attachments": :blob) }
41
+
42
+ after_save { attachment_changes[name.to_s]&.save }
43
+
44
+ after_commit(on: %i[ create update ]) { attachment_changes.delete(name.to_s).try(:upload) }
45
+
46
+ ActiveRecord::Reflection.add_attachment_reflection(
47
+ self,
48
+ name,
49
+ ActiveRecord::Reflection.create(:has_many_attached, name, nil, { dependent: dependent }, self)
50
+ )
51
+ end
52
+ end
53
+
54
+ dt_has_many_attached :images
55
+
56
+ validates :scope, presence: true
57
+ validates :lang, presence: true
58
+ validates :key, presence: true, uniqueness: { scope: [:scope, :lang] }
59
+ validates :content, presence: true
60
+
61
+ after_save :update_to_redis
62
+
63
+ def self.redis
64
+ Glib::DynamicText::Config.redis
65
+ end
66
+
67
+ def self.get_content(key, default_value, options:)
68
+ scope_key = "#{options[:scope]}.#{options[:lang]}.#{key}"
69
+
70
+ content = redis.get(scope_key)
71
+ text = find_by(scope: options[:scope], lang: options[:lang], key: key)
72
+
73
+ if !(content && text)
74
+ if text = find_by(scope: options[:scope], lang: options[:lang], key: key)
75
+ update_content(scope_key, text.content)
76
+ content = text.content
77
+ else
78
+ text = create(scope: options[:scope], lang: options[:lang], key: key, content: default_value)
79
+ update_content(scope_key, default_value)
80
+ content = default_value
81
+ end
82
+ end
83
+
84
+ [content, text]
85
+ end
86
+
87
+ private
88
+ def self.update_content(scope_key, content)
89
+ redis.set(scope_key, content)
90
+ end
91
+
92
+ def update_to_redis
93
+ Glib::Text.update_content("#{scope}.#{lang}.#{key}", content)
94
+ end
95
+ end
96
96
  end
@@ -1,191 +1,191 @@
1
- # The main purpose of this is for security. If it is important to display useful error message or to provide a "banana", then
2
- # it's better to perform an explicit check (e.g. as a validation in the model or using a before_action).
3
- module Glib
4
- class ApplicationPolicy
5
- attr_reader :user, :record, :policy_name, :controller, :request, :params
6
- class_attribute :should_exist_attributes, instance_writer: false, default: []
7
-
8
- private
9
- def initialize(user, record, policy_name, controller, request, params, attributes: {})
10
- @user = user
11
- @record = record
12
- @controller = controller
13
- @request = request
14
- # Don't get params from request because we might not have a proper request object. This might execute in Sidekiq.
15
- # See Presenter::Model::inside_mock_controller()
16
- @params = params
17
- @policy_name = policy_name
18
-
19
- if attributes.present? && controller.action_name != 'index'
20
- self.class.module_eval { attr_accessor(*attributes.keys) }
21
- attributes.each do |key, value|
22
- send("#{key}=", value)
23
- end
24
- end
25
-
26
- if controller.user_signed_in?
27
- should_exist_attributes.each do |attribute|
28
- if try(attribute).blank? && !['index'].include?(controller.action_name)
29
- raise "Attribute #{attribute} is blank, policy will not working properly"
30
- end
31
- end
32
- end
33
- end
34
-
35
- class << self
36
- attr_reader :catch_all
37
-
38
- def inherited(base)
39
- base.should_exist_attributes = should_exist_attributes.dup
40
- super
41
- end
42
-
43
- # This is to define the authorization logic for an action (or a group of actions). It's different from controller's
44
- # authorize().
45
- private # Used by child
46
- def authorize(*actions, &block)
47
- actions.each do |action|
48
- if action == :glib_all
49
- # Serve as a catch-all to all actions that have not been specified in the policy.
50
- @catch_all = block
51
- else
52
- method_name = "#{action}?"
53
- # Avoid accidentally redefining multiple times from child policies. But it's okay if the child policy
54
- # wants to override the parent's authorization method.
55
- raise "Action authorization has been declared: #{action}" if instance_methods(false).include?(method_name.to_sym)
56
- define_method method_name, &block
57
- end
58
- end
59
- end
60
-
61
- def should_exist(*attributes)
62
- should_exist_attributes.push(*attributes)
63
- end
64
- end
65
-
66
- private
67
- def catch_all
68
- self.class.catch_all
69
- end
70
-
71
- private
72
- # To ensure the block is called on the policy's instance instead class.
73
- def call_catch_all
74
- instance_eval(&catch_all)
75
- end
76
-
77
- authorize :index do
78
- # We need this line because in `index` action, this method will be called instead of method_missing().
79
- # Having this line ensures that the catch_all behaviour works according to the priority below:
80
- # - child_policy#index?
81
- # - child_policy#manage? -- catch_all
82
- # - application_policy@index?
83
- return call_catch_all if catch_all
84
-
85
- false
86
- end
87
-
88
- authorize :show do
89
- return call_catch_all if catch_all
90
-
91
- scope.where(id: record.id).exists?
92
- end
93
-
94
- authorize :create do
95
- return call_catch_all if catch_all
96
-
97
- false
98
- end
99
-
100
- authorize :new do
101
- return call_catch_all if catch_all
102
-
103
- create?
104
- end
105
-
106
- authorize :update do
107
- return call_catch_all if catch_all
108
-
109
- false
110
- end
111
-
112
- authorize :edit do
113
- return call_catch_all if catch_all
114
-
115
- update?
116
- end
117
-
118
- authorize :destroy do
119
- return call_catch_all if catch_all
120
-
121
- false
122
- end
123
-
124
- public
125
- def method_missing(name, *args, &block)
126
- if name.to_s.end_with?('?') && catch_all
127
- call_catch_all
128
- else
129
- super
130
- end
131
- end
132
-
133
- public
134
- def scope
135
- policy_scope_class = Pundit::PolicyFinder.new(@policy_name).scope
136
- return unless policy_scope_class
137
-
138
- controller.policy_scope(record.class, policy_scope_class: policy_scope_class)
139
- end
140
-
141
- public
142
- def self.args_builder
143
- Proc.new { |controller| [] }
144
- end
145
-
146
- public
147
- def helpers
148
- controller.helpers
149
- end
150
-
151
- # TODO: Remove. Deprecated
152
- # private # Used by child
153
- # def public?
154
- # true
155
- # end
156
-
157
- class Scope
158
- attr_reader :user, :scope
159
-
160
- def initialize(user, scope)
161
- @user = user
162
- @scope = scope
163
- end
164
-
165
- # def current_user
166
- # user
167
- # end
168
-
169
- # To be overridden
170
- def resolve
171
- scope.none
172
- end
173
- end
174
-
175
- private # Used by child
176
- def everyone
177
- true
178
- end
179
-
180
- # def current_user
181
- # user
182
- # end
183
-
184
- # TODO: Bad pattern. Implement explicit policy parameter instead.
185
- # - E.g. can? :destroy, :service_subscription_auto_renewal, { service_subscription: @service_subscription }
186
- # - E.g. super class: :service_subscription_auto_renewal, { service_subscription: @service_subscription }
187
- def controller_var(name)
188
- controller.instance_variable_get(:"@#{name}")
189
- end
190
- end
191
- end
1
+ # The main purpose of this is for security. If it is important to display useful error message or to provide a "banana", then
2
+ # it's better to perform an explicit check (e.g. as a validation in the model or using a before_action).
3
+ module Glib
4
+ class ApplicationPolicy
5
+ attr_reader :user, :record, :policy_name, :controller, :request, :params
6
+ class_attribute :should_exist_attributes, instance_writer: false, default: []
7
+
8
+ private
9
+ def initialize(user, record, policy_name, controller, request, params, attributes: {})
10
+ @user = user
11
+ @record = record
12
+ @controller = controller
13
+ @request = request
14
+ # Don't get params from request because we might not have a proper request object. This might execute in Sidekiq.
15
+ # See Presenter::Model::inside_mock_controller()
16
+ @params = params
17
+ @policy_name = policy_name
18
+
19
+ if attributes.present? && controller.action_name != 'index'
20
+ self.class.module_eval { attr_accessor(*attributes.keys) }
21
+ attributes.each do |key, value|
22
+ send("#{key}=", value)
23
+ end
24
+ end
25
+
26
+ if controller.user_signed_in?
27
+ should_exist_attributes.each do |attribute|
28
+ if try(attribute).blank? && !['index'].include?(controller.action_name)
29
+ raise "Attribute #{attribute} is blank, policy will not working properly"
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ class << self
36
+ attr_reader :catch_all
37
+
38
+ def inherited(base)
39
+ base.should_exist_attributes = should_exist_attributes.dup
40
+ super
41
+ end
42
+
43
+ # This is to define the authorization logic for an action (or a group of actions). It's different from controller's
44
+ # authorize().
45
+ private # Used by child
46
+ def authorize(*actions, &block)
47
+ actions.each do |action|
48
+ if action == :glib_all
49
+ # Serve as a catch-all to all actions that have not been specified in the policy.
50
+ @catch_all = block
51
+ else
52
+ method_name = "#{action}?"
53
+ # Avoid accidentally redefining multiple times from child policies. But it's okay if the child policy
54
+ # wants to override the parent's authorization method.
55
+ raise "Action authorization has been declared: #{action}" if instance_methods(false).include?(method_name.to_sym)
56
+ define_method method_name, &block
57
+ end
58
+ end
59
+ end
60
+
61
+ def should_exist(*attributes)
62
+ should_exist_attributes.push(*attributes)
63
+ end
64
+ end
65
+
66
+ private
67
+ def catch_all
68
+ self.class.catch_all
69
+ end
70
+
71
+ private
72
+ # To ensure the block is called on the policy's instance instead class.
73
+ def call_catch_all
74
+ instance_eval(&catch_all)
75
+ end
76
+
77
+ authorize :index do
78
+ # We need this line because in `index` action, this method will be called instead of method_missing().
79
+ # Having this line ensures that the catch_all behaviour works according to the priority below:
80
+ # - child_policy#index?
81
+ # - child_policy#manage? -- catch_all
82
+ # - application_policy@index?
83
+ return call_catch_all if catch_all
84
+
85
+ false
86
+ end
87
+
88
+ authorize :show do
89
+ return call_catch_all if catch_all
90
+
91
+ scope.where(id: record.id).exists?
92
+ end
93
+
94
+ authorize :create do
95
+ return call_catch_all if catch_all
96
+
97
+ false
98
+ end
99
+
100
+ authorize :new do
101
+ return call_catch_all if catch_all
102
+
103
+ create?
104
+ end
105
+
106
+ authorize :update do
107
+ return call_catch_all if catch_all
108
+
109
+ false
110
+ end
111
+
112
+ authorize :edit do
113
+ return call_catch_all if catch_all
114
+
115
+ update?
116
+ end
117
+
118
+ authorize :destroy do
119
+ return call_catch_all if catch_all
120
+
121
+ false
122
+ end
123
+
124
+ public
125
+ def method_missing(name, *args, &block)
126
+ if name.to_s.end_with?('?') && catch_all
127
+ call_catch_all
128
+ else
129
+ super
130
+ end
131
+ end
132
+
133
+ public
134
+ def scope
135
+ policy_scope_class = Pundit::PolicyFinder.new(@policy_name).scope
136
+ return unless policy_scope_class
137
+
138
+ controller.policy_scope(record.class, policy_scope_class: policy_scope_class)
139
+ end
140
+
141
+ public
142
+ def self.args_builder
143
+ Proc.new { |controller| [] }
144
+ end
145
+
146
+ public
147
+ def helpers
148
+ controller.helpers
149
+ end
150
+
151
+ # TODO: Remove. Deprecated
152
+ # private # Used by child
153
+ # def public?
154
+ # true
155
+ # end
156
+
157
+ class Scope
158
+ attr_reader :user, :scope
159
+
160
+ def initialize(user, scope)
161
+ @user = user
162
+ @scope = scope
163
+ end
164
+
165
+ # def current_user
166
+ # user
167
+ # end
168
+
169
+ # To be overridden
170
+ def resolve
171
+ scope.none
172
+ end
173
+ end
174
+
175
+ private # Used by child
176
+ def everyone
177
+ true
178
+ end
179
+
180
+ # def current_user
181
+ # user
182
+ # end
183
+
184
+ # TODO: Bad pattern. Implement explicit policy parameter instead.
185
+ # - E.g. can? :destroy, :service_subscription_auto_renewal, { service_subscription: @service_subscription }
186
+ # - E.g. super class: :service_subscription_auto_renewal, { service_subscription: @service_subscription }
187
+ def controller_var(name)
188
+ controller.instance_variable_get(:"@#{name}")
189
+ end
190
+ end
191
+ end