Module: ExpoTurbo::Rails::Cable

Defined in:
lib/expo_turbo/rails/cable.rb,
lib/expo_turbo/rails/cable/connection.rb,
lib/expo_turbo/rails/cable/configuration.rb,
lib/expo_turbo/rails/cable/protected_broadcast_job.rb,
lib/expo_turbo/rails/cable/protected_streams_channel.rb

Defined Under Namespace

Modules: Connection Classes: Configuration, ProtectedBroadcastJob, ProtectedStreamsChannel

Constant Summary collapse

PROTECTED_STREAM_VERIFIER_NAME =
"expo_turbo/protected_stream"
PROTECTED_STREAM_PURPOSE =
"expo_turbo.protected_stream"

Class Method Summary collapse

Class Method Details

.broadcast_protected_later_to(*streamables, content:) ⇒ Object



53
54
55
56
57
58
# File 'lib/expo_turbo/rails/cable.rb', line 53

def broadcast_protected_later_to(*streamables, content:)
  ProtectedBroadcastJob.perform_later(
    protected_stream_token_for(*streamables),
    content: Streams.valid_content!(content)
  )
end

.broadcast_protected_to(*streamables, content:) ⇒ Object



49
50
51
# File 'lib/expo_turbo/rails/cable.rb', line 49

def broadcast_protected_to(*streamables, content:)
  broadcast_to_protected_token(protected_stream_token_for(*streamables), content:)
end

.broadcast_to_protected_token(token, content:) ⇒ Object



60
61
62
63
64
65
66
# File 'lib/expo_turbo/rails/cable.rb', line 60

def broadcast_to_protected_token(token, content:)
  unless verified_protected_stream_name(token)
    raise ArgumentError, "protected stream token must be a valid Expo Turbo protected stream token"
  end

  ::Turbo::StreamsChannel.broadcast_stream_to(token, content: Streams.valid_content!(content))
end

.configurationObject



28
29
30
31
32
33
# File 'lib/expo_turbo/rails/cable.rb', line 28

def configuration
  @configuration || raise(
    ConfigurationError,
    "configure ExpoTurbo::Rails::Cable before rendering or accepting protected Expo Turbo subscriptions"
  )
end

.configure(credential_extractor:, subject_resolver:, subscription_authorizer:, subscription_error_reporter:) ⇒ Object



15
16
17
18
19
20
21
22
# File 'lib/expo_turbo/rails/cable.rb', line 15

def configure(credential_extractor:, subject_resolver:, subscription_authorizer:, subscription_error_reporter:)
  @configuration = Configuration.new(
    credential_extractor:,
    subject_resolver:,
    subscription_authorizer:,
    subscription_error_reporter:
  )
end

.configured?Boolean

Returns:

  • (Boolean)


24
25
26
# File 'lib/expo_turbo/rails/cable.rb', line 24

def configured?
  defined?(@configuration)
end

.protected_stream_token_for(*streamables) ⇒ Object



35
36
37
38
39
40
# File 'lib/expo_turbo/rails/cable.rb', line 35

def protected_stream_token_for(*streamables)
  protected_stream_verifier.generate(
    Streams.stream_name_for(*streamables),
    purpose: PROTECTED_STREAM_PURPOSE
  ).encode(Encoding::UTF_8)
end

.report_subscription_error(code:, error:) ⇒ Object



77
78
79
80
81
# File 'lib/expo_turbo/rails/cable.rb', line 77

def report_subscription_error(code:, error:)
  configuration.subscription_error_reporter.call(code:, error_class: error.class.name)
rescue
  # A failing observer must not make Action Cable log a descriptor containing the client-visible grant.
end

.resolve_subject(connection) ⇒ Object



68
69
70
71
# File 'lib/expo_turbo/rails/cable.rb', line 68

def resolve_subject(connection)
  credential = configuration.credential_extractor.call(connection)
  configuration.subject_resolver.call(credential)
end

.subscription_authorized?(subject:, stream_name:, grant:) ⇒ Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/expo_turbo/rails/cable.rb', line 73

def subscription_authorized?(subject:, stream_name:, grant:)
  configuration.subscription_authorizer.call(subject:, stream_name:, grant:) == true
end

.verified_protected_stream_name(token) ⇒ Object



42
43
44
45
46
47
# File 'lib/expo_turbo/rails/cable.rb', line 42

def verified_protected_stream_name(token)
  return unless valid_token?(token)

  stream_name = protected_stream_verifier.verified(token, purpose: PROTECTED_STREAM_PURPOSE)
  stream_name if Streams.valid_stream_name?(stream_name)
end