activity_notification 2.0.0 → 2.1.4

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 (202) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +22 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
  4. data/.github/pull_request_template.md +13 -0
  5. data/.gitignore +10 -3
  6. data/.travis.yml +6 -5
  7. data/CHANGELOG.md +60 -0
  8. data/Gemfile +8 -3
  9. data/Procfile +1 -1
  10. data/README.md +153 -1510
  11. data/activity_notification.gemspec +4 -1
  12. data/app/channels/activity_notification/notification_api_channel.rb +12 -0
  13. data/app/channels/activity_notification/notification_api_with_devise_channel.rb +46 -0
  14. data/app/channels/activity_notification/notification_channel.rb +2 -2
  15. data/app/channels/activity_notification/notification_with_devise_channel.rb +2 -2
  16. data/app/controllers/activity_notification/apidocs_controller.rb +75 -0
  17. data/app/controllers/activity_notification/notifications_api_controller.rb +143 -0
  18. data/app/controllers/activity_notification/notifications_api_with_devise_controller.rb +7 -0
  19. data/app/controllers/activity_notification/notifications_controller.rb +79 -53
  20. data/app/controllers/activity_notification/subscriptions_api_controller.rb +197 -0
  21. data/app/controllers/activity_notification/subscriptions_api_with_devise_controller.rb +7 -0
  22. data/app/controllers/activity_notification/subscriptions_controller.rb +78 -69
  23. data/app/views/activity_notification/notifications/default/_default.html.erb +18 -18
  24. data/app/views/activity_notification/notifications/default/_default_without_grouping.html.erb +14 -14
  25. data/app/views/activity_notification/notifications/default/index.html.erb +6 -6
  26. data/app/views/activity_notification/optional_targets/default/action_cable_channel/_default.html.erb +176 -0
  27. data/app/views/activity_notification/subscriptions/default/_form.html.erb +1 -1
  28. data/app/views/activity_notification/subscriptions/default/_notification_keys.html.erb +3 -31
  29. data/app/views/activity_notification/subscriptions/default/_subscription.html.erb +7 -7
  30. data/app/views/activity_notification/subscriptions/default/index.html.erb +11 -7
  31. data/bin/deploy_on_heroku.sh +3 -1
  32. data/docs/CODE_OF_CONDUCT.md +76 -0
  33. data/docs/CONTRIBUTING.md +36 -0
  34. data/docs/Functions.md +1130 -0
  35. data/docs/Setup.md +801 -0
  36. data/docs/Testing.md +148 -0
  37. data/gemfiles/Gemfile.rails-4.2 +5 -1
  38. data/gemfiles/Gemfile.rails-5.0 +6 -1
  39. data/gemfiles/Gemfile.rails-5.1 +6 -1
  40. data/gemfiles/Gemfile.rails-5.2 +6 -1
  41. data/gemfiles/{Gemfile.rails-6.0.rc → Gemfile.rails-6.0} +6 -5
  42. data/lib/activity_notification.rb +13 -0
  43. data/lib/activity_notification/apis/notification_api.rb +37 -93
  44. data/lib/activity_notification/apis/subscription_api.rb +20 -8
  45. data/lib/activity_notification/apis/swagger.rb +6 -0
  46. data/lib/activity_notification/common.rb +4 -1
  47. data/lib/activity_notification/config.rb +41 -21
  48. data/lib/activity_notification/controllers/common_api_controller.rb +30 -0
  49. data/lib/activity_notification/controllers/common_controller.rb +45 -21
  50. data/lib/activity_notification/controllers/concerns/swagger/error_responses.rb +55 -0
  51. data/lib/activity_notification/controllers/concerns/swagger/notifications_api.rb +273 -0
  52. data/lib/activity_notification/controllers/concerns/swagger/notifications_parameters.rb +92 -0
  53. data/lib/activity_notification/controllers/concerns/swagger/subscriptions_api.rb +405 -0
  54. data/lib/activity_notification/controllers/concerns/swagger/subscriptions_parameters.rb +50 -0
  55. data/lib/activity_notification/controllers/devise_authentication_controller.rb +7 -6
  56. data/lib/activity_notification/gem_version.rb +14 -0
  57. data/lib/activity_notification/helpers/errors.rb +2 -0
  58. data/lib/activity_notification/helpers/view_helpers.rb +4 -0
  59. data/lib/activity_notification/mailers/helpers.rb +17 -10
  60. data/lib/activity_notification/models/concerns/notifiable.rb +31 -15
  61. data/lib/activity_notification/models/concerns/subscriber.rb +12 -1
  62. data/lib/activity_notification/models/concerns/swagger/error_schema.rb +36 -0
  63. data/lib/activity_notification/models/concerns/swagger/notification_schema.rb +209 -0
  64. data/lib/activity_notification/models/concerns/swagger/subscription_schema.rb +162 -0
  65. data/lib/activity_notification/models/concerns/target.rb +36 -10
  66. data/lib/activity_notification/models/notification.rb +1 -0
  67. data/lib/activity_notification/models/subscription.rb +1 -0
  68. data/lib/activity_notification/optional_targets/action_cable_api_channel.rb +69 -0
  69. data/lib/activity_notification/optional_targets/action_cable_channel.rb +68 -0
  70. data/lib/activity_notification/optional_targets/base.rb +7 -13
  71. data/lib/activity_notification/orm/active_record/notification.rb +17 -1
  72. data/lib/activity_notification/orm/active_record/subscription.rb +1 -1
  73. data/lib/activity_notification/orm/dynamoid.rb +38 -3
  74. data/lib/activity_notification/orm/dynamoid/extension.rb +79 -1
  75. data/lib/activity_notification/orm/dynamoid/notification.rb +49 -14
  76. data/lib/activity_notification/orm/dynamoid/subscription.rb +2 -2
  77. data/lib/activity_notification/orm/mongoid.rb +32 -3
  78. data/lib/activity_notification/orm/mongoid/notification.rb +24 -6
  79. data/lib/activity_notification/orm/mongoid/subscription.rb +1 -1
  80. data/lib/activity_notification/rails/routes.rb +132 -48
  81. data/lib/activity_notification/renderable.rb +13 -2
  82. data/lib/activity_notification/roles/acts_as_notifiable.rb +39 -20
  83. data/lib/activity_notification/version.rb +1 -1
  84. data/lib/generators/activity_notification/controllers_generator.rb +2 -1
  85. data/lib/generators/templates/activity_notification.rb +8 -0
  86. data/lib/generators/templates/controllers/notifications_api_controller.rb +31 -0
  87. data/lib/generators/templates/controllers/notifications_api_with_devise_controller.rb +31 -0
  88. data/lib/generators/templates/controllers/notifications_controller.rb +1 -37
  89. data/lib/generators/templates/controllers/notifications_with_devise_controller.rb +1 -45
  90. data/lib/generators/templates/controllers/subscriptions_api_controller.rb +61 -0
  91. data/lib/generators/templates/controllers/subscriptions_api_with_devise_controller.rb +61 -0
  92. data/lib/generators/templates/controllers/subscriptions_controller.rb +14 -37
  93. data/lib/generators/templates/controllers/subscriptions_with_devise_controller.rb +14 -45
  94. data/lib/generators/templates/models/README +8 -4
  95. data/lib/generators/templates/models/notification.rb +1 -1
  96. data/lib/generators/templates/models/subscription.rb +1 -1
  97. data/package.json +8 -0
  98. data/spec/channels/notification_api_channel_shared_examples.rb +59 -0
  99. data/spec/channels/notification_api_channel_spec.rb +51 -0
  100. data/spec/channels/notification_api_with_devise_channel_spec.rb +78 -0
  101. data/spec/concerns/apis/notification_api_spec.rb +38 -3
  102. data/spec/concerns/models/notifiable_spec.rb +82 -18
  103. data/spec/concerns/models/subscriber_spec.rb +13 -16
  104. data/spec/concerns/models/target_spec.rb +32 -0
  105. data/spec/concerns/renderable_spec.rb +2 -2
  106. data/spec/config_spec.rb +26 -15
  107. data/spec/controllers/controller_spec_utility.rb +136 -0
  108. data/spec/controllers/notifications_api_controller_shared_examples.rb +506 -0
  109. data/spec/controllers/notifications_api_controller_spec.rb +19 -0
  110. data/spec/controllers/notifications_api_with_devise_controller_spec.rb +60 -0
  111. data/spec/controllers/notifications_controller_shared_examples.rb +54 -79
  112. data/spec/controllers/notifications_controller_spec.rb +1 -2
  113. data/spec/controllers/notifications_with_devise_controller_spec.rb +3 -12
  114. data/spec/controllers/subscriptions_api_controller_shared_examples.rb +750 -0
  115. data/spec/controllers/subscriptions_api_controller_spec.rb +19 -0
  116. data/spec/controllers/subscriptions_api_with_devise_controller_spec.rb +60 -0
  117. data/spec/controllers/subscriptions_controller_shared_examples.rb +94 -121
  118. data/spec/controllers/subscriptions_controller_spec.rb +1 -2
  119. data/spec/controllers/subscriptions_with_devise_controller_spec.rb +3 -12
  120. data/spec/helpers/view_helpers_spec.rb +4 -11
  121. data/spec/mailers/mailer_spec.rb +41 -0
  122. data/spec/models/notification_spec.rb +17 -0
  123. data/spec/models/subscription_spec.rb +8 -13
  124. data/spec/optional_targets/action_cable_api_channel_spec.rb +37 -0
  125. data/spec/optional_targets/action_cable_channel_spec.rb +44 -0
  126. data/spec/optional_targets/amazon_sns_spec.rb +0 -2
  127. data/spec/optional_targets/slack_spec.rb +0 -2
  128. data/spec/rails_app/Rakefile +9 -0
  129. data/spec/rails_app/app/assets/config/manifest.js +3 -0
  130. data/spec/rails_app/app/assets/images/.keep +0 -0
  131. data/spec/rails_app/app/controllers/admins_controller.rb +21 -0
  132. data/spec/rails_app/app/controllers/application_controller.rb +1 -1
  133. data/spec/rails_app/app/controllers/articles_controller.rb +6 -3
  134. data/spec/rails_app/app/controllers/spa_controller.rb +7 -0
  135. data/spec/rails_app/app/controllers/users/notifications_controller.rb +0 -65
  136. data/spec/rails_app/app/controllers/users/notifications_with_devise_controller.rb +0 -73
  137. data/spec/rails_app/app/controllers/users/subscriptions_controller.rb +0 -77
  138. data/spec/rails_app/app/controllers/users/subscriptions_with_devise_controller.rb +0 -85
  139. data/spec/rails_app/app/controllers/users_controller.rb +26 -0
  140. data/spec/rails_app/app/javascript/App.vue +40 -0
  141. data/spec/rails_app/app/javascript/components/DeviseTokenAuth.vue +82 -0
  142. data/spec/rails_app/app/javascript/components/Top.vue +98 -0
  143. data/spec/rails_app/app/javascript/components/notifications/Index.vue +200 -0
  144. data/spec/rails_app/app/javascript/components/notifications/Notification.vue +133 -0
  145. data/spec/rails_app/app/javascript/components/notifications/NotificationContent.vue +122 -0
  146. data/spec/rails_app/app/javascript/components/subscriptions/Index.vue +279 -0
  147. data/spec/rails_app/app/javascript/components/subscriptions/NewSubscription.vue +112 -0
  148. data/spec/rails_app/app/javascript/components/subscriptions/NotificationKey.vue +141 -0
  149. data/spec/rails_app/app/javascript/components/subscriptions/Subscription.vue +226 -0
  150. data/spec/rails_app/app/javascript/config/development.js +5 -0
  151. data/spec/rails_app/app/javascript/config/environment.js +7 -0
  152. data/spec/rails_app/app/javascript/config/production.js +5 -0
  153. data/spec/rails_app/app/javascript/config/test.js +5 -0
  154. data/spec/rails_app/app/javascript/packs/application.js +18 -0
  155. data/spec/rails_app/app/javascript/packs/spa.js +14 -0
  156. data/spec/rails_app/app/javascript/router/index.js +73 -0
  157. data/spec/rails_app/app/javascript/store/index.js +37 -0
  158. data/spec/rails_app/app/models/admin.rb +16 -15
  159. data/spec/rails_app/app/models/article.rb +26 -21
  160. data/spec/rails_app/app/models/comment.rb +24 -71
  161. data/spec/rails_app/app/models/dummy/dummy_group.rb +8 -0
  162. data/spec/rails_app/app/models/dummy/dummy_notifiable_target.rb +8 -0
  163. data/spec/rails_app/app/models/user.rb +44 -20
  164. data/spec/rails_app/app/views/activity_notification/notifications/default/article/_update.html.erb +146 -0
  165. data/spec/rails_app/app/views/articles/index.html.erb +51 -7
  166. data/spec/rails_app/app/views/articles/show.html.erb +1 -1
  167. data/spec/rails_app/app/views/layouts/_header.html.erb +8 -10
  168. data/spec/rails_app/app/views/spa/index.html.erb +2 -0
  169. data/spec/rails_app/babel.config.js +72 -0
  170. data/spec/rails_app/bin/webpack +18 -0
  171. data/spec/rails_app/bin/webpack-dev-server +18 -0
  172. data/spec/rails_app/config/application.rb +18 -2
  173. data/spec/rails_app/config/dynamoid.rb +11 -3
  174. data/spec/rails_app/config/environment.rb +2 -1
  175. data/spec/rails_app/config/environments/development.rb +5 -0
  176. data/spec/rails_app/config/environments/production.rb +6 -0
  177. data/spec/rails_app/config/environments/test.rb +5 -0
  178. data/spec/rails_app/config/initializers/activity_notification.rb +11 -3
  179. data/spec/rails_app/config/initializers/copy_it.aws.rb.template +6 -0
  180. data/spec/rails_app/config/initializers/devise_token_auth.rb +55 -0
  181. data/spec/rails_app/config/initializers/mysql.rb +9 -0
  182. data/spec/rails_app/config/locales/activity_notification.en.yml +2 -2
  183. data/spec/rails_app/config/routes.rb +37 -1
  184. data/spec/rails_app/config/webpack/development.js +5 -0
  185. data/spec/rails_app/config/webpack/environment.js +7 -0
  186. data/spec/rails_app/config/webpack/loaders/vue.js +6 -0
  187. data/spec/rails_app/config/webpack/production.js +5 -0
  188. data/spec/rails_app/config/webpack/test.js +5 -0
  189. data/spec/rails_app/config/webpacker.yml +97 -0
  190. data/spec/rails_app/db/migrate/20191201000000_add_tokens_to_users.rb +10 -0
  191. data/spec/rails_app/db/schema.rb +4 -1
  192. data/spec/rails_app/db/seeds.rb +10 -2
  193. data/spec/rails_app/lib/custom_optional_targets/raise_error.rb +14 -0
  194. data/spec/rails_app/package.json +23 -0
  195. data/spec/rails_app/postcss.config.js +12 -0
  196. data/spec/roles/acts_as_group_spec.rb +0 -2
  197. data/spec/roles/acts_as_notifiable_spec.rb +6 -8
  198. data/spec/roles/acts_as_notifier_spec.rb +0 -2
  199. data/spec/roles/acts_as_target_spec.rb +0 -4
  200. data/spec/spec_helper.rb +7 -15
  201. data/spec/version_spec.rb +31 -0
  202. metadata +191 -13
@@ -4,10 +4,7 @@ module ActivityNotification
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
- # :only-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
8
- # :only-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
9
- # :except-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
10
- # :except-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
7
+ # :nocov:
11
8
  unless ActivityNotification.config.orm == :dynamoid
12
9
  # Selects filtered subscriptions by key.
13
10
  # @example Get filtered subscriptions of the @user with key 'comment.reply'
@@ -77,10 +74,7 @@ module ActivityNotification
77
74
  time
78
75
  end
79
76
  end
80
- # :only-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
81
- # :only-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
82
- # :except-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
83
- # :except-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
77
+ # :nocov:
84
78
  end
85
79
 
86
80
  class_methods do
@@ -106,6 +100,24 @@ module ActivityNotification
106
100
  end
107
101
  end
108
102
 
103
+ # Override as_json method for optional_targets representation
104
+ #
105
+ # @param [Hash] options Options for as_json method
106
+ # @return [Hash] Hash representing the subscription model
107
+ def as_json(options = {})
108
+ json = super(options).with_indifferent_access
109
+ optional_targets_json = {}
110
+ optional_target_names.each do |optional_target_name|
111
+ optional_targets_json[optional_target_name] = {
112
+ subscribing: json[:optional_targets][Subscription.to_optional_target_key(optional_target_name)],
113
+ subscribed_at: json[:optional_targets][Subscription.to_optional_target_subscribed_at_key(optional_target_name)],
114
+ unsubscribed_at: json[:optional_targets][Subscription.to_optional_target_unsubscribed_at_key(optional_target_name)]
115
+ }
116
+ end
117
+ json[:optional_targets] = optional_targets_json
118
+ json
119
+ end
120
+
109
121
  # Subscribes to the notification and notification email.
110
122
  #
111
123
  # @param [Hash] options Options for subscribing to the notification
@@ -0,0 +1,6 @@
1
+ require 'swagger/blocks'
2
+
3
+ module ActivityNotification #:nodoc:
4
+ module Swagger #:nodoc:
5
+ end
6
+ end
@@ -98,9 +98,12 @@ module ActivityNotification
98
98
  end
99
99
 
100
100
  # Convets to class name.
101
+ # This function returns base_class name for STI models if the class responds to base_class method.
102
+ # @see https://github.com/simukappu/activity_notification/issues/89
103
+ # @see https://github.com/simukappu/activity_notification/pull/139
101
104
  # @return [String] Class name
102
105
  def to_class_name
103
- self.class.name
106
+ self.class.respond_to?(:base_class) ? self.class.base_class.name : self.class.name
104
107
  end
105
108
 
106
109
  # Convets to singularized model name (resource name).
@@ -165,6 +165,15 @@ module ActivityNotification
165
165
  # @return [Boolean] Whether WebSocket subscription using ActionCable is enabled.
166
166
  attr_accessor :action_cable_enabled
167
167
 
168
+ # @overload action_cable_api_enabled
169
+ # Returns whether WebSocket API subscription using ActionCable is enabled
170
+ # @return [Boolean] Whether WebSocket API subscription using ActionCable is enabled.
171
+ # @overload action_cable_api_enabled=(value)
172
+ # Sets whether WebSocket API subscription using ActionCable is enabled
173
+ # @param [Boolean] action_cable_enabled The new action_cable_api_enabled
174
+ # @return [Boolean] Whether WebSocket API subscription using ActionCable is enabled.
175
+ attr_accessor :action_cable_api_enabled
176
+
168
177
  # @overload action_cable_with_devise
169
178
  # Returns whether activity_notification publishes WebSocket notifications using ActionCable only to authenticated target with Devise
170
179
  # @return [Boolean] Whether activity_notification publishes WebSocket notifications using ActionCable only to authenticated target with Devise.
@@ -183,31 +192,42 @@ module ActivityNotification
183
192
  # @return [String] Notification channel prefix for ActionCable.
184
193
  attr_accessor :notification_channel_prefix
185
194
 
195
+ # @overload notification_api_channel_prefix
196
+ # Returns notification API channel prefix for ActionCable
197
+ # @return [String] Notification API channel prefix for ActionCable.
198
+ # @overload notification_api_channel_prefix=(value)
199
+ # Sets notification API channel prefix for ActionCable
200
+ # @param [String] notification_api_channel_prefix The new notification_api_channel_prefix
201
+ # @return [String] Notification API channel prefix for ActionCable.
202
+ attr_accessor :notification_api_channel_prefix
203
+
186
204
  # Initialize configuration for ActivityNotification.
187
205
  # These configuration can be overridden in initializer.
188
206
  # @return [Config] A new instance of Config
189
207
  def initialize
190
- @enabled = true
191
- @orm = :active_record
192
- @notification_table_name = 'notifications'
193
- @subscription_table_name = 'subscriptions'
194
- @email_enabled = false
195
- @subscription_enabled = false
196
- @subscribe_as_default = true
197
- @mailer_sender = nil
198
- @mailer = 'ActivityNotification::Mailer'
199
- @parent_mailer = 'ActionMailer::Base'
200
- @parent_job = 'ActiveJob::Base'
201
- @parent_controller = 'ApplicationController'
202
- @parent_channel = 'ActionCable::Channel::Base'
203
- @mailer_templates_dir = 'activity_notification/mailer'
204
- @opened_index_limit = 10
205
- @active_job_queue = :activity_notification
206
- @composite_key_delimiter = '#'
207
- @store_with_associated_records = false
208
- @action_cable_enabled = false
209
- @action_cable_with_devise = false
210
- @notification_channel_prefix = 'activity_notification_channel'
208
+ @enabled = true
209
+ @orm = :active_record
210
+ @notification_table_name = 'notifications'
211
+ @subscription_table_name = 'subscriptions'
212
+ @email_enabled = false
213
+ @subscription_enabled = false
214
+ @subscribe_as_default = true
215
+ @mailer_sender = nil
216
+ @mailer = 'ActivityNotification::Mailer'
217
+ @parent_mailer = 'ActionMailer::Base'
218
+ @parent_job = 'ActiveJob::Base'
219
+ @parent_controller = 'ApplicationController'
220
+ @parent_channel = 'ActionCable::Channel::Base'
221
+ @mailer_templates_dir = 'activity_notification/mailer'
222
+ @opened_index_limit = 10
223
+ @active_job_queue = :activity_notification
224
+ @composite_key_delimiter = '#'
225
+ @store_with_associated_records = false
226
+ @action_cable_enabled = false
227
+ @action_cable_api_enabled = false
228
+ @action_cable_with_devise = false
229
+ @notification_channel_prefix = 'activity_notification_channel'
230
+ @notification_api_channel_prefix = 'activity_notification_api_channel'
211
231
  end
212
232
 
213
233
  # Sets ORM name for ActivityNotification (:active_record, :mongoid or :dynamodb)
@@ -0,0 +1,30 @@
1
+ module ActivityNotification
2
+ # Module included in api controllers to select target
3
+ module CommonApiController
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ rescue_from ActiveRecord::RecordNotFound, with: :render_resource_not_found if defined?(ActiveRecord)
8
+ rescue_from Mongoid::Errors::DocumentNotFound, with: :render_resource_not_found if ActivityNotification.config.orm == :mongoid
9
+ rescue_from Dynamoid::Errors::RecordNotFound, with: :render_resource_not_found if ActivityNotification.config.orm == :dynamoid
10
+ end
11
+
12
+ protected
13
+
14
+ # Override to do nothing instead of JavaScript view for ajax request or redirects to back.
15
+ # @api protected
16
+ def return_back_or_ajax
17
+ end
18
+
19
+ # Override to do nothing instead of redirecting to notifiable_path
20
+ # @api protected
21
+ def redirect_to_notifiable_path
22
+ end
23
+
24
+ # Override to do nothing instead of redirecting to subscription path
25
+ # @api protected
26
+ def redirect_to_subscription_path
27
+ end
28
+
29
+ end
30
+ end
@@ -11,6 +11,7 @@ module ActivityNotification
11
11
 
12
12
  prepend_before_action :set_target
13
13
  before_action :set_view_prefixes
14
+ rescue_from ActivityNotification::RecordInvalidError, with: ->(e){ render_unprocessable_entity(e.message) }
14
15
  end
15
16
 
16
17
  DEFAULT_VIEW_DIRECTORY = "default"
@@ -19,15 +20,15 @@ module ActivityNotification
19
20
 
20
21
  # Sets @target instance variable from request parameters.
21
22
  # @api protected
22
- # @return [Object] Target instance (Returns HTTP 400 when request parameters are not enough)
23
+ # @return [Object] Target instance (Returns HTTP 400 when request parameters are invalid)
23
24
  def set_target
24
25
  if (target_type = params[:target_type]).present?
25
26
  target_class = target_type.to_model_class
26
27
  @target = params[:target_id].present? ?
27
28
  target_class.find_by!(id: params[:target_id]) :
28
- target_class.find_by!(id: params["#{target_type.to_resource_name}_id"])
29
+ target_class.find_by!(id: params["#{target_type.to_resource_name[/([^\/]+)$/]}_id"])
29
30
  else
30
- render plain: "400 Bad Request: Missing parameter", status: 400
31
+ render status: 400, json: error_response(code: 400, message: "Invalid parameter", type: "Parameter is missing or the value is empty: target_type")
31
32
  end
32
33
  end
33
34
 
@@ -37,7 +38,7 @@ module ActivityNotification
37
38
  # @return Nil or render HTTP 403 status
38
39
  def validate_target(belonging_model)
39
40
  if @target.present? && belonging_model.target != @target
40
- render plain: "403 Forbidden: Wrong target", status: 403
41
+ render status: 403, json: error_response(code: 403, message: "Forbidden because of invalid parameter", type: "Wrong target is specified")
41
42
  end
42
43
  end
43
44
 
@@ -82,9 +83,46 @@ module ActivityNotification
82
83
  lookup_context.prefixes.prepend(target_view_path)
83
84
  end
84
85
 
86
+ # Returns error response as Hash
87
+ # @api protected
88
+ # @return [Hash] Error message
89
+ def error_response(error_info = {})
90
+ { gem: "activity_notification", error: error_info }
91
+ end
92
+
93
+ # Render Resource Not Found error with 404 status
94
+ # @api protected
95
+ # @return [void]
96
+ def render_resource_not_found(error = nil)
97
+ message_type = error.respond_to?(:message) ? error.message : error
98
+ render status: 404, json: error_response(code: 404, message: "Resource not found", type: message_type)
99
+ end
100
+
101
+ # Render Invalid Parameter error with 400 status
102
+ # @api protected
103
+ # @return [void]
104
+ def render_invalid_parameter(message)
105
+ render status: 400, json: error_response(code: 400, message: "Invalid parameter", type: message)
106
+ end
107
+
108
+ # Validate param and return HTTP 400 unless it presents.
109
+ # @api protected
110
+ # @param [String, Symbol] param_name Parameter name to validate
111
+ # @return [void]
112
+ def validate_param(param_name)
113
+ render_invalid_parameter("Parameter is missing: #{param_name}") if params[param_name].blank?
114
+ end
115
+
116
+ # Render Invalid Parameter error with 400 status
117
+ # @api protected
118
+ # @return [void]
119
+ def render_unprocessable_entity(message)
120
+ render status: 422, json: error_response(code: 422, message: "Unprocessable entity", type: message)
121
+ end
122
+
85
123
  # Returns JavaScript view for ajax request or redirects to back as default.
86
124
  # @api protected
87
- # @return [Responce] JavaScript view for ajax request or redirects to back as default
125
+ # @return [Response] JavaScript view for ajax request or redirects to back as default
88
126
  def return_back_or_ajax
89
127
  set_index_options
90
128
  respond_to do |format|
@@ -101,29 +139,15 @@ module ActivityNotification
101
139
  # @api protected
102
140
  # @return [Boolean] True
103
141
  def compatibly_redirect_back(request_params = {})
104
- # :only-rails5-plus#only-rails-with-callback-issue:
105
- # :only-rails5-plus#only-rails-without-callback-issue:
106
- # :only-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
107
- # :only-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
142
+ # :nocov:
108
143
  if Rails::VERSION::MAJOR >= 5
109
144
  redirect_back fallback_location: { action: :index }, **request_params
110
- # :only-rails5-plus#only-rails-with-callback-issue:
111
- # :only-rails5-plus#only-rails-without-callback-issue:
112
- # :only-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
113
- # :only-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
114
- # :except-rails5-plus#only-rails-with-callback-issue:
115
- # :except-rails5-plus#only-rails-without-callback-issue:
116
- # :except-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
117
- # :except-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
118
145
  elsif request.referer
119
146
  redirect_to :back, **request_params
120
147
  else
121
148
  redirect_to action: :index, **request_params
122
149
  end
123
- # :except-rails5-plus#only-rails-with-callback-issue:
124
- # :except-rails5-plus#only-rails-without-callback-issue:
125
- # :except-rails5-plus#only-rails-with-callback-issue#except-dynamoid:
126
- # :except-rails5-plus#only-rails-without-callback-issue#except-dynamoid:
150
+ # :nocov:
127
151
  true
128
152
  end
129
153
  end
@@ -0,0 +1,55 @@
1
+ module ActivityNotification
2
+ module Swagger::ErrorResponses #:nodoc:
3
+ module InvalidParameterError #:nodoc:
4
+ def self.extended(base)
5
+ base.response 400 do
6
+ key :description, "Invalid parameter"
7
+ content 'application/json' do
8
+ schema do
9
+ key :'$ref', :Error
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ module ForbiddenError #:nodoc:
17
+ def self.extended(base)
18
+ base.response 403 do
19
+ key :description, "Forbidden because of invalid parameter"
20
+ content 'application/json' do
21
+ schema do
22
+ key :'$ref', :Error
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ module ResourceNotFoundError #:nodoc:
30
+ def self.extended(base)
31
+ base.response 404 do
32
+ key :description, "Resource not found"
33
+ content 'application/json' do
34
+ schema do
35
+ key :'$ref', :Error
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ module UnprocessableEntityError #:nodoc:
43
+ def self.extended(base)
44
+ base.response 422 do
45
+ key :description, "Unprocessable entity"
46
+ content 'application/json' do
47
+ schema do
48
+ key :'$ref', :Error
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,273 @@
1
+ module ActivityNotification
2
+ module Swagger::NotificationsApi #:nodoc:
3
+ extend ActiveSupport::Concern
4
+ include ::Swagger::Blocks
5
+
6
+ included do
7
+ include Swagger::ErrorSchema
8
+
9
+ swagger_path '/{target_type}/{target_id}/notifications' do
10
+ operation :get do
11
+ key :summary, 'Get notifications'
12
+ key :description, 'Returns notification index of the target.'
13
+ key :operationId, 'getNotifications'
14
+ key :tags, ['notifications']
15
+
16
+ extend Swagger::NotificationsParameters::TargetParameters
17
+ parameter do
18
+ key :name, :filter
19
+ key :in, :query
20
+ key :description, "Filter option to load notification index by their status"
21
+ key :required, false
22
+ key :type, :string
23
+ key :enum, ['auto', 'opened', 'unopened']
24
+ key :default, 'auto'
25
+ end
26
+ parameter do
27
+ key :name, :limit
28
+ key :in, :query
29
+ key :description, "Maximum number of notifications to return"
30
+ key :required, false
31
+ key :type, :integer
32
+ end
33
+ parameter do
34
+ key :name, :reverse
35
+ key :in, :query
36
+ key :description, "Whether notification index will be ordered as earliest first"
37
+ key :required, false
38
+ key :type, :boolean
39
+ key :default, false
40
+ end
41
+ parameter do
42
+ key :name, :without_grouping
43
+ key :in, :query
44
+ key :description, "Whether notification index will include group members, same as 'with_group_members'"
45
+ key :required, false
46
+ key :type, :boolean
47
+ key :default, false
48
+ key :example, true
49
+ end
50
+ parameter do
51
+ key :name, :with_group_members
52
+ key :in, :query
53
+ key :description, "Whether notification index will include group members, same as 'without_grouping'"
54
+ key :required, false
55
+ key :type, :boolean
56
+ key :default, false
57
+ end
58
+ extend Swagger::NotificationsParameters::FilterByParameters
59
+
60
+ response 200 do
61
+ key :description, "Notification index of the target"
62
+ content 'application/json' do
63
+ schema do
64
+ key :type, :object
65
+ property :count do
66
+ key :type, :integer
67
+ key :description, "Number of notification index records"
68
+ key :example, 1
69
+ end
70
+ property :notifications do
71
+ key :type, :array
72
+ items do
73
+ key :'$ref', :Notification
74
+ end
75
+ key :description, "Notification index, which means array of notifications of the target"
76
+ end
77
+ end
78
+ end
79
+ end
80
+ extend Swagger::ErrorResponses::InvalidParameterError
81
+ extend Swagger::ErrorResponses::ResourceNotFoundError
82
+ end
83
+ end
84
+
85
+ swagger_path '/{target_type}/{target_id}/notifications/open_all' do
86
+ operation :post do
87
+ key :summary, 'Open all notifications'
88
+ key :description, 'Opens all notifications of the target.'
89
+ key :operationId, 'openAllNotifications'
90
+ key :tags, ['notifications']
91
+
92
+ extend Swagger::NotificationsParameters::TargetParameters
93
+ extend Swagger::NotificationsParameters::FilterByParameters
94
+
95
+ response 200 do
96
+ key :description, "Opened notifications"
97
+ content 'application/json' do
98
+ schema do
99
+ key :type, :object
100
+ property :count do
101
+ key :type, :integer
102
+ key :description, "Number of opened notification records"
103
+ key :example, 1
104
+ end
105
+ property :notifications do
106
+ key :type, :array
107
+ items do
108
+ key :'$ref', :Notification
109
+ end
110
+ key :description, "Opened notifications"
111
+ end
112
+ end
113
+ end
114
+ end
115
+ extend Swagger::ErrorResponses::InvalidParameterError
116
+ extend Swagger::ErrorResponses::ResourceNotFoundError
117
+ end
118
+ end
119
+
120
+ swagger_path '/{target_type}/{target_id}/notifications/{id}' do
121
+ operation :get do
122
+ key :summary, 'Get notification'
123
+ key :description, 'Returns a single notification.'
124
+ key :operationId, 'getNotification'
125
+ key :tags, ['notifications']
126
+
127
+ extend Swagger::NotificationsParameters::TargetParameters
128
+ extend Swagger::NotificationsParameters::IdParameter
129
+
130
+ response 200 do
131
+ key :description, "Found single notification"
132
+ content 'application/json' do
133
+ schema do
134
+ key :'$ref', :Notification
135
+ end
136
+ end
137
+ end
138
+ extend Swagger::ErrorResponses::InvalidParameterError
139
+ extend Swagger::ErrorResponses::ForbiddenError
140
+ extend Swagger::ErrorResponses::ResourceNotFoundError
141
+ end
142
+
143
+ operation :delete do
144
+ key :summary, 'Delete notification'
145
+ key :description, 'Deletes a notification.'
146
+ key :operationId, 'deleteNotification'
147
+ key :tags, ['notifications']
148
+
149
+ extend Swagger::NotificationsParameters::TargetParameters
150
+ extend Swagger::NotificationsParameters::IdParameter
151
+
152
+ response 204 do
153
+ key :description, "No content as successfully deleted"
154
+ end
155
+ extend Swagger::ErrorResponses::InvalidParameterError
156
+ extend Swagger::ErrorResponses::ForbiddenError
157
+ extend Swagger::ErrorResponses::ResourceNotFoundError
158
+ end
159
+ end
160
+
161
+ swagger_path '/{target_type}/{target_id}/notifications/{id}/open' do
162
+ operation :put do
163
+ key :summary, 'Open notification'
164
+ key :description, 'Opens a notification.'
165
+ key :operationId, 'openNotification'
166
+ key :tags, ['notifications']
167
+
168
+ extend Swagger::NotificationsParameters::TargetParameters
169
+ extend Swagger::NotificationsParameters::IdParameter
170
+ parameter do
171
+ key :name, :move
172
+ key :in, :query
173
+ key :description, "Whether it redirects to notifiable_path after the notification is opened"
174
+ key :required, false
175
+ key :type, :boolean
176
+ key :default, false
177
+ end
178
+
179
+ response 200 do
180
+ key :description, "Opened notification"
181
+ content 'application/json' do
182
+ schema do
183
+ key :type, :object
184
+ property :count do
185
+ key :type, :integer
186
+ key :description, "Number of opened notification records"
187
+ key :example, 2
188
+ end
189
+ property :notification do
190
+ key :type, :object
191
+ key :'$ref', :Notification
192
+ key :description, "Opened notification"
193
+ end
194
+ end
195
+ end
196
+ end
197
+ response 302 do
198
+ key :description, "Opened notification and redirection to notifiable_path"
199
+ content 'application/json' do
200
+ schema do
201
+ key :type, :object
202
+ property :location do
203
+ key :type, :string
204
+ key :format, :uri
205
+ key :description, "notifiable_path for redirection"
206
+ end
207
+ property :count do
208
+ key :type, :integer
209
+ key :description, "Number of opened notification records"
210
+ key :example, 2
211
+ end
212
+ property :notification do
213
+ key :type, :object
214
+ key :'$ref', :Notification
215
+ key :description, "Opened notification"
216
+ end
217
+ end
218
+ end
219
+ end
220
+ extend Swagger::ErrorResponses::InvalidParameterError
221
+ extend Swagger::ErrorResponses::ForbiddenError
222
+ extend Swagger::ErrorResponses::ResourceNotFoundError
223
+ end
224
+ end
225
+
226
+ swagger_path '/{target_type}/{target_id}/notifications/{id}/move' do
227
+ operation :get do
228
+ key :summary, 'Move to notifiable_path'
229
+ key :description, 'Moves to notifiable_path of the notification.'
230
+ key :operationId, 'moveNotification'
231
+ key :tags, ['notifications']
232
+
233
+ extend Swagger::NotificationsParameters::TargetParameters
234
+ extend Swagger::NotificationsParameters::IdParameter
235
+ parameter do
236
+ key :name, :open
237
+ key :in, :query
238
+ key :description, "Whether the notification will be opened"
239
+ key :required, false
240
+ key :type, :boolean
241
+ key :default, false
242
+ end
243
+
244
+ response 302 do
245
+ key :description, "Redirection to notifiable path"
246
+ content 'application/json' do
247
+ schema do
248
+ property :location do
249
+ key :type, :string
250
+ key :format, :uri
251
+ key :description, "Notifiable path for redirection"
252
+ end
253
+ property :count do
254
+ key :type, :integer
255
+ key :description, "Number of opened notification records"
256
+ key :example, 2
257
+ end
258
+ property :notification do
259
+ key :type, :object
260
+ key :'$ref', :Notification
261
+ key :description, "Found notification to move"
262
+ end
263
+ end
264
+ end
265
+ end
266
+ extend Swagger::ErrorResponses::InvalidParameterError
267
+ extend Swagger::ErrorResponses::ForbiddenError
268
+ extend Swagger::ErrorResponses::ResourceNotFoundError
269
+ end
270
+ end
271
+ end
272
+ end
273
+ end