dexiecable 2.0.0.alpha4 → 2.0.0.alpha5

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: 502a99e32deef9551c55b8cb0bdae2e2d74af751e4f9889543f76ceea6d5a2ce
4
- data.tar.gz: f42e9bca1c1d05ef287b3b72373e7c264af8ab78c350c092b8ccd9f887aa0270
3
+ metadata.gz: 16d440593b555940ff8039e04091edf54026d8678183acfb5d56b6189b08560c
4
+ data.tar.gz: 78c9c8e4b7e8e9cd3ae3d8cb7367b040962ef7ea0149d167a20396c58093a938
5
5
  SHA512:
6
- metadata.gz: 37dc5d8afc9449875b3074c2684856ebb5d1f29e44a0c8d83558d061cf96baa270b8e5d1ad2a35a17bd01363b25956ec2946aead6929c3c465bee447a0c5d8d8
7
- data.tar.gz: 7c370e6be94b70a65c63cf8bd47bb762b353df0ce0e964cd0f68b256703514c6a790124605a973008595358976319f9d6fdb3876fd5cfc97eeba65a8b5902642
6
+ metadata.gz: d1d15766bb5dde84e8aaac57998da45e3dc88665740c6beb333d12dafddb3115b148b4e3b49ec8badf706d898eaba1c6fd7c8ad33e77b2aa60083b6b6e3b3a88
7
+ data.tar.gz: c716de1ee2d50979513c911b168879da8fc640d49f85ddd288ad70715197691c35ffb9020872a2250ae00a62fb35909214a501f91cdeb458323d31cb201bf511
data/README.md CHANGED
@@ -88,11 +88,17 @@ Stream tokens are signed with the application secret, so a client can only subsc
88
88
  DexieChannel.stream_token_for(target)
89
89
  ```
90
90
 
91
- For an ActiveRecord model it signs the record's GlobalID:
91
+ For an ActiveRecord model it returns a signed GlobalID (Rails' `signed_id`):
92
92
 
93
93
  ```ruby
94
94
  DexieChannel.stream_token_for(current_user)
95
- # => "signed token for gid://app/User/1"
95
+ # => "signed global id"
96
+ ```
97
+
98
+ Tokens never expire by default. Pass `expires_in:` or `expires_at:` to limit a token's lifetime:
99
+
100
+ ```ruby
101
+ DexieChannel.stream_token_for(current_user, expires_in: 1.day)
96
102
  ```
97
103
 
98
104
  Send that token to the client (render it in a view, return it from an endpoint, etc.) and add it to the subscription:
@@ -123,13 +129,16 @@ Add custom actions or push initial data directly on your channel:
123
129
  class DexieChannel < ApplicationCable::Channel
124
130
  include DexieCable
125
131
 
126
- # Push a snapshot when a private stream is added.
132
+ # Push a snapshot when a stream is added. `record` is a record for private
133
+ # streams, or the stream name (String) for public streams.
127
134
  def subscribed_to(record, params)
128
135
  case record
129
136
  when User
130
137
  table("notifications").bulkAdd(record.notifications.map(&:as_json_for_dexie))
131
138
  when Conversation
132
139
  table("messages").bulkAdd(record.messages.where("seq_id > ?", params[:last_seq_id]).map(&:as_json_for_dexie))
140
+ when String
141
+ table(record).bulkAdd(Announcement.for_stream(record).map(&:as_json_for_dexie))
133
142
  end
134
143
  end
135
144
 
@@ -25,6 +25,7 @@ module DexieCable
25
25
  extend ActiveSupport::Concern
26
26
 
27
27
  PUBLIC_STREAM_PREFIX = "public:"
28
+ STREAM_TOKEN_PURPOSE = "dexiecable:streams"
28
29
 
29
30
  included do
30
31
  public :transmit
@@ -40,15 +41,23 @@ module DexieCable
40
41
  ScopedChannel.new(self, target)
41
42
  end
42
43
 
43
- # Returns a signed token for +target+ (a record or other private
44
- # target). Send it to the client, which passes it to
45
- # +subscription.addStream+.
46
- def stream_token_for(target)
47
- verifier.generate(target.respond_to?(:to_gid_param) ? target.to_gid_param : target.to_s)
48
- end
49
-
50
- def verifier
51
- @verifier ||= Rails.application.message_verifier("dexiecable:streams")
44
+ # Returns a signed token for +target+ (a record). Send it to the client,
45
+ # which passes it to +subscription.addStream+.
46
+ #
47
+ # Tokens never expire by default. Pass +expires_in:+ (a duration) or
48
+ # +expires_at:+ (a time) to limit a token's lifetime.
49
+ def stream_token_for(target, expires_at: nil, expires_in: nil)
50
+ options = { for: STREAM_TOKEN_PURPOSE }
51
+
52
+ if expires_at
53
+ options[:expires_at] = expires_at
54
+ elsif expires_in
55
+ options[:expires_in] = expires_in
56
+ else
57
+ options[:expires_at] = nil # never expire
58
+ end
59
+
60
+ target.to_sgid_param(**options)
52
61
  end
53
62
  end
54
63
 
@@ -63,19 +72,19 @@ module DexieCable
63
72
  end
64
73
 
65
74
  def add_stream(data)
66
- target = verified_target(data["stream"])
67
- return unless target
75
+ record = resolve_subscribe_target(data["stream"])
76
+ return unless record
68
77
 
69
- stream_for target
78
+ stream_for record
70
79
  params = data.except("action", "stream").with_indifferent_access
71
- subscribed_to(resolve_subscribe_target(target), params)
80
+ subscribed_to(record, params)
72
81
  end
73
82
 
74
83
  def remove_stream(data)
75
- target = verified_target(data["stream"])
76
- return unless target
84
+ record = resolve_subscribe_target(data["stream"])
85
+ return unless record
77
86
 
78
- stop_stream_from self.class.broadcasting_for(target)
87
+ stop_stream_from self.class.broadcasting_for(record)
79
88
  end
80
89
 
81
90
  def remove_all_streams(_data)
@@ -84,7 +93,11 @@ module DexieCable
84
93
 
85
94
  def add_public_stream(data)
86
95
  name = data["stream"].to_s
87
- stream_from public_stream_name(name) if name.present?
96
+ return if name.blank?
97
+
98
+ stream_from public_stream_name(name)
99
+ params = data.except("action", "stream").with_indifferent_access
100
+ subscribed_to(name, params)
88
101
  end
89
102
 
90
103
  def remove_public_stream(data)
@@ -92,9 +105,9 @@ module DexieCable
92
105
  stop_stream_from public_stream_name(name) if name.present?
93
106
  end
94
107
 
95
- # Override to push initial data when a private stream is added. +record+
96
- # is the resolved target and +params+ are any extra params sent from the
97
- # client.
108
+ # Override to push initial data when a stream is added. +record+ is the
109
+ # resolved target a record for private streams, or the stream name for
110
+ # public streams — and +params+ are any extra params sent from the client.
98
111
  def subscribed_to(_record, _params)
99
112
  end
100
113
 
@@ -104,15 +117,9 @@ module DexieCable
104
117
  self.class.broadcasting_for("#{PUBLIC_STREAM_PREFIX}#{name}")
105
118
  end
106
119
 
107
- def verified_target(token)
108
- return unless token.present?
109
-
110
- self.class.verifier.verify(token)
111
- rescue ActiveSupport::MessageVerifier::InvalidSignature
120
+ def resolve_subscribe_target(token)
121
+ GlobalID::Locator.locate_signed(token, for: STREAM_TOKEN_PURPOSE)
122
+ rescue ActiveRecord::RecordNotFound, NameError
112
123
  nil
113
124
  end
114
-
115
- def resolve_subscribe_target(target)
116
- target.start_with?("gid://") ? GlobalID::Locator.locate(target) : target
117
- end
118
125
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DexieCable
4
- VERSION = "2.0.0.alpha4"
4
+ VERSION = "2.0.0.alpha5"
5
5
  end
data/lib/dexiecable.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "dexiecable/version"
4
+ require "global_id/railtie" if defined?(Rails::Railtie)
4
5
  require_relative "dexiecable/concern"
5
6
  require_relative "dexiecable/scoped_channel"
6
7
  require_relative "dexiecable/query"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dexiecable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.alpha4
4
+ version: 2.0.0.alpha5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Buhrmester
@@ -37,6 +37,20 @@ dependencies:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
39
  version: '7.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: globalid
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0.6'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0.6'
40
54
  description: DexieCable augments ActionCable channels with a query DSL that mirrors
41
55
  the Dexie.js API, letting you push database mutations from the server to the client
42
56
  in real time. Includes an ActiveRecord macro (syncs_to_dexie) for automatic change