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
@@ -23,19 +23,22 @@ Gem::Specification.new do |s|
23
23
  s.add_dependency 'railties', '>= 4.2.0', '< 6.1'
24
24
  s.add_dependency 'i18n', '>= 0.5.0'
25
25
  s.add_dependency 'jquery-rails', '>= 3.1.1'
26
+ s.add_dependency 'swagger-blocks', '>= 3.0.0'
26
27
 
27
28
  s.add_development_dependency 'puma', '>= 3.12.0'
28
29
  s.add_development_dependency 'sqlite3', '>= 1.3.13'
29
30
  s.add_development_dependency 'mysql2', '>= 0.5.2'
30
31
  s.add_development_dependency 'pg', '>= 1.0.0'
31
32
  s.add_development_dependency 'mongoid', '>= 4.0.0'
32
- s.add_development_dependency 'dynamoid', '>= 3.0.0', '< 3.2.0'
33
+ s.add_development_dependency 'dynamoid', '3.1.0'
33
34
  s.add_development_dependency 'rspec-rails', '>= 3.8.0'
34
35
  s.add_development_dependency 'factory_bot_rails', '>= 4.11.0', '< 5.0.0'
35
36
  s.add_development_dependency 'simplecov', '~> 0'
36
37
  s.add_development_dependency 'yard', '>= 0.9.16'
37
38
  s.add_development_dependency 'yard-activesupport-concern', '>= 0.0.1'
38
39
  s.add_development_dependency 'devise', '>= 4.5.0'
40
+ s.add_development_dependency 'devise_token_auth', '>= 1.1.3'
41
+ s.add_development_dependency 'mongoid-locker', '>= 2.0.0'
39
42
  s.add_development_dependency 'aws-sdk-sns', '~> 1'
40
43
  s.add_development_dependency 'slack-notifier', '>= 1.5.1'
41
44
  end
@@ -0,0 +1,12 @@
1
+ if defined?(ActionCable)
2
+ # Action Cable API channel to subscribe broadcasted notifications.
3
+ class ActivityNotification::NotificationApiChannel < ActivityNotification::NotificationChannel
4
+ # ActionCable::Channel::Base#subscribed
5
+ # @see https://api.rubyonrails.org/classes/ActionCable/Channel/Base.html#method-i-subscribed
6
+ def subscribed
7
+ stream_from "#{ActivityNotification.config.notification_api_channel_prefix}_#{@target.to_class_name}#{ActivityNotification.config.composite_key_delimiter}#{@target.id}"
8
+ rescue
9
+ reject
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,46 @@
1
+ if defined?(ActionCable)
2
+ # Action Cable API channel to subscribe broadcasted notifications with Devise authentication.
3
+ class ActivityNotification::NotificationApiWithDeviseChannel < ActivityNotification::NotificationApiChannel
4
+ # Include PolymorphicHelpers to resolve string extentions
5
+ include ActivityNotification::PolymorphicHelpers
6
+
7
+ protected
8
+
9
+ # Find current authenticated target from auth token headers with Devise Token Auth.
10
+ # @api protected
11
+ # @param [String] devise_type Class name of Devise resource to authenticate
12
+ # @return [Object] Current authenticated target from auth token headers
13
+ def find_current_target(devise_type = nil)
14
+ devise_type = (devise_type || @target.notification_devise_resource.class.name).to_s
15
+ current_target = devise_type.to_model_class.find_by!(uid: params[:uid])
16
+ return nil unless current_target.valid_token?(params[:'access-token'], params[:client])
17
+ current_target
18
+ end
19
+
20
+ # Set @target instance variable from request parameters.
21
+ # This method overrides super (ActivityNotiication::NotificationChannel#set_target)
22
+ # to set devise authenticated target when the target_id params is not specified.
23
+ # @api protected
24
+ # @return [Object] Target instance (Reject subscription when request parameters are not enough)
25
+ def set_target
26
+ reject and return if (target_type = params[:target_type]).blank?
27
+ if params[:target_id].blank? && params["#{target_type.to_s.to_resource_name[/([^\/]+)$/]}_id"].blank?
28
+ reject and return if params[:devise_type].blank?
29
+ current_target = find_current_target(params[:devise_type])
30
+ params[:target_id] = target_type.to_model_class.resolve_current_devise_target(current_target)
31
+ reject and return if params[:target_id].blank?
32
+ end
33
+ super
34
+ end
35
+
36
+ # Authenticate the target of requested notification with authenticated devise resource.
37
+ # @api protected
38
+ # @return [Response] Returns connected or rejected
39
+ def authenticate_target!
40
+ current_resource = find_current_target
41
+ reject unless @target.authenticated_with_devise?(current_resource)
42
+ rescue
43
+ reject
44
+ end
45
+ end
46
+ end
@@ -22,14 +22,14 @@ if defined?(ActionCable)
22
22
  target_class = target_type.to_s.to_model_class
23
23
  @target = params[:target_id].present? ?
24
24
  target_class.find_by!(id: params[:target_id]) :
25
- target_class.find_by!(id: params["#{target_type.to_s.to_resource_name}_id"])
25
+ target_class.find_by!(id: params["#{target_type.to_s.to_resource_name[/([^\/]+)$/]}_id"])
26
26
  rescue
27
27
  reject
28
28
  end
29
29
 
30
30
  # Allow the target to subscribe notification channel if notification_action_cable_with_devise? returns false
31
31
  # @api protected
32
- # @return [Responce] Returns connected or rejected
32
+ # @return [Response] Returns connected or rejected
33
33
  def authenticate_target!
34
34
  reject if @target.nil? || @target.notification_action_cable_with_devise?
35
35
  end
@@ -29,7 +29,7 @@ if defined?(ActionCable)
29
29
  # @return [Object] Target instance (Reject subscription when request parameters are not enough)
30
30
  def set_target
31
31
  reject and return if (target_type = params[:target_type]).blank?
32
- if params[:target_id].blank? && params["#{target_type.to_s.to_resource_name}_id"].blank?
32
+ if params[:target_id].blank? && params["#{target_type.to_s.to_resource_name[/([^\/]+)$/]}_id"].blank?
33
33
  reject and return if params[:devise_type].blank?
34
34
  current_target = find_current_target(params[:devise_type])
35
35
  params[:target_id] = target_type.to_model_class.resolve_current_devise_target(current_target)
@@ -40,7 +40,7 @@ if defined?(ActionCable)
40
40
 
41
41
  # Authenticate the target of requested notification with authenticated devise resource.
42
42
  # @api protected
43
- # @return [Responce] Returns connected or rejected
43
+ # @return [Response] Returns connected or rejected
44
44
  def authenticate_target!
45
45
  current_resource = find_current_target
46
46
  reject unless @target.authenticated_with_devise?(current_resource)
@@ -0,0 +1,75 @@
1
+ module ActivityNotification
2
+ # Controller to manage Swagger API references.
3
+ # @See https://github.com/fotinakis/swagger-blocks/blob/master/spec/lib/swagger_v3_blocks_spec.rb
4
+ class ApidocsController < ActivityNotification.config.parent_controller.constantize
5
+ include ::Swagger::Blocks
6
+
7
+ swagger_root do
8
+ key :openapi, '3.0.0'
9
+ info version: ActivityNotification::VERSION do
10
+ key :description, 'A default REST API created by activity_notification which provides integrated user activity notifications for Ruby on Rails'
11
+ key :title, 'ActivityNotification'
12
+ key :termsOfService, 'https://github.com/simukappu/activity_notification'
13
+ contact do
14
+ key :name, 'activity_notification community'
15
+ key :url, 'https://github.com/simukappu/activity_notification#help'
16
+ end
17
+ license do
18
+ key :name, 'MIT'
19
+ key :url, 'https://github.com/simukappu/activity_notification/blob/master/MIT-LICENSE'
20
+ end
21
+ end
22
+
23
+ server do
24
+ key :url, 'https://activity-notification-example.herokuapp.com/api/{version}'
25
+ key :description, 'ActivityNotification online demo including REST API'
26
+
27
+ variable :version do
28
+ key :enum, ['v2']
29
+ key :default, :"v#{ActivityNotification::GEM_VERSION::MAJOR}"
30
+ end
31
+ end
32
+ server do
33
+ key :url, 'http://localhost:3000/api/{version}'
34
+ key :description, 'Example Rails application at localhost including REST API'
35
+
36
+ variable :version do
37
+ key :enum, ['v2']
38
+ key :default, :"v#{ActivityNotification::GEM_VERSION::MAJOR}"
39
+ end
40
+ end
41
+
42
+ tag do
43
+ key :name, 'notifications'
44
+ key :description, 'Operations about user activity notifications'
45
+ externalDocs do
46
+ key :description, 'Find out more'
47
+ key :url, 'https://github.com/simukappu/activity_notification#creating-notifications'
48
+ end
49
+ end
50
+
51
+ tag do
52
+ key :name, 'subscriptions'
53
+ key :description, 'Operations about subscription management'
54
+ externalDocs do
55
+ key :description, 'Find out more'
56
+ key :url, 'https://github.com/simukappu/activity_notification#subscription-management'
57
+ end
58
+ end
59
+ end
60
+
61
+ SWAGGERED_CLASSES = [
62
+ Notification,
63
+ NotificationsApiController,
64
+ Subscription,
65
+ SubscriptionsApiController,
66
+ self
67
+ ].freeze
68
+
69
+ # Returns root JSON of Swagger API references.
70
+ # GET /apidocs
71
+ def index
72
+ render json: ::Swagger::Blocks.build_root_json(SWAGGERED_CLASSES)
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,143 @@
1
+ module ActivityNotification
2
+ # Controller to manage notifications API.
3
+ class NotificationsApiController < NotificationsController
4
+ # Include Swagger API reference
5
+ include Swagger::NotificationsApi
6
+ # Include CommonApiController to select target and define common methods
7
+ include CommonApiController
8
+ protect_from_forgery except: [:open_all]
9
+ rescue_from ActivityNotification::NotifiableNotFoundError, with: :render_notifiable_not_found
10
+
11
+ # Returns notification index of the target.
12
+ #
13
+ # GET /:target_type/:target_id/notifications
14
+ # @overload index(params)
15
+ # @param [Hash] params Request parameter options for notification index
16
+ # @option params [String] :filter (nil) Filter option to load notification index by their status (Nothing as auto, 'opened' or 'unopened')
17
+ # @option params [String] :limit (nil) Maximum number of notifications to return
18
+ # @option params [String] :reverse ('false') Whether notification index will be ordered as earliest first
19
+ # @option params [String] :without_grouping ('false') Whether notification index will include group members
20
+ # @option params [String] :with_group_members ('false') Whether notification index will include group members
21
+ # @option params [String] :filtered_by_type (nil) Notifiable type to filter notification index
22
+ # @option params [String] :filtered_by_group_type (nil) Group type to filter notification index, valid with :filtered_by_group_id
23
+ # @option params [String] :filtered_by_group_id (nil) Group instance ID to filter notification index, valid with :filtered_by_group_type
24
+ # @option params [String] :filtered_by_key (nil) Key of notifications to filter notification index
25
+ # @option params [String] :later_than (nil) ISO 8601 format time to filter notification index later than specified time
26
+ # @option params [String] :earlier_than (nil) ISO 8601 format time to filter notification index earlier than specified time
27
+ # @return [JSON] count: number of notification index records, notifications: notification index
28
+ def index
29
+ super
30
+ render json: {
31
+ count: @notifications.size,
32
+ notifications: @notifications.as_json(notification_json_options)
33
+ }
34
+ end
35
+
36
+ # Opens all notifications of the target.
37
+ #
38
+ # POST /:target_type/:target_id/notifications/open_all
39
+ # @overload open_all(params)
40
+ # @param [Hash] params Request parameters
41
+ # @option params [String] :filtered_by_type (nil) Notifiable type to filter notification index
42
+ # @option params [String] :filtered_by_group_type (nil) Group type to filter notification index, valid with :filtered_by_group_id
43
+ # @option params [String] :filtered_by_group_id (nil) Group instance ID to filter notification index, valid with :filtered_by_group_type
44
+ # @option params [String] :filtered_by_key (nil) Key of notifications to filter notification index
45
+ # @option params [String] :later_than (nil) ISO 8601 format time to filter notification index later than specified time
46
+ # @option params [String] :earlier_than (nil) ISO 8601 format time to filter notification index earlier than specified time
47
+ # @return [JSON] count: number of opened notification records, notifications: opened notifications
48
+ def open_all
49
+ super
50
+ render json: {
51
+ count: @opened_notifications.size,
52
+ notifications: @opened_notifications.as_json(notification_json_options)
53
+ }
54
+ end
55
+
56
+ # Returns a single notification.
57
+ #
58
+ # GET /:target_type/:target_id/notifications/:id
59
+ # @overload show(params)
60
+ # @param [Hash] params Request parameters
61
+ # @return [JSON] Found single notification
62
+ def show
63
+ super
64
+ render json: notification_json
65
+ end
66
+
67
+ # Deletes a notification.
68
+ #
69
+ # DELETE /:target_type/:target_id/notifications/:id
70
+ # @overload destroy(params)
71
+ # @param [Hash] params Request parameters
72
+ # @return [JSON] 204 No Content
73
+ def destroy
74
+ super
75
+ head 204
76
+ end
77
+
78
+ # Opens a notification.
79
+ #
80
+ # PUT /:target_type/:target_id/notifications/:id/open
81
+ # @overload open(params)
82
+ # @param [Hash] params Request parameters
83
+ # @option params [String] :move ('false') Whether it redirects to notifiable_path after the notification is opened
84
+ # @return [JSON] count: number of opened notification records, notification: opened notification
85
+ def open
86
+ super
87
+ unless params[:move].to_s.to_boolean(false)
88
+ render json: {
89
+ count: @opened_notifications_count,
90
+ notification: notification_json
91
+ }
92
+ end
93
+ end
94
+
95
+ # Moves to notifiable_path of the notification.
96
+ #
97
+ # GET /:target_type/:target_id/notifications/:id/move
98
+ # @overload open(params)
99
+ # @param [Hash] params Request parameters
100
+ # @option params [String] :open ('false') Whether the notification will be opened
101
+ # @return [JSON] location: notifiable path, count: number of opened notification records, notification: specified notification
102
+ def move
103
+ super
104
+ render status: 302, location: @notification.notifiable_path, json: {
105
+ location: @notification.notifiable_path,
106
+ count: (@opened_notifications_count || 0),
107
+ notification: notification_json
108
+ }
109
+ end
110
+
111
+ protected
112
+
113
+ # Returns options for notification JSON
114
+ # @api protected
115
+ def notification_json_options
116
+ {
117
+ include: {
118
+ target: { methods: [:printable_type, :printable_target_name] },
119
+ notifiable: { methods: [:printable_type] },
120
+ group: { methods: [:printable_type, :printable_group_name] },
121
+ notifier: { methods: [:printable_type, :printable_notifier_name] },
122
+ group_members: {}
123
+ },
124
+ methods: [:notifiable_path, :printable_notifiable_name, :group_member_notifier_count, :group_notification_count]
125
+ }
126
+ end
127
+
128
+ # Returns JSON of @notification
129
+ # @api protected
130
+ def notification_json
131
+ @notification.as_json(notification_json_options)
132
+ end
133
+
134
+ # Render associated notifiable record not found error with 500 status
135
+ # @api protected
136
+ # @param [Error] error Error object
137
+ # @return [void]
138
+ def render_notifiable_not_found(error)
139
+ render status: 500, json: error_response(code: 500, message: "Associated record not found", type: error.message)
140
+ end
141
+
142
+ end
143
+ end
@@ -0,0 +1,7 @@
1
+ module ActivityNotification
2
+ # Controller to manage notifications API with Devise authentication.
3
+ class NotificationsApiWithDeviseController < NotificationsApiController
4
+ include DeviseTokenAuth::Concerns::SetUserByToken if defined?(DeviseTokenAuth)
5
+ include DeviseAuthenticationController
6
+ end
7
+ end
@@ -10,24 +10,22 @@ module ActivityNotification
10
10
  # GET /:target_type/:target_id/notifications
11
11
  # @overload index(params)
12
12
  # @param [Hash] params Request parameter options for notification index
13
- # @option params [String] :filter (nil) Filter option to load notification index (Nothing as auto, 'opened' or 'unopened')
14
- # @option params [String] :limit (nil) Limit to query for notifications
15
- # @option params [String] :reverse ('false') If notification index will be ordered as earliest first
16
- # @option params [String] :without_grouping ('false') If notification index will include group members
17
- # @option params [String] :with_group_members ('false') If notification index will include group members
18
- # @option params [String] :filtered_by_type (nil) Notifiable type for filter
19
- # @option params [String] :filtered_by_group_type (nil) Group type for filter, valid with :filtered_by_group_id
20
- # @option params [String] :filtered_by_group_id (nil) Group instance id for filter, valid with :filtered_by_group_type
21
- # @option params [String] :filtered_by_key (nil) Key of the notification for filter
13
+ # @option params [String] :filter (nil) Filter option to load notification index by their status (Nothing as auto, 'opened' or 'unopened')
14
+ # @option params [String] :limit (nil) Maximum number of notifications to return
15
+ # @option params [String] :reverse ('false') Whether notification index will be ordered as earliest first
16
+ # @option params [String] :without_grouping ('false') Whether notification index will include group members
17
+ # @option params [String] :with_group_members ('false') Whether notification index will include group members
18
+ # @option params [String] :filtered_by_type (nil) Notifiable type to filter notification index
19
+ # @option params [String] :filtered_by_group_type (nil) Group type to filter notification index, valid with :filtered_by_group_id
20
+ # @option params [String] :filtered_by_group_id (nil) Group instance ID to filter notification index, valid with :filtered_by_group_type
21
+ # @option params [String] :filtered_by_key (nil) Key of notifications to filter notification index
22
+ # @option params [String] :later_than (nil) ISO 8601 format time to filter notification index later than specified time
23
+ # @option params [String] :earlier_than (nil) ISO 8601 format time to filter notification index earlier than specified time
22
24
  # @option params [String] :reload ('true') Whether notification index will be reloaded
23
- # @return [Responce] HTML view as default or JSON of notification index with json format parameter
25
+ # @return [Response] HTML view of notification index
24
26
  def index
25
27
  set_index_options
26
28
  load_index if params[:reload].to_s.to_boolean(true)
27
- respond_to do |format|
28
- format.html # index.html.erb
29
- format.json { render json: @notifications.to_json(include: [:target, :notifiable, :group]) }
30
- end
31
29
  end
32
30
 
33
31
  # Opens all notifications of the target.
@@ -35,18 +33,20 @@ module ActivityNotification
35
33
  # POST /:target_type/:target_id/notifications/open_all
36
34
  # @overload open_all(params)
37
35
  # @param [Hash] params Request parameters
38
- # @option params [String] :filter (nil) Filter option to load notification index (Nothing as auto, 'opened' or 'unopened')
39
- # @option params [String] :limit (nil) Limit to query for notifications
40
- # @option params [String] :reload ('true') Whether notification index will be reloaded
41
- # @option params [String] :without_grouping ('false') If notification index will include group members
42
- # @option params [String] :with_group_members ('false') If notification index will include group members
43
- # @option params [String] :filtered_by_type (nil) Notifiable type for filter
44
- # @option params [String] :filtered_by_group_type (nil) Group type for filter, valid only :filtered_by_group_id
45
- # @option params [String] :filtered_by_group_id (nil) Group instance id for filter, valid only :filtered_by_group_type
46
- # @option params [String] :filtered_by_key (nil) Key of the notification for filter
47
- # @return [Responce] JavaScript view for ajax request or redirects to back as default
36
+ # @option params [String] :filter (nil) Filter option to load notification index by their status (Nothing as auto, 'opened' or 'unopened')
37
+ # @option params [String] :limit (nil) Maximum number of notifications to return
38
+ # @option params [String] :without_grouping ('false') Whether notification index will include group members
39
+ # @option params [String] :with_group_members ('false') Whether notification index will include group members
40
+ # @option params [String] :filtered_by_type (nil) Notifiable type to filter notification index
41
+ # @option params [String] :filtered_by_group_type (nil) Group type to filter notification index, valid with :filtered_by_group_id
42
+ # @option params [String] :filtered_by_group_id (nil) Group instance ID to filter notification index, valid with :filtered_by_group_type
43
+ # @option params [String] :filtered_by_key (nil) Key of notifications to filter notification index
44
+ # @option params [String] :later_than (nil) ISO 8601 format time to filter notification index later than specified time
45
+ # @option params [String] :earlier_than (nil) ISO 8601 format time to filter notification index earlier than specified time
46
+ # @option params [String] :reload ('true') Whether notification index will be reloaded
47
+ # @return [Response] JavaScript view for ajax request or redirects to back as default
48
48
  def open_all
49
- @target.open_all_notifications(params)
49
+ @opened_notifications = @target.open_all_notifications(params)
50
50
  return_back_or_ajax
51
51
  end
52
52
 
@@ -55,22 +55,21 @@ module ActivityNotification
55
55
  # GET /:target_type/:target_id/notifications/:id
56
56
  # @overload show(params)
57
57
  # @param [Hash] params Request parameters
58
- # @return [Responce] HTML view as default
58
+ # @return [Response] HTML view as default
59
59
  def show
60
60
  end
61
61
 
62
62
  # Deletes a notification.
63
63
  #
64
64
  # DELETE /:target_type/:target_id/notifications/:id
65
- #
66
65
  # @overload destroy(params)
67
66
  # @param [Hash] params Request parameters
68
- # @option params [String] :filter (nil) Filter option to load notification index (Nothing as auto, 'opened' or 'unopened')
69
- # @option params [String] :limit (nil) Limit to query for notifications
70
- # @option params [String] :reload ('true') Whether notification index will be reloaded
71
- # @option params [String] :without_grouping ('false') If notification index will include group members
72
- # @option params [String] :with_group_members ('false') If notification index will include group members
73
- # @return [Responce] JavaScript view for ajax request or redirects to back as default
67
+ # @option params [String] :filter (nil) Filter option to load notification index by their status (Nothing as auto, 'opened' or 'unopened')
68
+ # @option params [String] :limit (nil) Maximum number of notifications to return
69
+ # @option params [String] :without_grouping ('false') Whether notification index will include group members
70
+ # @option params [String] :with_group_members ('false') Whether notification index will include group members
71
+ # @option params [String] :reload ('true') Whether notification index will be reloaded
72
+ # @return [Response] JavaScript view for ajax request or redirects to back as default
74
73
  def destroy
75
74
  @notification.destroy
76
75
  return_back_or_ajax
@@ -78,22 +77,20 @@ module ActivityNotification
78
77
 
79
78
  # Opens a notification.
80
79
  #
81
- # POST /:target_type/:target_id/notifications/:id/open
80
+ # PUT /:target_type/:target_id/notifications/:id/open
82
81
  # @overload open(params)
83
82
  # @param [Hash] params Request parameters
84
- # @option params [String] :move ('false') Whether redirects to notifiable_path after the notification is opened
85
- # @option params [String] :filter (nil) Filter option to load notification index (Nothing as auto, 'opened' or 'unopened')
86
- # @option params [String] :limit (nil) Limit to query for notifications
87
- # @option params [String] :reload ('true') Whether notification index will be reloaded
88
- # @option params [String] :without_grouping ('false') If notification index will include group members
89
- # @option params [String] :with_group_members ('false') If notification index will include group members
90
- # @return [Responce] JavaScript view for ajax request or redirects to back as default
83
+ # @option params [String] :move ('false') Whether it redirects to notifiable_path after the notification is opened
84
+ # @option params [String] :filter (nil) Filter option to load notification index by their status (Nothing as auto, 'opened' or 'unopened')
85
+ # @option params [String] :limit (nil) Maximum number of notifications to return
86
+ # @option params [String] :without_grouping ('false') Whether notification index will include group members
87
+ # @option params [String] :with_group_members ('false') Whether notification index will include group members
88
+ # @option params [String] :reload ('true') Whether notification index will be reloaded
89
+ # @return [Response] JavaScript view for ajax request or redirects to back as default
91
90
  def open
92
91
  with_members = !(params[:with_group_members].to_s.to_boolean(false) || params[:without_grouping].to_s.to_boolean(false))
93
- @notification.open!(with_members: with_members)
94
- params[:move].to_s.to_boolean(false) ?
95
- move :
96
- return_back_or_ajax
92
+ @opened_notifications_count = @notification.open!(with_members: with_members)
93
+ params[:move].to_s.to_boolean(false) ? move : return_back_or_ajax
97
94
  end
98
95
 
99
96
  # Moves to notifiable_path of the notification.
@@ -101,14 +98,17 @@ module ActivityNotification
101
98
  # GET /:target_type/:target_id/notifications/:id/move
102
99
  # @overload open(params)
103
100
  # @param [Hash] params Request parameters
104
- # @option params [String] :open ('false') Whether the notification will be opened
105
- # @option params [String] :filter (nil) Filter option to load notification index (Nothing as auto, 'opened' or 'unopened')
106
- # @option params [String] :limit (nil) Limit to query for notifications
107
- # @option params [String] :reload ('true') Whether notification index will be reloaded
108
- # @return [Responce] JavaScript view for ajax request or redirects to back as default
101
+ # @option params [String] :open ('false') Whether the notification will be opened
102
+ # @option params [String] :filter (nil) Filter option to load notification index by their status (Nothing as auto, 'opened' or 'unopened')
103
+ # @option params [String] :limit (nil) Maximum number of notifications to return
104
+ # @option params [String] :without_grouping ('false') Whether notification index will include group members
105
+ # @option params [String] :with_group_members ('false') Whether notification index will include group members
106
+ # @option params [String] :reload ('true') Whether notification index will be reloaded
107
+ # @return [Response] JavaScript view for ajax request or redirects to back as default
109
108
  def move
110
- @notification.open! if params[:open].to_s.to_boolean(false)
111
- redirect_to @notification.notifiable_path
109
+ with_members = !(params[:with_group_members].to_s.to_boolean(false) || params[:without_grouping].to_s.to_boolean(false))
110
+ @opened_notifications_count = @notification.open!(with_members: with_members) if params[:open].to_s.to_boolean(false)
111
+ redirect_to_notifiable_path
112
112
  end
113
113
 
114
114
  # Returns path of the target view templates.
@@ -117,6 +117,26 @@ module ActivityNotification
117
117
  super
118
118
  end
119
119
 
120
+ # :nocov:
121
+ if Rails::VERSION::MAJOR == 4
122
+ # Defines custom renderer class method for Rails 4.2
123
+ def self.renderer
124
+ view_context = ActionView::Base.new(ActionController::Base.view_paths, {})
125
+ view_context.class_eval do
126
+ include Rails.application.routes.url_helpers
127
+ def default_url_options
128
+ ActionMailer::Base.default_url_options
129
+ end
130
+ def render(params = {})
131
+ assign(params[:assigns])
132
+ super(params)
133
+ end
134
+ end
135
+ view_context
136
+ end
137
+ end
138
+ # :nocov:
139
+
120
140
  protected
121
141
 
122
142
  # Sets @notification instance variable from request parameters.
@@ -135,7 +155,7 @@ module ActivityNotification
135
155
  params[:reverse].to_s.to_boolean(false) : nil
136
156
  with_group_members = params[:with_group_members].present? || params[:without_grouping].present? ?
137
157
  params[:with_group_members].to_s.to_boolean(false) || params[:without_grouping].to_s.to_boolean(false) : nil
138
- @index_options = params.permit(:filter, :filtered_by_type, :filtered_by_group_type, :filtered_by_group_id, :filtered_by_key, :routing_scope, :devise_default_routes)
158
+ @index_options = params.permit(:filter, :filtered_by_type, :filtered_by_group_type, :filtered_by_group_id, :filtered_by_key, :later_than, :earlier_than, :routing_scope, :devise_default_routes)
139
159
  .to_h.symbolize_keys
140
160
  .merge(limit: limit, reverse: reverse, with_group_members: with_group_members)
141
161
  end
@@ -155,6 +175,12 @@ module ActivityNotification
155
175
  end
156
176
  end
157
177
 
178
+ # Redirect to notifiable_path
179
+ # @api protected
180
+ def redirect_to_notifiable_path
181
+ redirect_to @notification.notifiable_path
182
+ end
183
+
158
184
  # Returns controller path.
159
185
  # This method is called from target_view_path method and can be overridden.
160
186
  # @api protected