pubnub 4.6.1 → 4.8.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pubnub might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +3 -1
- data/.github/workflows/commands-handler.yml +27 -0
- data/.github/workflows/release/versions.json +17 -0
- data/.github/workflows/release.yml +58 -0
- data/.github/workflows/run_acceptance_tests.yml +46 -0
- data/.gitignore +18 -0
- data/.pubnub.yml +32 -4
- data/.travis.yml +0 -4
- data/CHANGELOG.md +31 -6
- data/Gemfile +2 -0
- data/Gemfile.lock +42 -1
- data/VERSION +1 -1
- data/config/cucumber.yml +7 -0
- data/features/step_definitions/access_steps.rb +256 -0
- data/features/support/env.rb +15 -0
- data/features/support/helper.rb +39 -0
- data/features/support/hooks.rb +98 -0
- data/lib/pubnub/cbor.rb +182 -0
- data/lib/pubnub/client/events.rb +1 -1
- data/lib/pubnub/client/paged_history.rb +144 -17
- data/lib/pubnub/client.rb +14 -0
- data/lib/pubnub/constants.rb +10 -7
- data/lib/pubnub/event.rb +21 -10
- data/lib/pubnub/events/grant_token.rb +172 -0
- data/lib/pubnub/events/revoke_token.rb +66 -0
- data/lib/pubnub/validators/grant_token.rb +51 -0
- data/lib/pubnub/validators/revoke_token.rb +31 -0
- data/lib/pubnub/version.rb +1 -1
- metadata +22 -4
@@ -0,0 +1,15 @@
|
|
1
|
+
ParameterType(
|
2
|
+
name: 'resourceType',
|
3
|
+
regexp: /CHANNEL|CHANNEL_GROUP|UUID/,
|
4
|
+
type: String,
|
5
|
+
transformer: ->(s) { s }
|
6
|
+
)
|
7
|
+
|
8
|
+
ParameterType(
|
9
|
+
name: 'permissionType',
|
10
|
+
regexp: /READ|WRITE|GET|MANAGE|UPDATE|JOIN|DELETE|/,
|
11
|
+
type: String,
|
12
|
+
transformer: ->(s) { s }
|
13
|
+
)
|
14
|
+
|
15
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
def has_permission(perms, permission_type)
|
2
|
+
current_perm = nil
|
3
|
+
eval "current_perm = Pubnub::Permissions.res(#{permission_type.downcase}: true).calculate_bitmask"
|
4
|
+
perms & current_perm != 0
|
5
|
+
end
|
6
|
+
|
7
|
+
def prepare_permissions_map(grants, resource_type)
|
8
|
+
grants
|
9
|
+
.select { |_, value|
|
10
|
+
value[:resource_type] == resource_type
|
11
|
+
}
|
12
|
+
.to_h { |name, value|
|
13
|
+
empty_permissions = if value[:pattern]
|
14
|
+
Pubnub::Permissions.pat
|
15
|
+
else
|
16
|
+
Pubnub::Permissions.res
|
17
|
+
end
|
18
|
+
permissions = value[:permission_type].reduce(empty_permissions) { |accumulated_permissions, string_perm|
|
19
|
+
accumulated_permissions.instance_variable_set("@" + string_perm.downcase, true)
|
20
|
+
accumulated_permissions
|
21
|
+
}
|
22
|
+
[name, permissions]
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def call_grant_token(pubnub, grant_token_state)
|
27
|
+
pubnub.grant_token(
|
28
|
+
ttl: grant_token_state[:ttl],
|
29
|
+
http_sync: true,
|
30
|
+
channels: prepare_permissions_map(grant_token_state[:current_grant], "CHANNEL"),
|
31
|
+
channel_groups: prepare_permissions_map(grant_token_state[:current_grant], "CHANNEL_GROUP"),
|
32
|
+
uuids: prepare_permissions_map(grant_token_state[:current_grant], "UUID"),
|
33
|
+
authorized_uuid: grant_token_state[:authorized_uuid]
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_error_body(error_response)
|
38
|
+
Pubnub::Formatter.parse_json(error_response.status[:server_response].body)[0]
|
39
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
Before do |scenario|
|
5
|
+
@grant_token_state = {}
|
6
|
+
@global_state = {}
|
7
|
+
@grant_token_state[:current_grant] = {}
|
8
|
+
@pn_configuration = {}
|
9
|
+
|
10
|
+
when_mock_server_used {
|
11
|
+
puts "Using mock"
|
12
|
+
expect(ENV['SERVER_HOST']).not_to be_nil
|
13
|
+
expect(ENV['SERVER_PORT']).not_to be_nil
|
14
|
+
@pn_configuration = {
|
15
|
+
origin: ENV['SERVER_HOST'] + ":" + ENV['SERVER_PORT'],
|
16
|
+
isSecure: false,
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
when_mock_server_used {
|
21
|
+
init_mock(scenario)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
After do |scenario|
|
26
|
+
when_mock_server_used {
|
27
|
+
expect_mock(scenario)
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def when_mock_server_used(&block)
|
32
|
+
if ENV['SERVER_MOCK']&.to_s&.downcase == 'true'
|
33
|
+
block.call
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def init_mock(scenario)
|
38
|
+
contract_name = contract_name(scenario)
|
39
|
+
if contract_name
|
40
|
+
call_init_endpoint(contract_name)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def call_init_endpoint(contract_name)
|
45
|
+
Net::HTTP.get_response("#{ENV['SERVER_HOST']}", "/init?__contract__script__=#{contract_name}", "#{ENV['SERVER_PORT']}")
|
46
|
+
end
|
47
|
+
|
48
|
+
def expect_mock(scenario)
|
49
|
+
contract_name = contract_name(scenario)
|
50
|
+
if contract_name
|
51
|
+
expect_result = call_expect_endpoint()
|
52
|
+
print(expect_result)
|
53
|
+
if still_pending?(expect_result) || some_failed?(expect_result)
|
54
|
+
message = "Scenario #{extract_contract(expect_result)} considered failure:
|
55
|
+
pending - #{extract_pending(expect_result)},
|
56
|
+
failed - #{extract_failed(expect_result)}"
|
57
|
+
RSpec::Expectations.fail_with(message)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def extract_contract(expect_result)
|
63
|
+
expect_result['contract']
|
64
|
+
end
|
65
|
+
|
66
|
+
def extract_pending(expect_result)
|
67
|
+
expect_result['expectations']['pending'].join(", ")
|
68
|
+
end
|
69
|
+
|
70
|
+
def extract_failed(expect_result)
|
71
|
+
expect_result['expectations']['failed'].join(", ")
|
72
|
+
end
|
73
|
+
|
74
|
+
def still_pending?(expect_result)
|
75
|
+
pending = expect_result['expectations']['pending']
|
76
|
+
not pending.empty?
|
77
|
+
end
|
78
|
+
|
79
|
+
def some_failed?(expect_result)
|
80
|
+
pending = expect_result['expectations']['failed']
|
81
|
+
not pending.empty?
|
82
|
+
end
|
83
|
+
|
84
|
+
def call_expect_endpoint
|
85
|
+
expect_response = Net::HTTP.get_response("#{ENV['SERVER_HOST']}", "/expect", "#{ENV['SERVER_PORT']}")
|
86
|
+
|
87
|
+
if expect_response == nil || expect_response.body == nil
|
88
|
+
RSpec::Expectations.fail_with("Expect response body is null")
|
89
|
+
else
|
90
|
+
JSON.parse(expect_response.body)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def contract_name(scenario)
|
95
|
+
scenario.source_tag_names&.
|
96
|
+
select { |tagName| tagName.start_with?("@contract") }&.
|
97
|
+
map { |tagName| tagName.split("=")[1] }&.first
|
98
|
+
end
|
data/lib/pubnub/cbor.rb
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
module Pubnub
|
2
|
+
class Cbor
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
TYPE_MASK = 0b11100000
|
7
|
+
ADDITIONAL_MASK = 0b00011111
|
8
|
+
|
9
|
+
TYPE_UNSIGNED_INT = 0b00000000
|
10
|
+
TYPE_NEGATIVE_INT = 0b00100000
|
11
|
+
TYPE_BYTE_STRING = 0b01000000
|
12
|
+
TYPE_TEXT_STRING = 0b01100000
|
13
|
+
TYPE_ARRAY = 0b10000000
|
14
|
+
TYPE_HASHMAP = 0b10100000
|
15
|
+
TYPE_TAG = 0b11000000
|
16
|
+
TYPE_FLOAT = 0b11100000
|
17
|
+
|
18
|
+
ADDITIONAL_TYPE_INDEFINITE = 31
|
19
|
+
INDEFINITE_BREAK = 0b11111111
|
20
|
+
|
21
|
+
ADDITIONAL_LENGTH_1B = 24
|
22
|
+
ADDITIONAL_LENGTH_2B = 25
|
23
|
+
ADDITIONAL_LENGTH_4B = 26
|
24
|
+
ADDITIONAL_LENGTH_8B = 27
|
25
|
+
|
26
|
+
ADDITIONAL_LENGTH_BYTES = {
|
27
|
+
ADDITIONAL_LENGTH_1B => 1,
|
28
|
+
ADDITIONAL_LENGTH_2B => 2,
|
29
|
+
ADDITIONAL_LENGTH_4B => 4,
|
30
|
+
ADDITIONAL_LENGTH_8B => 8,
|
31
|
+
}
|
32
|
+
|
33
|
+
SIMPLE_VALUE_FALSE = 0xF4
|
34
|
+
SIMPLE_VALUE_TRUE = 0xF5
|
35
|
+
SIMPLE_VALUE_NULL = 0xF6
|
36
|
+
SIMPLE_VALUE_UNDEF = 0xF7
|
37
|
+
|
38
|
+
def bytearray_to_i(byte_array)
|
39
|
+
byte_array.reverse_each.map.with_index do |b, i|
|
40
|
+
b << 8 * i
|
41
|
+
end.reduce(0) do |reduced, byte|
|
42
|
+
reduced | byte
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def decode_integer(data, additional)
|
47
|
+
if ADDITIONAL_LENGTH_BYTES.member?(additional)
|
48
|
+
bytearray_to_i(data.shift(ADDITIONAL_LENGTH_BYTES[additional]))
|
49
|
+
else
|
50
|
+
additional
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def decode_float(data, additional)
|
55
|
+
if additional <= 23
|
56
|
+
additional
|
57
|
+
else
|
58
|
+
bytes = bytearray_to_i(data.shift(ADDITIONAL_LENGTH_BYTES[additional]))
|
59
|
+
case (additional)
|
60
|
+
when ADDITIONAL_LENGTH_1B
|
61
|
+
bytes
|
62
|
+
when ADDITIONAL_LENGTH_2B
|
63
|
+
sign = (bytes >> 15) != 0 ? -1 : 1
|
64
|
+
exp = (bytes & 0b0111110000000000) >> 10
|
65
|
+
mant = bytes & 0b1111111111
|
66
|
+
if exp == 0
|
67
|
+
result = (2 ** -14) * (mant / 1024.to_f)
|
68
|
+
elsif exp == 0b11111
|
69
|
+
result = Float::INFINITY
|
70
|
+
else
|
71
|
+
result = (2 ** (exp - 15)) * (1 + mant / 1024.to_f)
|
72
|
+
end
|
73
|
+
sign * result
|
74
|
+
when ADDITIONAL_LENGTH_4B
|
75
|
+
sign = (bytes >> 31) != 0 ? -1 : 1
|
76
|
+
x = (bytes & ((1 << 23) - 1)) + (1 << 23)
|
77
|
+
exp = (bytes >> 23 & 0xFF) - 127
|
78
|
+
x * (2 ** (exp - 23)) * sign
|
79
|
+
when ADDITIONAL_LENGTH_8B
|
80
|
+
sign = (bytes >> 63) != 0 ? -1 : 1
|
81
|
+
exp = (bytes >> 52) & 0x7FF
|
82
|
+
|
83
|
+
mant = bytes & 0xFFFFFFFFFFFFF
|
84
|
+
|
85
|
+
if 0 == exp
|
86
|
+
val = mant * 2 ** (-(1022 + 52))
|
87
|
+
elsif 0b11111111111 != exp
|
88
|
+
val = (mant + (1 << 52)) * 2 ** (exp - (1023 + 52))
|
89
|
+
else
|
90
|
+
val = 0 == mant ? Float::INFINITY : Float::NAN
|
91
|
+
end
|
92
|
+
sign * val
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def indefinite_data(data)
|
98
|
+
result = []
|
99
|
+
|
100
|
+
loop do
|
101
|
+
byte = data.shift
|
102
|
+
break if byte == INDEFINITE_BREAK
|
103
|
+
result.append(byte)
|
104
|
+
break if data.empty?
|
105
|
+
end
|
106
|
+
result
|
107
|
+
end
|
108
|
+
|
109
|
+
def compute_length(data, additional)
|
110
|
+
if ADDITIONAL_LENGTH_BYTES.member?(additional)
|
111
|
+
bytearray_to_i(data.shift(ADDITIONAL_LENGTH_BYTES[additional]))
|
112
|
+
else
|
113
|
+
additional
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def decode_string(data, additional)
|
118
|
+
if additional == ADDITIONAL_TYPE_INDEFINITE
|
119
|
+
indefinite_data(data).pack('C*').force_encoding('UTF-8')
|
120
|
+
else
|
121
|
+
length = compute_length(data, additional)
|
122
|
+
data.shift(length).pack('C*').force_encoding('UTF-8')
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def decode_map(data, additional)
|
127
|
+
length = compute_length(data, additional)
|
128
|
+
result = Hash.new
|
129
|
+
(1..length).each { result.store(parse_data(data), parse_data(data)) }
|
130
|
+
result
|
131
|
+
end
|
132
|
+
|
133
|
+
def decode_array(data, additional)
|
134
|
+
length = compute_length(data, additional)
|
135
|
+
(1..length).map { parse_data(data) }
|
136
|
+
end
|
137
|
+
|
138
|
+
def parse_data(data)
|
139
|
+
byte = data.shift
|
140
|
+
|
141
|
+
case (byte)
|
142
|
+
when SIMPLE_VALUE_NULL
|
143
|
+
return nil
|
144
|
+
when SIMPLE_VALUE_TRUE
|
145
|
+
return true
|
146
|
+
when SIMPLE_VALUE_FALSE
|
147
|
+
return false
|
148
|
+
when SIMPLE_VALUE_UNDEF
|
149
|
+
return nil
|
150
|
+
else
|
151
|
+
type = byte & TYPE_MASK
|
152
|
+
additional = byte & ADDITIONAL_MASK
|
153
|
+
|
154
|
+
case (type)
|
155
|
+
when TYPE_NEGATIVE_INT
|
156
|
+
-1 - decode_integer(data, additional)
|
157
|
+
when TYPE_UNSIGNED_INT
|
158
|
+
decode_integer(data, additional)
|
159
|
+
when TYPE_FLOAT
|
160
|
+
decode_float(data, additional).to_f
|
161
|
+
when TYPE_BYTE_STRING
|
162
|
+
decode_string(data, additional)
|
163
|
+
when TYPE_TEXT_STRING
|
164
|
+
decode_string(data, additional)
|
165
|
+
when TYPE_ARRAY
|
166
|
+
decode_array(data, additional)
|
167
|
+
when TYPE_HASHMAP
|
168
|
+
decode_map(data, additional)
|
169
|
+
else
|
170
|
+
nil
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
public
|
176
|
+
|
177
|
+
def decode(value)
|
178
|
+
parse_data(value)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
data/lib/pubnub/client/events.rb
CHANGED
@@ -4,7 +4,7 @@ module Pubnub
|
|
4
4
|
class Client
|
5
5
|
# Module that holds generator for all events
|
6
6
|
module Events
|
7
|
-
EVENTS = %w[publish subscribe presence leave history here_now audit grant delete_messages
|
7
|
+
EVENTS = %w[publish subscribe presence leave history here_now audit grant grant_token revoke_token delete_messages
|
8
8
|
revoke time heartbeat where_now set_state state channel_registration message_counts signal
|
9
9
|
add_channels_to_push list_push_provisions remove_channels_from_push remove_device_from_push
|
10
10
|
set_uuid_metadata set_channel_metadata remove_uuid_metadata remove_channel_metadata
|
@@ -1,19 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Toplevel Pubnub module.
|
2
4
|
module Pubnub
|
3
5
|
# Pubnub client Class
|
4
6
|
class Client
|
5
7
|
# Module that holds paged_history event logic
|
6
8
|
module PagedHistory
|
9
|
+
# Fetch messages as long as one of criteria won't be met.
|
10
|
+
# Messages returned as single envelope.
|
11
|
+
def all_history_messages(options = {}, &block)
|
12
|
+
channel = options.fetch(:channel)
|
13
|
+
# Time frame between which messages should be fetched.
|
14
|
+
start_tt = options.fetch(:start, nil)
|
15
|
+
end_tt = options.fetch(:end, nil)
|
16
|
+
page_size = options.fetch(:page_size, 100) # How many messages per-request should be fetched.
|
17
|
+
reverse = options.fetch(:reverse, false) # Order in which messages should be retrieved if :end not set.
|
18
|
+
include_token = options.fetch(:include_token, true) # Whether timetoken should be included with message or not.
|
19
|
+
maximum = options.fetch(:max, 500) # Maximum number of messages which should be fetched.
|
20
|
+
callback = options.fetch(:callback, block)
|
21
|
+
|
22
|
+
reverse = false unless end_tt.nil? # Disable revers if closed time interval specified.
|
23
|
+
maximum = nil unless end_tt.nil? # Disable maximum messages count if closed time interval specified.
|
24
|
+
|
25
|
+
if options[:http_sync]
|
26
|
+
sync_all_history_messages(channel, include_token, page_size, reverse, maximum, callback, start: start_tt, end: end_tt)
|
27
|
+
else
|
28
|
+
async_all_history_messages(options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
7
32
|
def paged_history(options = {}, &block)
|
8
33
|
channel = options.fetch(:channel)
|
9
|
-
page = options.fetch(:page, 1)
|
10
|
-
limit = options.fetch(:limit, 100)
|
34
|
+
page = options.fetch(:page, 1) # How many mages should be fetched with specified limit.
|
35
|
+
limit = options.fetch(:limit, 100) # How many messages per page should be fetched.
|
36
|
+
include_token = options.fetch(:include_token, false) # Whether timetoken should be included with message or not.
|
11
37
|
callback = options.fetch(:callback, block)
|
12
|
-
|
13
|
-
start_tt = options.fetch(:start)
|
14
|
-
end_tt = options.fetch(:end)
|
15
|
-
|
16
|
-
|
38
|
+
# Time frame between which messages should be fetched.
|
39
|
+
start_tt = options.fetch(:start, nil)
|
40
|
+
end_tt = options.fetch(:end, nil)
|
41
|
+
|
42
|
+
if options[:http_sync]
|
43
|
+
sync_paged_history(channel, page, limit, include_token, callback, start: start_tt, end: end_tt)
|
17
44
|
else
|
18
45
|
async_paged_history(options)
|
19
46
|
end
|
@@ -21,40 +48,140 @@ module Pubnub
|
|
21
48
|
|
22
49
|
private
|
23
50
|
|
24
|
-
def
|
51
|
+
def sync_all_history_messages(channel, include_token, page_size, reverse, maximum, callback, timetokens)
|
52
|
+
next_timetoken = timetokens[:start]
|
53
|
+
messages_timetokens = timetokens.dup
|
54
|
+
final_envelope = nil
|
55
|
+
keep_fetching = true
|
56
|
+
messages = []
|
57
|
+
|
58
|
+
while keep_fetching
|
59
|
+
envelope = history(
|
60
|
+
channel: channel,
|
61
|
+
include_token: include_token,
|
62
|
+
count: page_size,
|
63
|
+
reverse: reverse,
|
64
|
+
start: next_timetoken,
|
65
|
+
end: timetokens[:end],
|
66
|
+
http_sync: true
|
67
|
+
)
|
68
|
+
|
69
|
+
# Terminate fetch because last attempt failed.
|
70
|
+
if envelope.status[:category] != :ack
|
71
|
+
final_envelope = envelope
|
72
|
+
break
|
73
|
+
end
|
74
|
+
|
75
|
+
result_data = envelope.result[:data]
|
76
|
+
result_messages = result_data[:messages]
|
77
|
+
break if result_messages.empty?
|
78
|
+
|
79
|
+
if reverse || timetokens[:end]
|
80
|
+
messages_timetokens[:start] = result_data[:start].to_i if messages.empty?
|
81
|
+
messages_timetokens[:end] = result_data[:end].to_i
|
82
|
+
messages.concat(result_messages)
|
83
|
+
else
|
84
|
+
messages_timetokens[:end] = result_data[:end].to_i if messages.empty?
|
85
|
+
messages_timetokens[:start] = result_data[:start].to_i
|
86
|
+
messages.unshift(*result_messages)
|
87
|
+
end
|
88
|
+
|
89
|
+
keep_fetching = result_messages.length == page_size
|
90
|
+
keep_fetching = messages.length < maximum if keep_fetching && maximum && maximum > 0
|
91
|
+
|
92
|
+
if keep_fetching
|
93
|
+
next_timetoken = reverse ? result_data[:end].to_i : result_data[:start].to_i
|
94
|
+
next_timetoken = result_data[:end].to_i unless timetokens[:end].nil?
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Create envelop if no error should be reported.
|
99
|
+
final_envelope = envelope_with_messages(messages, messages_timetokens) if final_envelope.nil?
|
100
|
+
|
101
|
+
callback&.call final_envelope
|
102
|
+
final_envelope
|
103
|
+
end
|
104
|
+
|
105
|
+
# Retrieve results page-by-page (callback called for each page).
|
106
|
+
def sync_paged_history(channel, page, limit, include_token, callback, timetokens)
|
25
107
|
envelopes = []
|
26
|
-
page.times do |
|
27
|
-
|
108
|
+
page.times do |_i|
|
109
|
+
envelope = history(
|
28
110
|
channel: channel,
|
111
|
+
include_token: include_token,
|
29
112
|
http_sync: true,
|
30
113
|
count: limit,
|
31
114
|
start: timetokens[:start],
|
32
115
|
end: timetokens[:end]
|
33
116
|
)
|
34
|
-
|
35
|
-
|
36
|
-
|
117
|
+
|
118
|
+
break if envelope.result[:data][:messages].empty?
|
119
|
+
|
120
|
+
envelopes.push envelope
|
121
|
+
timetokens[:start] = envelope.result[:data][:start].to_i
|
122
|
+
# No need to iterate further if there is no more messages.
|
123
|
+
break if envelope.result[:data][:messages].length < limit
|
37
124
|
end
|
38
125
|
|
39
126
|
call_callback(envelopes, callback)
|
40
127
|
end
|
41
128
|
|
42
129
|
def async_paged_history(options)
|
43
|
-
Concurrent::Future.
|
130
|
+
Concurrent::Future.execute do
|
44
131
|
sync_options = options.dup
|
45
132
|
sync_options[:http_sync] = true
|
46
|
-
paged_history(sync_options
|
133
|
+
paged_history(sync_options)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def async_all_history_messages(options)
|
138
|
+
Concurrent::Future.execute do
|
139
|
+
sync_options = options.dup
|
140
|
+
sync_options[:http_sync] = true
|
141
|
+
all_history_messages(sync_options)
|
47
142
|
end
|
48
143
|
end
|
49
144
|
|
50
145
|
def call_callback(envelopes, callback)
|
51
|
-
envelopes.flatten!
|
52
146
|
if callback
|
53
147
|
envelopes.each do |envelope|
|
54
|
-
|
148
|
+
callback.call envelope
|
55
149
|
end
|
56
150
|
end
|
57
151
|
envelopes
|
152
|
+
rescue StandardError => e
|
153
|
+
Pubnub.logger.error('Pubnub::Client') { "Error while calling callback #{e.inspect}" }
|
154
|
+
end
|
155
|
+
|
156
|
+
def envelope_with_messages(messages, timetokens)
|
157
|
+
Pubnub::Envelope.new(
|
158
|
+
event: :history,
|
159
|
+
event_options: nil,
|
160
|
+
timetoken: nil,
|
161
|
+
status: {
|
162
|
+
code: 200,
|
163
|
+
client_request: nil,
|
164
|
+
server_response: nil,
|
165
|
+
|
166
|
+
category: Pubnub::Constants::STATUS_ACK,
|
167
|
+
error: false,
|
168
|
+
auto_retried: false,
|
169
|
+
|
170
|
+
data: nil,
|
171
|
+
current_timetoken: nil,
|
172
|
+
last_timetoken: nil,
|
173
|
+
subscribed_channels: nil,
|
174
|
+
subscribed_channel_groups: nil,
|
175
|
+
config: nil
|
176
|
+
},
|
177
|
+
result: {
|
178
|
+
code: 200,
|
179
|
+
operation: Pubnub::Constants::OPERATION_HISTORY,
|
180
|
+
client_request: nil,
|
181
|
+
server_response: nil,
|
182
|
+
data: { messages: messages, end: timetokens[:end], start: timetokens[:start] }
|
183
|
+
}
|
184
|
+
)
|
58
185
|
end
|
59
186
|
end
|
60
187
|
end
|
data/lib/pubnub/client.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
1
3
|
require 'pubnub/error'
|
2
4
|
require 'pubnub/uuid'
|
3
5
|
require 'pubnub/formatter'
|
@@ -34,6 +36,8 @@ require 'pubnub/validators/client'
|
|
34
36
|
require 'pubnub/validators/audit'
|
35
37
|
require 'pubnub/validators/channel_registration'
|
36
38
|
require 'pubnub/validators/grant'
|
39
|
+
require 'pubnub/validators/grant_token'
|
40
|
+
require 'pubnub/validators/revoke_token'
|
37
41
|
require 'pubnub/validators/heartbeat'
|
38
42
|
require 'pubnub/validators/here_now'
|
39
43
|
require 'pubnub/validators/history'
|
@@ -67,6 +71,7 @@ require 'pubnub/validators/set_channel_members'
|
|
67
71
|
require 'pubnub/validators/set_memberships'
|
68
72
|
require 'pubnub/validators/remove_channel_members'
|
69
73
|
require 'pubnub/validators/remove_memberships'
|
74
|
+
require 'pubnub/cbor'
|
70
75
|
|
71
76
|
Dir[File.join(File.dirname(__dir__), 'pubnub', 'events', '*.rb')].each do |file|
|
72
77
|
require file
|
@@ -319,6 +324,15 @@ module Pubnub
|
|
319
324
|
@telemetry.await.fetch_average(event).value
|
320
325
|
end
|
321
326
|
|
327
|
+
def parse_token(token)
|
328
|
+
token_bytes = Base64.urlsafe_decode64(token)
|
329
|
+
Cbor.new.decode(token_bytes.bytes)
|
330
|
+
end
|
331
|
+
|
332
|
+
def set_token(token)
|
333
|
+
@env[:token] = token
|
334
|
+
end
|
335
|
+
|
322
336
|
private
|
323
337
|
|
324
338
|
def create_state_pools(event)
|
data/lib/pubnub/constants.rb
CHANGED
@@ -57,6 +57,8 @@ module Pubnub
|
|
57
57
|
OPERATION_CHANNEL_GROUP_REMOVE = :channel_group_remove
|
58
58
|
OPERATION_AUDIT = :audit
|
59
59
|
OPERATION_GRANT = :grant
|
60
|
+
OPERATION_GRANT_TOKEN = :grant_token
|
61
|
+
OPERATION_REVOKE_TOKEN = :revoke_token
|
60
62
|
OPERATION_REVOKE = :revoke
|
61
63
|
OPERATION_DELETE = :delete
|
62
64
|
OPERATION_LIST_ALL_CHANNEL_GROUPS = :list_all_channel_groups
|
@@ -86,13 +88,14 @@ module Pubnub
|
|
86
88
|
OPERATION_SUBSCRIBE, OPERATION_HEARTBEAT, OPERATION_PRESENCE, OPERATION_TIME, OPERATION_HISTORY,
|
87
89
|
OPERATION_HERE_NOW, OPERATION_GLOBAL_HERE_NOW, OPERATION_GET_STATE, OPERATION_LIST_ALL_CHANNEL_GROUPS,
|
88
90
|
OPERATION_LIST_ALL_CHANNELS_IN_CHANNEL_GROUP, OPERATION_CHANNEL_GROUP_ADD, OPERATION_CHANNEL_GROUP_REMOVE,
|
89
|
-
OPERATION_AUDIT, OPERATION_GRANT, OPERATION_REVOKE, OPERATION_WHERE_NOW,
|
90
|
-
OPERATION_ADD_CHANNELS_TO_PUSH, OPERATION_LIST_PUSH_PROVISIONS,
|
91
|
-
OPERATION_REMOVE_DEVICE_FROM_PUSH, OPERATION_SIGNAL,
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
91
|
+
OPERATION_AUDIT, OPERATION_GRANT, OPERATION_GRANT_TOKEN, OPERATION_REVOKE, OPERATION_WHERE_NOW,
|
92
|
+
OPERATION_MESSAGE_COUNTS, OPERATION_ADD_CHANNELS_TO_PUSH, OPERATION_LIST_PUSH_PROVISIONS,
|
93
|
+
OPERATION_REMOVE_CHANNELS_FROM_PUSH, OPERATION_REMOVE_DEVICE_FROM_PUSH, OPERATION_SIGNAL,
|
94
|
+
OPERATION_SET_UUID_METADATA, OPERATION_GET_UUID_METADATA, OPERATION_GET_ALL_UUID_METADATA,
|
95
|
+
OPERATION_REMOVE_UUID_METADATA, OPERATION_SET_CHANNEL_METADATA, OPERATION_GET_CHANNEL_METADATA,
|
96
|
+
OPERATION_GET_ALL_CHANNELS_METADATA, OPERATION_REMOVE_CHANNEL_METADATA, OPERATION_GET_CHANNEL_MEMBERS,
|
97
|
+
OPERATION_SET_CHANNEL_MEMBERS, OPERATION_REMOVE_CHANNEL_MEMBERS, OPERATION_GET_MEMBERSHIPS,
|
98
|
+
OPERATION_SET_MEMBERSHIPS, OPERATION_REMOVE_MEMBERSHIPS
|
96
99
|
].freeze
|
97
100
|
|
98
101
|
# Announcements
|