ably-pubsub-core 0.0.1.pre
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 +7 -0
- data/lib/ably/agent.rb +8 -0
- data/lib/ably/auth.rb +791 -0
- data/lib/ably/exceptions.rb +169 -0
- data/lib/ably/logger.rb +119 -0
- data/lib/ably/models/auth_details.rb +45 -0
- data/lib/ably/models/channel_details.rb +69 -0
- data/lib/ably/models/channel_metrics.rb +107 -0
- data/lib/ably/models/channel_occupancy.rb +50 -0
- data/lib/ably/models/channel_options.rb +120 -0
- data/lib/ably/models/channel_state_change.rb +84 -0
- data/lib/ably/models/channel_status.rb +63 -0
- data/lib/ably/models/cipher_params.rb +137 -0
- data/lib/ably/models/connection_details.rb +149 -0
- data/lib/ably/models/connection_state_change.rb +83 -0
- data/lib/ably/models/delta_extras.rb +28 -0
- data/lib/ably/models/device_details.rb +126 -0
- data/lib/ably/models/device_push_details.rb +94 -0
- data/lib/ably/models/error_info.rb +104 -0
- data/lib/ably/models/http_paginated_response.rb +112 -0
- data/lib/ably/models/idiomatic_ruby_wrapper.rb +235 -0
- data/lib/ably/models/message.rb +223 -0
- data/lib/ably/models/message_encoders/base.rb +135 -0
- data/lib/ably/models/message_encoders/base64.rb +40 -0
- data/lib/ably/models/message_encoders/cipher.rb +84 -0
- data/lib/ably/models/message_encoders/json.rb +34 -0
- data/lib/ably/models/message_encoders/utf8.rb +26 -0
- data/lib/ably/models/nil_logger.rb +20 -0
- data/lib/ably/models/paginated_result.rb +201 -0
- data/lib/ably/models/presence_message.rb +244 -0
- data/lib/ably/models/protocol_message.rb +288 -0
- data/lib/ably/models/push_channel_subscription.rb +114 -0
- data/lib/ably/models/stats.rb +242 -0
- data/lib/ably/models/stats_types.rb +107 -0
- data/lib/ably/models/token_details.rb +148 -0
- data/lib/ably/models/token_request.rb +180 -0
- data/lib/ably/modules/ably.rb +26 -0
- data/lib/ably/modules/async_wrapper.rb +69 -0
- data/lib/ably/modules/channels_collection.rb +105 -0
- data/lib/ably/modules/conversions.rb +153 -0
- data/lib/ably/modules/encodeable.rb +111 -0
- data/lib/ably/modules/enum.rb +230 -0
- data/lib/ably/modules/event_emitter.rb +200 -0
- data/lib/ably/modules/event_machine_helpers.rb +26 -0
- data/lib/ably/modules/exception_codes.rb +128 -0
- data/lib/ably/modules/http_helpers.rb +41 -0
- data/lib/ably/modules/message_emitter.rb +78 -0
- data/lib/ably/modules/message_pack.rb +14 -0
- data/lib/ably/modules/model_common.rb +84 -0
- data/lib/ably/modules/safe_deferrable.rb +83 -0
- data/lib/ably/modules/safe_yield.rb +41 -0
- data/lib/ably/modules/state_emitter.rb +181 -0
- data/lib/ably/modules/state_machine.rb +59 -0
- data/lib/ably/modules/statesman_monkey_patch.rb +33 -0
- data/lib/ably/modules/uses_state_machine.rb +111 -0
- data/lib/ably/realtime/auth.rb +283 -0
- data/lib/ably/realtime/channel/channel_manager.rb +272 -0
- data/lib/ably/realtime/channel/channel_properties.rb +40 -0
- data/lib/ably/realtime/channel/channel_state_machine.rb +104 -0
- data/lib/ably/realtime/channel/publisher.rb +82 -0
- data/lib/ably/realtime/channel/push_channel.rb +69 -0
- data/lib/ably/realtime/channel.rb +440 -0
- data/lib/ably/realtime/channels.rb +71 -0
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +225 -0
- data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +87 -0
- data/lib/ably/realtime/client.rb +363 -0
- data/lib/ably/realtime/connection/connection_manager.rb +594 -0
- data/lib/ably/realtime/connection/connection_state_machine.rb +144 -0
- data/lib/ably/realtime/connection/websocket_transport.rb +287 -0
- data/lib/ably/realtime/connection.rb +738 -0
- data/lib/ably/realtime/models/nil_channel.rb +30 -0
- data/lib/ably/realtime/presence/members_map.rb +395 -0
- data/lib/ably/realtime/presence/presence_manager.rb +78 -0
- data/lib/ably/realtime/presence/presence_state_machine.rb +57 -0
- data/lib/ably/realtime/presence.rb +502 -0
- data/lib/ably/realtime/push/admin.rb +75 -0
- data/lib/ably/realtime/push/channel_subscriptions.rb +108 -0
- data/lib/ably/realtime/push/device_registrations.rb +105 -0
- data/lib/ably/realtime/push.rb +25 -0
- data/lib/ably/realtime/recovery_key_context.rb +36 -0
- data/lib/ably/realtime.rb +60 -0
- data/lib/ably/rest/channel/push_channel.rb +59 -0
- data/lib/ably/rest/channel.rb +194 -0
- data/lib/ably/rest/channels.rb +47 -0
- data/lib/ably/rest/client.rb +727 -0
- data/lib/ably/rest/middleware/encoder.rb +49 -0
- data/lib/ably/rest/middleware/exceptions.rb +53 -0
- data/lib/ably/rest/middleware/external_exceptions.rb +24 -0
- data/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +22 -0
- data/lib/ably/rest/middleware/logger.rb +58 -0
- data/lib/ably/rest/middleware/parse_json.rb +27 -0
- data/lib/ably/rest/middleware/parse_message_pack.rb +43 -0
- data/lib/ably/rest/presence.rb +113 -0
- data/lib/ably/rest/push/admin.rb +58 -0
- data/lib/ably/rest/push/channel_subscriptions.rb +121 -0
- data/lib/ably/rest/push/device_registrations.rb +114 -0
- data/lib/ably/rest/push.rb +25 -0
- data/lib/ably/rest.rb +40 -0
- data/lib/ably/util/ably_extensions.rb +29 -0
- data/lib/ably/util/crypto.rb +134 -0
- data/lib/ably/util/pub_sub.rb +45 -0
- data/lib/ably/util/safe_deferrable.rb +44 -0
- data/lib/ably/version.rb +7 -0
- data/lib/ably.rb +16 -0
- metadata +497 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'statesman'
|
|
2
|
+
require 'ably/modules/statesman_monkey_patch'
|
|
3
|
+
|
|
4
|
+
module Ably::Modules
|
|
5
|
+
# Module providing Statesman StateMachine functionality
|
|
6
|
+
#
|
|
7
|
+
# Expects method #logger to be defined
|
|
8
|
+
#
|
|
9
|
+
# @api private
|
|
10
|
+
module StateMachine
|
|
11
|
+
def self.included(klass)
|
|
12
|
+
klass.class_eval do
|
|
13
|
+
include Statesman::Machine
|
|
14
|
+
end
|
|
15
|
+
klass.extend Ably::Modules::StatesmanMonkeyPatch
|
|
16
|
+
klass.extend ClassMethods
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Alternative to Statesman's #transition_to that:
|
|
20
|
+
# * log state change failures to {Logger}
|
|
21
|
+
#
|
|
22
|
+
# @return [void]
|
|
23
|
+
#
|
|
24
|
+
def transition_state(state, *args)
|
|
25
|
+
unless result = transition_to(state.to_sym, *args)
|
|
26
|
+
exception = exception_for_state_change_to(state)
|
|
27
|
+
logger.fatal { "#{self.class}: #{exception.message}\n#{caller[0..20].join("\n")}" }
|
|
28
|
+
end
|
|
29
|
+
result
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @return [Statesman History Object]
|
|
33
|
+
#
|
|
34
|
+
def previous_transition
|
|
35
|
+
history[-2]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @return [Symbol]
|
|
39
|
+
#
|
|
40
|
+
def previous_state
|
|
41
|
+
previous_transition.to_state if previous_transition
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @return [Ably::Exceptions::InvalidStateChange]
|
|
45
|
+
#
|
|
46
|
+
def exception_for_state_change_to(state)
|
|
47
|
+
error_message = "#{self.class}: Unable to transition from #{current_state} => #{state}"
|
|
48
|
+
Ably::Exceptions::InvalidStateChange.new(error_message, nil, Ably::Exceptions::Codes::CHANNEL_OPERATION_FAILED_INVALID_CHANNEL_STATE)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
module ClassMethods
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def is_error_type?(error)
|
|
55
|
+
error.kind_of?(Ably::Models::ErrorInfo) || error.kind_of?(StandardError)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Ably::Modules
|
|
2
|
+
# @api private
|
|
3
|
+
module StatesmanMonkeyPatch
|
|
4
|
+
# Override Statesman's #before_transition to support :from arrays
|
|
5
|
+
# This can be removed once https://github.com/gocardless/statesman/issues/95 is solved
|
|
6
|
+
def before_transition(options = nil, &block)
|
|
7
|
+
arrayify_transition(options) do |options_without_from_array|
|
|
8
|
+
super(*options_without_from_array, &block)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Override Statesman's #after_transition to support :from arrays
|
|
13
|
+
# This can be removed once https://github.com/gocardless/statesman/issues/95 is solved
|
|
14
|
+
def after_transition(options = nil, &block)
|
|
15
|
+
arrayify_transition(options) do |options_without_from_array|
|
|
16
|
+
super(*options_without_from_array, &block)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
def arrayify_transition(options, &block)
|
|
22
|
+
if options.nil?
|
|
23
|
+
yield []
|
|
24
|
+
elsif options.fetch(:from, nil).kind_of?(Array)
|
|
25
|
+
options[:from].each do |from_state|
|
|
26
|
+
yield [options.merge(from: from_state)]
|
|
27
|
+
end
|
|
28
|
+
else
|
|
29
|
+
yield [options]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
module Ably::Modules
|
|
2
|
+
# Mixing module that assists with {https://github.com/gocardless/statesman Statemans State Machine} state transitions
|
|
3
|
+
# and maintaining state of this object's #state.
|
|
4
|
+
#
|
|
5
|
+
# Expects:
|
|
6
|
+
# - @state_machine is set to the StateMachine
|
|
7
|
+
# - StateEmitter is included in the object
|
|
8
|
+
#
|
|
9
|
+
module UsesStateMachine
|
|
10
|
+
extend Forwardable
|
|
11
|
+
|
|
12
|
+
# Call #transition_to on the StateMachine
|
|
13
|
+
#
|
|
14
|
+
# @return [Boolean] true if new_state can be transitioned to by state machine
|
|
15
|
+
# @api private
|
|
16
|
+
def transition_state_machine(new_state, emit_params = {})
|
|
17
|
+
state_machine.transition_state(new_state, emit_object(new_state, emit_params))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Call #transition_to! on the StateMachine
|
|
21
|
+
# An exception wil be raised if new_state cannot be transitioned to by state machine
|
|
22
|
+
#
|
|
23
|
+
# @return [void]
|
|
24
|
+
# @api private
|
|
25
|
+
def transition_state_machine!(new_state, emit_params = {})
|
|
26
|
+
state_machine.transition_to!(new_state, emit_object(new_state, emit_params))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Provides an internal method for this object's state to match the StateMachine's current state.
|
|
30
|
+
# The current object's state will be changed to the StateMachine state and will emit an event
|
|
31
|
+
# @api private
|
|
32
|
+
def synchronize_state_with_statemachine(*args)
|
|
33
|
+
log_state_machine_state_change
|
|
34
|
+
change_state state_machine.current_state, state_machine.last_transition.metadata
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @!attribute [r] previous_state
|
|
38
|
+
# @return [STATE,nil] The previous state for this connection
|
|
39
|
+
# @api private
|
|
40
|
+
def previous_state
|
|
41
|
+
if state_machine.previous_state
|
|
42
|
+
STATE(state_machine.previous_state)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @!attribute [r] state_history
|
|
47
|
+
# @return [Array<Hash>] All previous states including the current state in date ascending order with Hash properties :state, :metadata, :transitioned_at
|
|
48
|
+
# @api private
|
|
49
|
+
def state_history
|
|
50
|
+
state_machine.history.map do |transition|
|
|
51
|
+
{
|
|
52
|
+
state: STATE(transition.to_state),
|
|
53
|
+
metadata: transition.metadata,
|
|
54
|
+
transitioned_at: transition.created_at
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def_delegators :state_machine, :can_transition_to?
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
def state_machine
|
|
63
|
+
@state_machine
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def_delegators :state_machine, :exception_for_state_change_to
|
|
67
|
+
|
|
68
|
+
def log_state_machine_state_change
|
|
69
|
+
if state_machine.previous_state
|
|
70
|
+
logger.debug { "#{self.class.name}: Transitioned from #{state_machine.previous_state} => #{state_machine.current_state}" }
|
|
71
|
+
else
|
|
72
|
+
logger.debug { "#{self.class.name}: Transitioned to #{state_machine.current_state}" }
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def emit_object(new_state, emit_params)
|
|
77
|
+
if self.class.emits_klass
|
|
78
|
+
self.class.emits_klass.new((emit_params || {}).merge(
|
|
79
|
+
current: STATE(new_state),
|
|
80
|
+
previous: STATE(state_machine.current_state),
|
|
81
|
+
event: EVENT(new_state)
|
|
82
|
+
))
|
|
83
|
+
else
|
|
84
|
+
emit_params
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def self.included(base)
|
|
89
|
+
base.extend(ClassMethods)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
module ClassMethods
|
|
93
|
+
def emits_klass
|
|
94
|
+
@emits_klass ||= if defined?(@emits_klass_name) && @emits_klass_name
|
|
95
|
+
get_const(@emits_klass_name)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def ensure_state_machine_emits(klass)
|
|
100
|
+
@emits_klass_name = klass
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def get_const(klass_name)
|
|
104
|
+
klass_names = klass_name.split('::')
|
|
105
|
+
klass_names.inject(Kernel) do |klass, name|
|
|
106
|
+
klass.const_get(name)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
require 'ably/auth'
|
|
2
|
+
|
|
3
|
+
module Ably
|
|
4
|
+
module Realtime
|
|
5
|
+
# Auth is responsible for authentication with {https://www.ably.com Ably} using basic or token authentication
|
|
6
|
+
# This {Ably::Realtime::Auth Realtime::Auth} class wraps the {Ably::Auth Synchronous Ably::Auth} class in an EventMachine friendly way using Deferrables for all IO. See {Ably::Auth Ably::Auth} for more information
|
|
7
|
+
#
|
|
8
|
+
# Find out more about Ably authentication at: https://www.ably.com/docs/general/authentication/
|
|
9
|
+
#
|
|
10
|
+
# @!attribute [r] client_id
|
|
11
|
+
# (see Ably::Auth#client_id)
|
|
12
|
+
# @!attribute [r] current_token_details
|
|
13
|
+
# (see Ably::Auth#current_token_details)
|
|
14
|
+
# @!attribute [r] token
|
|
15
|
+
# (see Ably::Auth#token)
|
|
16
|
+
# @!attribute [r] key
|
|
17
|
+
# (see Ably::Auth#key)
|
|
18
|
+
# @!attribute [r] key_name
|
|
19
|
+
# (see Ably::Auth#key_name)
|
|
20
|
+
# @!attribute [r] key_secret
|
|
21
|
+
# (see Ably::Auth#key_secret)
|
|
22
|
+
# @!attribute [r] options
|
|
23
|
+
# (see Ably::Auth#options)
|
|
24
|
+
# @!attribute [r] token_params
|
|
25
|
+
# (see Ably::Auth#options)
|
|
26
|
+
# @!attribute [r] using_basic_auth?
|
|
27
|
+
# (see Ably::Auth#using_basic_auth?)
|
|
28
|
+
# @!attribute [r] using_token_auth?
|
|
29
|
+
# (see Ably::Auth#using_token_auth?)
|
|
30
|
+
# @!attribute [r] token_renewable?
|
|
31
|
+
# (see Ably::Auth#token_renewable?)
|
|
32
|
+
# @!attribute [r] authentication_security_requirements_met?
|
|
33
|
+
# (see Ably::Auth#authentication_security_requirements_met?)
|
|
34
|
+
#
|
|
35
|
+
class Auth
|
|
36
|
+
extend Forwardable
|
|
37
|
+
include Ably::Modules::AsyncWrapper
|
|
38
|
+
|
|
39
|
+
def_delegators :auth_sync, :client_id
|
|
40
|
+
def_delegators :auth_sync, :token_client_id_allowed?, :configure_client_id, :client_id_validated?
|
|
41
|
+
def_delegators :auth_sync, :can_assume_client_id?, :has_client_id?
|
|
42
|
+
def_delegators :auth_sync, :current_token_details, :token
|
|
43
|
+
def_delegators :auth_sync, :key, :key_name, :key_secret, :options, :auth_options, :token_params
|
|
44
|
+
def_delegators :auth_sync, :using_basic_auth?, :using_token_auth?
|
|
45
|
+
def_delegators :auth_sync, :token_renewable?, :authentication_security_requirements_met?
|
|
46
|
+
def_delegators :client, :logger
|
|
47
|
+
def_delegators :client, :connection
|
|
48
|
+
|
|
49
|
+
def initialize(client)
|
|
50
|
+
@client = client
|
|
51
|
+
@auth_sync = client.rest_client.auth
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# For new connections, ensures valid auth credentials are present for the library instance. This may rely on an already-known and valid token, and will obtain a new token if necessary.
|
|
55
|
+
# If a connection is already established, the connection will be upgraded with a new token
|
|
56
|
+
#
|
|
57
|
+
# In the event that a new token request is made, the provided options are used
|
|
58
|
+
#
|
|
59
|
+
# @param (see Ably::Auth#authorize)
|
|
60
|
+
# @option (see Ably::Auth#authorize)
|
|
61
|
+
#
|
|
62
|
+
# @return [Ably::Util::SafeDeferrable]
|
|
63
|
+
# @yield [Ably::Models::TokenDetails]
|
|
64
|
+
#
|
|
65
|
+
# @example
|
|
66
|
+
# # will issue a simple token request using basic auth
|
|
67
|
+
# client = Ably::Rest::Client.new(key: 'key.id:secret')
|
|
68
|
+
# client.auth.authorize do |token_details|
|
|
69
|
+
# token_details #=> Ably::Models::TokenDetails
|
|
70
|
+
# end
|
|
71
|
+
#
|
|
72
|
+
def authorize(token_params = nil, auth_options = nil, &success_callback)
|
|
73
|
+
Ably::Util::SafeDeferrable.new(logger).tap do |authorize_method_deferrable|
|
|
74
|
+
# Wrap the sync authorize method and wait for the result from the deferrable
|
|
75
|
+
async_wrap do
|
|
76
|
+
authorize_sync(token_params, auth_options)
|
|
77
|
+
end.tap do |auth_operation|
|
|
78
|
+
# Authorize operation succeeded and we have a new token, now let's perform inline authentication
|
|
79
|
+
auth_operation.callback do |token|
|
|
80
|
+
case connection.state.to_sym
|
|
81
|
+
when :initialized, :disconnected, :suspended, :closed, :closing, :failed
|
|
82
|
+
connection.connect
|
|
83
|
+
when :connected
|
|
84
|
+
perform_inline_auth token
|
|
85
|
+
when :connecting
|
|
86
|
+
# Fail all current connection attempts and try again with the new token, see #RTC8b
|
|
87
|
+
connection.manager.release_and_establish_new_transport
|
|
88
|
+
else
|
|
89
|
+
logger.fatal { "Auth#authorize: unsupported state #{connection.state}" }
|
|
90
|
+
authorize_method_deferrable.fail Ably::Exceptions::InvalidState.new("Unsupported state #{connection.state} for Auth#authorize")
|
|
91
|
+
next
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Indicate success or failure based on response from realtime, see #RTC8b1
|
|
95
|
+
auth_deferrable_resolved = false
|
|
96
|
+
|
|
97
|
+
connection.unsafe_once(:connected, :update) do
|
|
98
|
+
auth_deferrable_resolved = true
|
|
99
|
+
authorize_method_deferrable.succeed token
|
|
100
|
+
end
|
|
101
|
+
connection.unsafe_once(:suspended, :closed, :failed) do |state_change|
|
|
102
|
+
auth_deferrable_resolved = true
|
|
103
|
+
authorize_method_deferrable.fail state_change.reason
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Authorize failed, likely due to auth_url or auth_callback failing
|
|
108
|
+
auth_operation.errback do |error|
|
|
109
|
+
client.connection.transition_state_machine :failed, reason: error if error.kind_of?(Ably::Exceptions::IncompatibleClientId)
|
|
110
|
+
authorize_method_deferrable.fail error
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Call the block provided to this method upon success of this deferrable
|
|
115
|
+
authorize_method_deferrable.callback do |token|
|
|
116
|
+
yield token if block_given?
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# @deprecated Use {#authorize} instead
|
|
122
|
+
def authorise(*args, &block)
|
|
123
|
+
logger.warn { "Auth#authorise is deprecated and will be removed in 1.0. Please use Auth#authorize instead" }
|
|
124
|
+
authorize(*args, &block)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Synchronous version of {#authorize}. See {Ably::Auth#authorize} for method definition
|
|
128
|
+
# Please note that authorize_sync will however not upgrade the current connection's token as this requires
|
|
129
|
+
# an synchronous operation to send the new authentication details to Ably over a realtime connection
|
|
130
|
+
#
|
|
131
|
+
# @param (see Ably::Auth#authorize)
|
|
132
|
+
# @option (see Ably::Auth#authorize)
|
|
133
|
+
# @return [Ably::Models::TokenDetails]
|
|
134
|
+
#
|
|
135
|
+
def authorize_sync(token_params = nil, auth_options = nil)
|
|
136
|
+
@authorization_in_flight = true
|
|
137
|
+
auth_sync.authorize(token_params, auth_options)
|
|
138
|
+
ensure
|
|
139
|
+
@authorization_in_flight = false
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# @api private
|
|
143
|
+
def authorization_in_flight?
|
|
144
|
+
@authorization_in_flight
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# @deprecated Use {#authorize_sync} instead
|
|
148
|
+
def authorise_sync(*args)
|
|
149
|
+
logger.warn { "Auth#authorise_sync is deprecated and will be removed in 1.0. Please use Auth#authorize_sync instead" }
|
|
150
|
+
authorize_sync(*args)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Request a {Ably::Models::TokenDetails} which can be used to make authenticated token based requests
|
|
154
|
+
#
|
|
155
|
+
# @param (see Ably::Auth#request_token)
|
|
156
|
+
# @option (see Ably::Auth#request_token)
|
|
157
|
+
#
|
|
158
|
+
# @return [Ably::Util::SafeDeferrable]
|
|
159
|
+
# @yield [Ably::Models::TokenDetails]
|
|
160
|
+
#
|
|
161
|
+
# @example
|
|
162
|
+
# # simple token request using basic auth
|
|
163
|
+
# client = Ably::Rest::Client.new(key: 'key.id:secret')
|
|
164
|
+
# client.auth.request_token do |token_details|
|
|
165
|
+
# token_details #=> Ably::Models::TokenDetails
|
|
166
|
+
# end
|
|
167
|
+
#
|
|
168
|
+
def request_token(token_params = {}, auth_options = {}, &success_callback)
|
|
169
|
+
async_wrap(success_callback) do
|
|
170
|
+
request_token_sync(token_params, auth_options)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Synchronous version of {#request_token}. See {Ably::Auth#request_token} for method definition
|
|
175
|
+
# @param (see Ably::Auth#authorize)
|
|
176
|
+
# @option (see Ably::Auth#authorize)
|
|
177
|
+
# @return [Ably::Models::TokenDetails]
|
|
178
|
+
#
|
|
179
|
+
def request_token_sync(token_params = {}, auth_options = {})
|
|
180
|
+
auth_sync.request_token(token_params, auth_options)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Creates and signs a token request that can then subsequently be used by any client to request a token
|
|
184
|
+
#
|
|
185
|
+
# @param (see Ably::Auth#create_token_request)
|
|
186
|
+
# @option (see Ably::Auth#create_token_request)
|
|
187
|
+
#
|
|
188
|
+
# @return [Ably::Util::SafeDeferrable]
|
|
189
|
+
# @yield [Models::TokenRequest]
|
|
190
|
+
#
|
|
191
|
+
# @example
|
|
192
|
+
# client.auth.create_token_request({ ttl: 3600 }, id: 'asd.asd') do |token_request|
|
|
193
|
+
# token_request #=> Ably::Models::TokenRequest
|
|
194
|
+
# end
|
|
195
|
+
def create_token_request(token_params = {}, auth_options = {}, &success_callback)
|
|
196
|
+
async_wrap(success_callback) do
|
|
197
|
+
create_token_request_sync(token_params, auth_options)
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Synchronous version of {#create_token_request}. See {Ably::Auth#create_token_request} for method definition
|
|
202
|
+
# @param (see Ably::Auth#authorize)
|
|
203
|
+
# @option (see Ably::Auth#authorize)
|
|
204
|
+
# @return [Ably::Models::TokenRequest]
|
|
205
|
+
#
|
|
206
|
+
def create_token_request_sync(token_params = {}, auth_options = {})
|
|
207
|
+
auth_sync.create_token_request(token_params, auth_options)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Auth header string used in HTTP requests to Ably
|
|
211
|
+
# Will reauthorize implicitly if required and capable
|
|
212
|
+
#
|
|
213
|
+
# @return [Ably::Util::SafeDeferrable]
|
|
214
|
+
# @yield [String] HTTP authentication value used in HTTP_AUTHORIZATION header
|
|
215
|
+
#
|
|
216
|
+
def auth_header(&success_callback)
|
|
217
|
+
async_wrap(success_callback) do
|
|
218
|
+
auth_header_sync
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Synchronous version of {#auth_header}. See {Ably::Auth#auth_header} for method definition
|
|
223
|
+
# @return [String] HTTP authentication value used in HTTP_AUTHORIZATION header
|
|
224
|
+
#
|
|
225
|
+
def auth_header_sync
|
|
226
|
+
auth_sync.auth_header
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def client_id_for_request_sync
|
|
230
|
+
auth_sync.client_id_for_request
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Auth params used in URI endpoint for Realtime connections
|
|
234
|
+
# Will reauthorize implicitly if required and capable
|
|
235
|
+
#
|
|
236
|
+
# @return [Ably::Util::SafeDeferrable]
|
|
237
|
+
# @yield [Hash] Auth params for a new Realtime connection
|
|
238
|
+
#
|
|
239
|
+
def auth_params(&success_callback)
|
|
240
|
+
fail_callback = lambda do |error, deferrable|
|
|
241
|
+
logger.error { "Failed to authenticate: #{error}" }
|
|
242
|
+
if error.kind_of?(Ably::Exceptions::BaseAblyException)
|
|
243
|
+
# Use base exception if it exists carrying forward the status codes
|
|
244
|
+
deferrable.fail Ably::Exceptions::AuthenticationFailed.new(error.message, nil, nil, error)
|
|
245
|
+
else
|
|
246
|
+
deferrable.fail Ably::Exceptions::AuthenticationFailed.new(error.message, 500, Ably::Exceptions::Codes::CLIENT_CONFIGURED_AUTHENTICATION_PROVIDER_REQUEST_FAILED)
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
async_wrap(success_callback, fail_callback) do
|
|
250
|
+
auth_params_sync
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
# Synchronous version of {#auth_params}. See {Ably::Auth#auth_params} for method definition
|
|
255
|
+
# @return [Hash] Auth params for a new Realtime connection
|
|
256
|
+
#
|
|
257
|
+
def auth_params_sync
|
|
258
|
+
auth_sync.auth_params
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
private
|
|
262
|
+
# The synchronous Auth class instanced by the Rest client
|
|
263
|
+
# @return [Ably::Auth]
|
|
264
|
+
def auth_sync
|
|
265
|
+
@auth_sync
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def client
|
|
269
|
+
@client
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# Sends an AUTH ProtocolMessage on the existing connection triggering
|
|
273
|
+
# an inline AUTH process, see #RTC8a
|
|
274
|
+
def perform_inline_auth(token)
|
|
275
|
+
logger.debug { "Performing inline AUTH with Ably using token #{token}" }
|
|
276
|
+
connection.send_protocol_message(
|
|
277
|
+
action: Ably::Models::ProtocolMessage::ACTION.Auth.to_i,
|
|
278
|
+
auth: { access_token: token.token }
|
|
279
|
+
)
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|