live_record 0.2.7 → 0.2.8

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
  SHA1:
3
- metadata.gz: 186f7837ba3477c89c64825de64ab23966f633f0
4
- data.tar.gz: 8a1d31b23fdbf06a16fb18e0c3460b6f90d77d6a
3
+ metadata.gz: d08ed348f467c4dad7084528d36552775a03f365
4
+ data.tar.gz: 3698f07abf6f4e6edc1430870fb8eb7ad6862bad
5
5
  SHA512:
6
- metadata.gz: 72b4f7a7ecd74ad4b4f4ad6d5f9d74ce5561d5ebaee4982a0313b3567331810a1e4bcf554d3f90b276a04a1c7b111b999f700bc178d705ebd125a4d27d63ebeb
7
- data.tar.gz: 8035a50ec324b8e19f3f143a48379ef510336ffa0f781461fa57df8e1ce0fa964f3ccb7622e1c2125fc3c1724878fdc868165a4af3cef8989af6ede5affb58a8
6
+ metadata.gz: 482a0751d39af81591ac4137fc2a8f12206fa4e687aeb5b1508c1ce60fb85fe1d92465ff853affad114017f1f97e19a859a2d39553f3d92d387d05ccc5840630
7
+ data.tar.gz: '081b8691a3f37984961031d230afa749603c9c61e402347d63a914ed854170cf6c2df561c68d8be8514e0bfc04cfc139cfbe1878573ff72fc5057a94bb0401b8'
data/README.md CHANGED
@@ -101,9 +101,9 @@
101
101
  # Add attributes to this array that you would like `current_user` to have access to when syncing this particular `book`
102
102
  # empty array means not-authorised
103
103
  if book.user == current_user
104
- [:title, :author, :created_at, :updated_at, :reference_id, :origin_address]
104
+ [:id, :title, :author, :created_at, :updated_at, :reference_id, :origin_address]
105
105
  elsif current_user.present?
106
- [:title, :author, :created_at, :updated_at]
106
+ [:id ,:title, :author, :created_at, :updated_at]
107
107
  else
108
108
  []
109
109
  end
@@ -113,7 +113,7 @@
113
113
  # Add attributes to this array that you would like `current_user` to be able to query upon on the `subscribe({where: {...}}) function`
114
114
  # empty array means not-authorised
115
115
  if current_user.isAdmin?
116
- [:title, :author, :created_at, :updated_at, :reference_id, :origin_address]
116
+ [:id, :title, :author, :created_at, :updated_at, :reference_id, :origin_address]
117
117
  else
118
118
  []
119
119
  end
@@ -127,7 +127,7 @@
127
127
  1. Add the following to your `Gemfile`:
128
128
 
129
129
  ```ruby
130
- gem 'live_record', '~> 0.2.7'
130
+ gem 'live_record', '~> 0.2.8'
131
131
  ```
132
132
 
133
133
  2. Run:
@@ -180,13 +180,13 @@
180
180
  def self.live_record_whitelisted_attributes(book, current_user)
181
181
  # Add attributes to this array that you would like current_user to have access to when syncing.
182
182
  # Defaults to empty array, thereby blocking everything by default, only unless explicitly stated here so.
183
- [:title, :author, :created_at, :updated_at]
183
+ [:id, :title, :author, :created_at, :updated_at]
184
184
  end
185
185
 
186
186
  def self.live_record_queryable_attributes(current_user)
187
187
  # Add attributes to this array that you would like current_user to query upon when using `.subscribe({where: {...})`
188
188
  # Defaults to empty array, thereby blocking everything by default, only unless explicitly stated here so.
189
- [:title, :author, :created_at, :updated_at]
189
+ [:id, :title, :author, :created_at, :updated_at]
190
190
  end
191
191
  end
192
192
  ```
@@ -203,9 +203,9 @@
203
203
  # Notice that from above, you also have access to `book` (the record currently requested by the client to be synced),
204
204
  # and the `current_user`, the current user who is trying to sync the `book` record.
205
205
  if book.user == current_user
206
- [:title, :author, :created_at, :updated_at, :reference_id, :origin_address]
206
+ [:id, :title, :author, :created_at, :updated_at, :reference_id, :origin_address]
207
207
  elsif current_user.present?
208
- [:title, :author, :created_at, :updated_at]
208
+ [:id, :title, :author, :created_at, :updated_at]
209
209
  else
210
210
  []
211
211
  end
@@ -215,7 +215,7 @@
215
215
  # this method should look like your `live_record_whitelisted_attributes` above, only except if you want to further customise this for flexibility
216
216
  # or... that you may just simply return `[]` (empty array) if you do not want to allow users to use `subscribe()`
217
217
  # also take note that this method only has `current_user` argument compared to `live_record_whitelisted_attributes` above which also has the `book` argument. This is intended for SQL performance reasons
218
- [:title, :author, :created_at, :updated_at]
218
+ [:id, :title, :author, :created_at, :updated_at]
219
219
  end
220
220
  end
221
221
  ```
@@ -439,14 +439,14 @@
439
439
  has_many :live_record_updates, as: :recordable, dependent: :destroy
440
440
 
441
441
  def self.live_record_whitelisted_attributes(book, current_user)
442
- [:title, :is_enabled]
442
+ [:id, :title, :is_enabled]
443
443
  end
444
444
 
445
445
  ## this method will be invoked when `subscribe()` is called
446
446
  ## but, you should not use this method when using `ransack` gem!
447
447
  ## ransack's methods like `ransackable_attributes` below will be invoked instead
448
448
  # def self.live_record_queryable_attributes(book, current_user)
449
- # [:title, :is_enabled]
449
+ # [:id, :title, :is_enabled]
450
450
  # end
451
451
 
452
452
  private
@@ -659,11 +659,14 @@
659
659
  * MIT
660
660
 
661
661
  ## Changelog
662
+ * 0.2.8
663
+ * You can now specify `:id` into `live_record_whitelisted_attributes` for verbosity; used to be automatically-included by default. Needed to do this otherwise there was this minor bug where `subscribe()` still receives records (having just `:id` attribute though) even when it is specified to be not-authorized.
664
+ * fixed minor bug when `live_record_whitelisted_attributes` is not returning anything, throwing a `NoMethodError`
662
665
  * 0.2.7
663
666
  * improved performance when using `subscribe({reload: true})`, but by doing so, I am forced to a conscious decision to have another separate model method for "queryable" attributes: `live_record_queryable_attributes`, which both has `pro` and `cons`
664
667
  * pros:
665
668
  * greatly sped up SQL for loading of data
666
- * pro & con: now two methods in model: `live_record_whitelisted_attributes` and `live_record_queryable_attributes` which should have mostly the same code [(see some differences above)]('#example-1---simple-usage') which makes it repetitive to some degree, although this allows more flexibility.
669
+ * pro & con: now two methods in model: `live_record_whitelisted_attributes` and `live_record_queryable_attributes` which should have mostly the same code [(see some differences above)](#example-1---simple-usage) which makes it repetitive to some degree, although this allows more flexibility.
667
670
  * added `matches` and `does_not_match` filters
668
671
  * 0.2.6
669
672
  * fixed minor bug where `MODELINSTANCE.changes` do not accurately work on NULL values.
@@ -1,13 +1,32 @@
1
1
  class LiveRecord::BaseChannel < ActionCable::Channel::Base
2
2
 
3
- protected
3
+ module Helpers
4
+ def self.whitelisted_attributes(record, current_user)
5
+ whitelisted_attributes = record.class.live_record_whitelisted_attributes(record, current_user)
6
+
7
+ unless whitelisted_attributes.is_a? Array
8
+ raise "#{record.class}.live_record_whitelisted_attributes should return an array"
9
+ end
10
+
11
+ whitelisted_attributes = whitelisted_attributes.map(&:to_s)
12
+
13
+ if !whitelisted_attributes.empty? && !whitelisted_attributes.include?('id')
14
+ raise "#{record.class}.live_record_whitelisted_attributes should return an array that also includes the :id attribute, as you are authorizing at least one other attribute along with it."
15
+ end
4
16
 
5
- def authorised_attributes(record, current_user)
6
- whitelisted_attributes = record.class.live_record_whitelisted_attributes(record, current_user)
7
- raise "#{record.model}.live_record_whitelisted_attributes should return an array" unless whitelisted_attributes.is_a? Array
8
- ([:id] + whitelisted_attributes).map(&:to_s).to_set
17
+ whitelisted_attributes.to_set
18
+ end
19
+
20
+ def self.queryable_attributes(model_class, current_user)
21
+ queryable_attributes = model_class.live_record_queryable_attributes(current_user)
22
+ raise "#{model_class}.live_record_queryable_attributes should return an array" unless queryable_attributes.is_a? Array
23
+ queryable_attributes = queryable_attributes.map(&:to_s)
24
+ queryable_attributes.to_set
25
+ end
9
26
  end
10
27
 
28
+ protected
29
+
11
30
  def filtered_message(message, filters)
12
31
  message['attributes'].slice!(*filters) if message['attributes'].present?
13
32
  message
@@ -5,20 +5,19 @@ class LiveRecord::ChangesChannel < LiveRecord::BaseChannel
5
5
 
6
6
  def subscribed
7
7
  find_record_from_params(params) do |record|
8
- authorised_attributes = authorised_attributes(record, current_user)
8
+ whitelisted_attributes = Helpers.whitelisted_attributes(record, current_user)
9
9
 
10
- if authorised_attributes.present?
10
+ if whitelisted_attributes.present?
11
11
  stream_for record, coder: ActiveSupport::JSON do |message|
12
12
  begin
13
13
  record.reload
14
14
  rescue ActiveRecord::RecordNotFound
15
15
  end
16
16
 
17
- authorised_attributes = authorised_attributes(record, current_user)
17
+ whitelisted_attributes = Helpers.whitelisted_attributes(record, current_user)
18
18
 
19
- # if not just :id
20
- if authorised_attributes.size > 1
21
- response = filtered_message(message, authorised_attributes)
19
+ if whitelisted_attributes.size > 0
20
+ response = filtered_message(message, whitelisted_attributes)
22
21
  transmit response if response.present?
23
22
  else
24
23
  respond_with_error(:forbidden)
@@ -36,10 +35,9 @@ class LiveRecord::ChangesChannel < LiveRecord::BaseChannel
36
35
  params = data.symbolize_keys
37
36
 
38
37
  find_record_from_params(params) do |record|
39
- authorised_attributes = authorised_attributes(record, current_user)
38
+ whitelisted_attributes = Helpers.whitelisted_attributes(record, current_user)
40
39
 
41
- # if not just :id
42
- if authorised_attributes.size > 1
40
+ if whitelisted_attributes.size > 0
43
41
  live_record_updates = nil
44
42
 
45
43
  if params[:stale_since].present?
@@ -55,7 +53,7 @@ class LiveRecord::ChangesChannel < LiveRecord::BaseChannel
55
53
  # then we update the record in the client-side
56
54
  if params[:stale_since].blank? || live_record_updates.exists?
57
55
  message = { 'action' => 'update', 'attributes' => record.attributes }
58
- response = filtered_message(message, authorised_attributes)
56
+ response = filtered_message(message, whitelisted_attributes)
59
57
  transmit response if response.present?
60
58
  end
61
59
  else
@@ -14,7 +14,7 @@ class LiveRecord::PublicationsChannel < LiveRecord::BaseChannel
14
14
  reject_subscription
15
15
  end
16
16
 
17
- if !(model_class && model_class.live_record_queryable_attributes(current_user).present?)
17
+ if !(model_class && Helpers.queryable_attributes(model_class, current_user).present?)
18
18
  respond_with_error(:forbidden, 'You do not have privileges to query')
19
19
  reject_subscription
20
20
  end
@@ -29,11 +29,11 @@ class LiveRecord::PublicationsChannel < LiveRecord::BaseChannel
29
29
  )
30
30
 
31
31
  if active_record_relation.exists?(id: newly_created_record.id)
32
- @authorised_attributes ||= authorised_attributes(newly_created_record, current_user)
33
- # if not just :id
34
- if @authorised_attributes.size > 1
32
+ whitelisted_attributes = Helpers.whitelisted_attributes(newly_created_record, current_user)
33
+
34
+ if whitelisted_attributes.size > 0
35
35
  message = { 'action' => 'create', 'attributes' => message['attributes'] }
36
- response = filtered_message(message, @authorised_attributes)
36
+ response = filtered_message(message, whitelisted_attributes)
37
37
  transmit response if response.present?
38
38
  end
39
39
  end
@@ -61,11 +61,13 @@ class LiveRecord::PublicationsChannel < LiveRecord::BaseChannel
61
61
  # we `transmmit` a message back to client for each matching record
62
62
  active_record_relation.find_each do |record|
63
63
  # but first, check for the authorised attributes, if exists
64
- current_authorised_attributes = authorised_attributes(record, current_user)
64
+ whitelisted_attributes = Helpers.whitelisted_attributes(record, current_user)
65
65
 
66
- message = { 'action' => 'create', 'attributes' => record.attributes }
67
- response = filtered_message(message, current_authorised_attributes)
68
- transmit response if response.present?
66
+ if whitelisted_attributes.size > 0
67
+ message = { 'action' => 'create', 'attributes' => record.attributes }
68
+ response = filtered_message(message, whitelisted_attributes)
69
+ transmit response if response.present?
70
+ end
69
71
  end
70
72
  else
71
73
  respond_with_error(:bad_request, 'Not a correct model name')
@@ -28,12 +28,12 @@ class LiveRecord::PublicationsChannel
28
28
  current_user = args.fetch(:current_user)
29
29
 
30
30
  current_active_record_relation = model_class.all
31
- queryable_attributes = model_class.live_record_queryable_attributes(current_user)
31
+ queryable_attributes = LiveRecord::BaseChannel::Helpers.queryable_attributes(model_class, current_user)
32
32
 
33
33
  conditions_hash.each do |key, value|
34
34
  operator = key.split('_').last
35
35
  # to get attribute_name, we subtract the end part of the string with size of operator substring; i.e.: created_at_lteq -> created_at
36
- attribute_name = key[0..(-1 - operator.size - 1)].to_sym
36
+ attribute_name = key[0..(-1 - operator.size - 1)]
37
37
 
38
38
  if queryable_attributes.include?(attribute_name)
39
39
  case operator
@@ -20,7 +20,7 @@ class <%= class_name %> < <%= parent_class_name.classify %>
20
20
  # then only these whitelisted attributes will be sent to this current_user client
21
21
  # Empty array means unauthorized
22
22
  # Example:
23
- # [:email, :name, :is_admin, :group_id, :created_at, :updated_at]
23
+ # [:id, :email, :name, :is_admin, :group_id, :created_at, :updated_at]
24
24
  []
25
25
  end
26
26
 
@@ -36,7 +36,7 @@ class <%= class_name %> < <%= parent_class_name.classify %>
36
36
  # if you're using `ransack` gem, use `ransackable_attributes`
37
37
  # Empty array means unauthorized
38
38
  # Example:
39
- # [:email, :name, :is_admin, :group_id, :created_at, :updated_at]
39
+ # [:id, :email, :name, :is_admin, :group_id, :created_at, :updated_at]
40
40
  []
41
41
  end
42
42
  end
@@ -1,3 +1,3 @@
1
1
  module LiveRecord
2
- VERSION = '0.2.7'.freeze
2
+ VERSION = '0.2.8'.freeze
3
3
  end
@@ -5,29 +5,10 @@ class Post < ApplicationRecord
5
5
  has_many :live_record_updates, as: :recordable, dependent: :destroy
6
6
 
7
7
  def self.live_record_whitelisted_attributes(post, current_user)
8
- # Add attributes to this array that you would like current_user client to be able to receive
9
- # Defaults to empty array, thereby blocking everything by default, only unless explicitly stated here so.
10
- # i.e. if this file is a User model, and that a User has been created/updated in the backend,
11
- # then only these whitelisted attributes will be sent to this current_user client
12
- # Empty array means unauthorized
13
- # Example:
14
- # [:email, :name, :is_admin, :group_id, :created_at, :updated_at]
15
- [:title, :is_enabled, :user_id, :created_at, :updated_at]
8
+ [:id, :title, :is_enabled, :user_id, :created_at, :updated_at]
16
9
  end
17
10
 
18
11
  def self.live_record_queryable_attributes(current_user)
19
- # This method only applies when not using `ransack` gem!
20
- # If you're using ransack gem, instead of this method, use one or more of the ransack methods:
21
- # see https://github.com/activerecord-hackery/ransack#authorization-whitelistingblacklisting
22
- #
23
- # Add attributes to this array that you would like current_user client to be able to query upon when "subscribing"
24
- # Defaults to empty array, thereby blocking everything by default, only unless explicitly stated here so.
25
- # i.e. if a current_user client subscribes to "new records creation" using `.subscribe({where: {...}})`,
26
- # then only these attributes will be considered in the "{where: ...}" argument
27
- # if you're using `ransack` gem, use `ransackable_attributes`
28
- # Empty array means unauthorized
29
- # Example:
30
- # [:email, :name, :is_admin, :group_id, :created_at, :updated_at]
31
- [:title, :is_enabled, :user_id, :created_at, :updated_at]
12
+ [:id, :title, :is_enabled, :user_id, :created_at, :updated_at]
32
13
  end
33
14
  end
@@ -5,9 +5,7 @@ class User < ApplicationRecord
5
5
  has_many :posts
6
6
 
7
7
  def self.live_record_whitelisted_attributes(user, current_user)
8
- # Add attributes to this array that you would like current_user to have access to.
9
- # Defaults to empty array, thereby blocking everything by default, only unless explicitly stated here so.
10
- [:email, :created_at, :updated_at]
8
+ [:id, :email, :created_at, :updated_at]
11
9
  end
12
10
 
13
11
  def self.live_record_queryable_attributes(current_user)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: live_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jules Roman B. Polidario