activity_notification 2.7.1 → 2.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56122565c61de552c48285f449429a7d64616f5c13f04f0e023a68b33273db6f
4
- data.tar.gz: 6462762a8f2d8b7b68b82be0632c1dd3d89379aa7fe904c6f4492053be2633fb
3
+ metadata.gz: 9c4c8885cdeaf0c979ae2474e5ca5459a16e0f14c605fa5d2f0ad37076e7c793
4
+ data.tar.gz: 267223c3dbc745920baabb75d5e936cafef5a3fbe2e301f46aab04ae9d6a34a8
5
5
  SHA512:
6
- metadata.gz: fd7b507f00663ebcf26694a0c8c98a0051f51f7bf35e67687a77e668fb61f500f1cf84e2fa433ecbc39bf59357449fcd0cfd0303b107b7e16ea9838d39e3848f
7
- data.tar.gz: 12cd4b4e589aa66e4ccb6108beb5624d5b13f3d327234491520551c5d9134afabe718367ee3d5193a92e9a1fd2491c9bf5d59250e8e2bb8588c3bcdfaf8565b7
6
+ metadata.gz: bcb53649395b3e43ab8e3b4a043a40947305ee35cd15fe16a9737f16c866ff543749e78b00c5c5659d8a34eaf198a6c30b6933d29a048db00d56ea17b7c4694e
7
+ data.tar.gz: cc390e51688280d2c84bb949814ae6a3ecad9f1c444066b45d91316d47fea5bb71a7dec03fd4a582d503cc5f7aad70e47c9c0f7ddf16b1da1f92ae1485c10595
@@ -4,6 +4,7 @@ module ActivityNotification
4
4
  # Include CommonController to select target and define common methods
5
5
  include CommonController
6
6
  before_action :set_notification, except: [:index, :open_all, :destroy_all]
7
+ before_action :validate_time_params, only: [:index, :open_all, :destroy_all]
7
8
 
8
9
  # Shows notification index of the target.
9
10
  #
@@ -125,6 +126,7 @@ module ActivityNotification
125
126
  # @overload open(params)
126
127
  # @param [Hash] params Request parameters
127
128
  # @option params [String] :open ('false') Whether the notification will be opened
129
+ # @option params [String] :open_token (nil) Token to open the notification, which is required with open parameter since GET requests are not protected from CSRF (See Notification#open_token)
128
130
  # @option params [String] :filter (nil) Filter option to load notification index by their status (Nothing as auto, 'opened' or 'unopened')
129
131
  # @option params [String] :limit (nil) Maximum number of notifications to return
130
132
  # @option params [String] :without_grouping ('false') Whether notification index will include group members
@@ -133,7 +135,7 @@ module ActivityNotification
133
135
  # @return [Response] JavaScript view for ajax request or redirects to back as default
134
136
  def move
135
137
  with_members = !(params[:with_group_members].to_s.to_boolean(false) || params[:without_grouping].to_s.to_boolean(false))
136
- @opened_notifications_count = @notification.open!(with_members: with_members) if params[:open].to_s.to_boolean(false)
138
+ @opened_notifications_count = @notification.open!(with_members: with_members) if params[:open].to_s.to_boolean(false) && @notification.valid_open_token?(params[:open_token])
137
139
  redirect_to_notifiable_path
138
140
  end
139
141
 
@@ -171,7 +173,7 @@ module ActivityNotification
171
173
  # @api protected
172
174
  # @return [Hash] options to load notification index
173
175
  def set_index_options
174
- limit = params[:limit].to_i > 0 ? params[:limit].to_i : nil
176
+ limit = index_limit
175
177
  reverse = params[:reverse].present? ?
176
178
  params[:reverse].to_s.to_boolean(false) : nil
177
179
  with_group_members = params[:with_group_members].present? || params[:without_grouping].present? ? params[:with_group_members].to_s.to_boolean(false) || params[:without_grouping].to_s.to_boolean(false) : nil
@@ -180,6 +182,21 @@ module ActivityNotification
180
182
  .merge(limit: limit, reverse: reverse, with_group_members: with_group_members)
181
183
  end
182
184
 
185
+ # Validates ISO 8601 time parameters and returns HTTP 400 when they are invalid.
186
+ # @api protected
187
+ # @return [void]
188
+ def validate_time_params
189
+ [:later_than, :earlier_than].each do |param_name|
190
+ next unless params.key?(param_name)
191
+ begin
192
+ Time.iso8601(params[param_name].to_s)
193
+ rescue ArgumentError
194
+ render_invalid_parameter("Parameter is not ISO 8601 time: #{param_name}")
195
+ return
196
+ end
197
+ end
198
+ end
199
+
183
200
  # Loads notification index with request parameters.
184
201
  # @api protected
185
202
  # @return [Array] Array of notification index
@@ -198,7 +198,7 @@ module ActivityNotification
198
198
  # @api protected
199
199
  # @return [Hash] options to load subscription index
200
200
  def set_index_options
201
- limit = params[:limit].to_i > 0 ? params[:limit].to_i : nil
201
+ limit = index_limit
202
202
  reverse = params[:reverse].present? ? params[:reverse].to_s.to_boolean(false) : nil
203
203
  @index_options = params.permit(:filter, :filtered_by_key, :routing_scope, :devise_default_routes)
204
204
  .to_h.symbolize_keys.merge(limit: limit, reverse: reverse)
@@ -707,6 +707,23 @@ module ActivityNotification
707
707
  unopened_member_count + 1
708
708
  end
709
709
 
710
+ # Returns a token to open the notification by HTTP GET request to move action.
711
+ # GET requests are not protected from CSRF, so move action opens the notification only with this token.
712
+ # move_notification_path_for and move_notification_url_for helpers add this token when open: true is specified.
713
+ #
714
+ # @return [String] Token to open the notification by move action
715
+ def open_token
716
+ ActivityNotification.open_token_verifier.generate(id.to_s, purpose: :open_notification)
717
+ end
718
+
719
+ # Returns if the token is valid to open the notification by move action.
720
+ #
721
+ # @param [String] token Token to verify
722
+ # @return [Boolean] If the token is valid to open the notification
723
+ def valid_open_token?(token)
724
+ token.is_a?(String) && ActivityNotification.open_token_verifier.verified(token, purpose: :open_notification) == id.to_s
725
+ end
726
+
710
727
  # Returns if the notification is unopened.
711
728
  #
712
729
  # @return [Boolean] If the notification is unopened
@@ -92,6 +92,12 @@ module ActivityNotification
92
92
  end
93
93
  private_class_method :contains_javascript_query_operator?
94
94
 
95
+ # Returns message verifier to generate and verify tokens to open notifications by move action.
96
+ # @return [ActiveSupport::MessageVerifier] Message verifier for open tokens
97
+ def self.open_token_verifier
98
+ Rails.application.message_verifier("activity_notification_open_token")
99
+ end
100
+
95
101
  # Casts to indifferent hash
96
102
  # @param [ActionController::Parameters, Hash] hash
97
103
  # @return [HashWithIndifferentAccess] Converted indifferent hash
@@ -249,6 +249,15 @@ module ActivityNotification
249
249
  # @return [Boolean] Whether the REST API restricts embedded associated records to their id and printable_* method values.
250
250
  attr_accessor :restrict_api_response_fields
251
251
 
252
+ # @overload max_index_limit
253
+ # Returns maximum number of records that notification and subscription index actions of the controllers return
254
+ # @return [Integer, nil] Maximum number of records that index actions return.
255
+ # @overload max_index_limit=(value)
256
+ # Sets maximum number of records that notification and subscription index actions of the controllers return. The limit request parameter is capped by this value, and this value is used when the limit parameter is not specified. Set nil to remove the cap.
257
+ # @param [Integer, nil] max_index_limit The new max_index_limit
258
+ # @return [Integer, nil] Maximum number of records that index actions return.
259
+ attr_accessor :max_index_limit
260
+
252
261
  # Initialize configuration for ActivityNotification.
253
262
  # These configuration can be overridden in initializer.
254
263
  # @return [Config] A new instance of Config
@@ -282,6 +291,7 @@ module ActivityNotification
282
291
  @notification_api_channel_prefix = 'activity_notification_api_channel'
283
292
  @rescue_optional_target_errors = true
284
293
  @restrict_api_response_fields = false
294
+ @max_index_limit = 1000
285
295
  end
286
296
 
287
297
  # Sets ORM name for ActivityNotification (:active_record, :mongoid or :dynamodb)
@@ -103,6 +103,15 @@ module ActivityNotification
103
103
  render status: 400, json: error_response(code: 400, message: "Invalid parameter", type: message)
104
104
  end
105
105
 
106
+ # Returns limit for index actions from request parameter, capped by ActivityNotification.config.max_index_limit.
107
+ # @api protected
108
+ # @return [Integer, nil] Limit for index actions
109
+ def index_limit
110
+ limit = params[:limit].to_i > 0 ? params[:limit].to_i : nil
111
+ max_limit = ActivityNotification.config.max_index_limit
112
+ max_limit ? [limit || max_limit, max_limit].min : limit
113
+ end
114
+
106
115
  # Validate param and return HTTP 400 unless it presents.
107
116
  # @api protected
108
117
  # @param [String, Symbol] param_name Parameter name to validate
@@ -294,11 +294,18 @@ module ActivityNotification
294
294
  parameter do
295
295
  key :name, :open
296
296
  key :in, :query
297
- key :description, "Whether the notification will be opened"
297
+ key :description, "Whether the notification will be opened. The notification is opened only with a valid open_token, since GET requests are not protected from CSRF. Use PUT /{target_type}/{target_id}/notifications/{id}/open with move parameter to open and move without a token."
298
298
  key :required, false
299
299
  key :type, :boolean
300
300
  key :default, false
301
301
  end
302
+ parameter do
303
+ key :name, :open_token
304
+ key :in, :query
305
+ key :description, "Token to open the notification with open parameter, which is generated by Notification#open_token and added by move_notification_path_for and move_notification_url_for helpers"
306
+ key :required, false
307
+ key :type, :string
308
+ end
302
309
 
303
310
  response 302 do
304
311
  key :description, "Redirection to notifiable path"
@@ -111,7 +111,7 @@ module ActivityNotification
111
111
  # @todo Needs any other better implementation
112
112
  # @todo Must handle devise namespace
113
113
  def move_notification_path_for(notification, params = {})
114
- options = params.dup
114
+ options = move_notification_options(notification, params)
115
115
  options.delete(:devise_default_routes) ?
116
116
  send("move_#{routing_scope(options)}notification_path", notification, options) :
117
117
  send("move_#{routing_scope(options)}#{notification.target.to_resource_name}_notification_path", notification.target, notification, options)
@@ -195,7 +195,7 @@ module ActivityNotification
195
195
  # @todo Needs any other better implementation
196
196
  # @todo Must handle devise namespace
197
197
  def move_notification_url_for(notification, params = {})
198
- options = params.dup
198
+ options = move_notification_options(notification, params)
199
199
  options.delete(:devise_default_routes) ?
200
200
  send("move_#{routing_scope(options)}notification_url", notification, options) :
201
201
  send("move_#{routing_scope(options)}#{notification.target.to_resource_name}_notification_url", notification.target, notification, options)
@@ -553,6 +553,14 @@ module ActivityNotification
553
553
  [root, path].map(&:to_s).join('/')
554
554
  end
555
555
 
556
+ # Prepare options for move_notification path with token to open the notification
557
+ # @api private
558
+ def move_notification_options(notification, params)
559
+ options = params.dup
560
+ options[:open_token] = notification.open_token if options[:open].to_s.to_boolean(false)
561
+ options
562
+ end
563
+
556
564
  # Prepare routing scope from options
557
565
  # @api private
558
566
  def routing_scope(options = {})
@@ -1,3 +1,3 @@
1
1
  module ActivityNotification
2
- VERSION = "2.7.1"
2
+ VERSION = "2.7.2"
3
3
  end
@@ -129,4 +129,9 @@ ActivityNotification.configure do |config|
129
129
  # your application (see the :with_devise routing option). Default value is false.
130
130
  # config.restrict_api_response_fields = false
131
131
 
132
+ # Configure maximum number of records that notification and subscription index actions of the controllers return.
133
+ # The limit request parameter is capped by this value, and this value is used when the limit parameter is not specified.
134
+ # Set nil to remove the cap. Default value is 1000.
135
+ # config.max_index_limit = 1000
136
+
132
137
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activity_notification
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.1
4
+ version: 2.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shota Yamazaki