pubnub 4.6.2 → 5.0.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 +30 -4
- data/.travis.yml +0 -4
- data/CHANGELOG.md +35 -8
- 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 +258 -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/getters_setters.rb +5 -0
- data/lib/pubnub/client/paged_history.rb +144 -17
- data/lib/pubnub/client.rb +14 -5
- 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/client.rb +1 -0
- data/lib/pubnub/validators/common_validator.rb +17 -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
- data/lib/pubnub.rb +1 -0
- metadata +22 -4
@@ -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)
|
@@ -370,14 +384,9 @@ module Pubnub
|
|
370
384
|
|
371
385
|
def prepare_env
|
372
386
|
assign_defaults
|
373
|
-
generate_uuid if @env[:uuid].blank?
|
374
387
|
setup_pools
|
375
388
|
end
|
376
389
|
|
377
|
-
def generate_uuid
|
378
|
-
@env[:uuid] = UUID.generate
|
379
|
-
end
|
380
|
-
|
381
390
|
def assign_defaults
|
382
391
|
@env[:origin] = @env[:origins_pool].first if @env[:origins_pool]
|
383
392
|
default_values.each do |k, v|
|
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
|
data/lib/pubnub/event.rb
CHANGED
@@ -24,8 +24,8 @@ module Pubnub
|
|
24
24
|
env.delete(:state)
|
25
25
|
create_variables_from_options(env.merge(options))
|
26
26
|
@origin = @app.current_origin
|
27
|
-
format_channels
|
28
|
-
format_group
|
27
|
+
format_channels if enable_format_channels?
|
28
|
+
format_group if enable_format_group?
|
29
29
|
set_timestamp
|
30
30
|
validate!
|
31
31
|
telemetry = @app.telemetry_for(@telemetry_name)
|
@@ -44,7 +44,7 @@ module Pubnub
|
|
44
44
|
envelopes
|
45
45
|
end
|
46
46
|
|
47
|
-
def send_request(compressed_body = '')
|
47
|
+
def send_request(compressed_body = '', header = {})
|
48
48
|
Pubnub.logger.debug('Pubnub::Event') { '#send_request called' }
|
49
49
|
|
50
50
|
@compressed_body = compressed_body
|
@@ -54,13 +54,13 @@ module Pubnub
|
|
54
54
|
telemetry_time_start = ::Time.now.to_f
|
55
55
|
response = case operation_http_method
|
56
56
|
when "get"
|
57
|
-
sender.get(uri.to_s)
|
57
|
+
sender.get(uri.to_s, header: header)
|
58
58
|
when "post"
|
59
|
-
sender.post(uri.to_s, body: compressed_body)
|
59
|
+
sender.post(uri.to_s, body: compressed_body, header: header)
|
60
60
|
when "patch"
|
61
|
-
sender.patch(uri.to_s, body: compressed_body)
|
61
|
+
sender.patch(uri.to_s, body: compressed_body, header: header)
|
62
62
|
else
|
63
|
-
sender.delete(uri.to_s)
|
63
|
+
sender.delete(uri.to_s, header: header)
|
64
64
|
end
|
65
65
|
|
66
66
|
begin
|
@@ -102,9 +102,18 @@ module Pubnub
|
|
102
102
|
|
103
103
|
private
|
104
104
|
|
105
|
+
def enable_format_channels?
|
106
|
+
true
|
107
|
+
end
|
108
|
+
|
109
|
+
def enable_format_group?
|
110
|
+
true
|
111
|
+
end
|
112
|
+
|
105
113
|
def operation_http_method
|
106
114
|
case @event
|
107
|
-
when Pubnub::Constants::OPERATION_DELETE, Pubnub::Constants::OPERATION_REMOVE_CHANNEL_METADATA,
|
115
|
+
when Pubnub::Constants::OPERATION_DELETE, Pubnub::Constants::OPERATION_REMOVE_CHANNEL_METADATA,
|
116
|
+
Pubnub::Constants::OPERATION_REMOVE_UUID_METADATA, Pubnub::Constants::OPERATION_REVOKE_TOKEN
|
108
117
|
"delete"
|
109
118
|
when Pubnub::Constants::OPERATION_SET_UUID_METADATA, Pubnub::Constants::OPERATION_SET_CHANNEL_METADATA,
|
110
119
|
Pubnub::Constants::OPERATION_SET_CHANNEL_MEMBERS, Pubnub::Constants::OPERATION_SET_MEMBERSHIPS,
|
@@ -136,8 +145,9 @@ module Pubnub
|
|
136
145
|
pnsdk: @app.sdk_version
|
137
146
|
}
|
138
147
|
|
148
|
+
token = @app.env[:token]
|
139
149
|
empty_if_blank = {
|
140
|
-
auth: @auth_key,
|
150
|
+
auth: token ? token : @auth_key,
|
141
151
|
uuid: @app.env[:uuid],
|
142
152
|
@telemetry_name => @current_telemetry
|
143
153
|
}
|
@@ -164,7 +174,8 @@ module Pubnub
|
|
164
174
|
end count limit reverse presence_callback store skip_validate
|
165
175
|
state channel_group channel_groups compressed meta customs include_token
|
166
176
|
replicate with_presence cipher_key_selector include_meta join update get
|
167
|
-
add remove push_token push_gateway environment topic
|
177
|
+
add remove push_token push_gateway environment topic authorized_uuid
|
178
|
+
token
|
168
179
|
]
|
169
180
|
|
170
181
|
options = options.each_with_object({}) { |option, obj| obj[option.first.to_sym] = option.last }
|
@@ -0,0 +1,172 @@
|
|
1
|
+
module Pubnub
|
2
|
+
# Holds grant token functionality
|
3
|
+
class GrantToken < SingleEvent
|
4
|
+
include Concurrent::Async
|
5
|
+
include Pubnub::Validator::GrantToken
|
6
|
+
|
7
|
+
def initialize(options, app)
|
8
|
+
@event = current_operation
|
9
|
+
@telemetry_name = :l_pamv3
|
10
|
+
@uuids = options[:uuids] || {}
|
11
|
+
options[:channels] = options[:channels] || {}
|
12
|
+
options[:channel_groups] = options[:channel_groups] || {}
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def fire
|
17
|
+
Pubnub.logger.debug('Pubnub::GrantToken') { "Fired event #{self.class}" }
|
18
|
+
|
19
|
+
raw_body = {
|
20
|
+
ttl: @ttl,
|
21
|
+
permissions: {
|
22
|
+
meta: @meta,
|
23
|
+
uuid: @authorized_uuid,
|
24
|
+
resources: prepare_permissions(:resource, @channels, @channel_groups, @uuids),
|
25
|
+
patterns: prepare_permissions(:pattern, @channels, @channel_groups, @uuids)
|
26
|
+
}.select { |_, v| v }
|
27
|
+
}
|
28
|
+
body = Formatter.format_message(raw_body, "", false, false)
|
29
|
+
response = send_request(body, { "Content-Type": "application/json" })
|
30
|
+
|
31
|
+
envelopes = fire_callbacks(handle(response, uri))
|
32
|
+
finalize_event(envelopes)
|
33
|
+
envelopes
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def enable_format_channels?
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
def enable_format_group?
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
def current_operation
|
47
|
+
Pubnub::Constants::OPERATION_GRANT_TOKEN
|
48
|
+
end
|
49
|
+
|
50
|
+
def prepare_permissions(type, channels, groups, uuids)
|
51
|
+
{
|
52
|
+
channels: prepare_single_permissions(type, channels),
|
53
|
+
groups: prepare_single_permissions(type, groups),
|
54
|
+
uuids: prepare_single_permissions(type, uuids)
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def prepare_single_permissions(type, resources)
|
59
|
+
resources
|
60
|
+
.select { |_, v| v.type == type }
|
61
|
+
.to_h { |k, v| [k, v.calculate_bitmask] }
|
62
|
+
end
|
63
|
+
|
64
|
+
def valid_envelope(parsed_response, req_res_objects)
|
65
|
+
Pubnub::Envelope.new(
|
66
|
+
event: @event,
|
67
|
+
event_options: @given_options,
|
68
|
+
timetoken: nil,
|
69
|
+
status: {
|
70
|
+
code: req_res_objects[:response].code,
|
71
|
+
client_request: req_res_objects[:request],
|
72
|
+
server_response: req_res_objects[:response],
|
73
|
+
category: Pubnub::Constants::STATUS_ACK,
|
74
|
+
error: false,
|
75
|
+
auto_retried: false,
|
76
|
+
|
77
|
+
current_timetoken: nil,
|
78
|
+
last_timetoken: nil,
|
79
|
+
subscribed_channels: nil,
|
80
|
+
subscribed_channel_groups: nil,
|
81
|
+
|
82
|
+
data: nil,
|
83
|
+
|
84
|
+
config: get_config
|
85
|
+
|
86
|
+
},
|
87
|
+
result: {
|
88
|
+
code: req_res_objects[:response].code,
|
89
|
+
operation: current_operation,
|
90
|
+
client_request: req_res_objects[:request],
|
91
|
+
server_response: req_res_objects[:response],
|
92
|
+
|
93
|
+
data: parsed_response['data']
|
94
|
+
}
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
def path
|
99
|
+
'/' + [
|
100
|
+
'v3',
|
101
|
+
'pam',
|
102
|
+
@subscribe_key,
|
103
|
+
'grant'
|
104
|
+
].join('/')
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class Permissions
|
109
|
+
attr_reader :type
|
110
|
+
|
111
|
+
class << Permissions
|
112
|
+
def pat(read: false, write: false, manage: false, delete: false,
|
113
|
+
create: false, get: false, update: false, join: false)
|
114
|
+
Permissions.new(
|
115
|
+
type: :pattern,
|
116
|
+
read: read,
|
117
|
+
write: write,
|
118
|
+
manage: manage,
|
119
|
+
delete: delete,
|
120
|
+
create: create,
|
121
|
+
get: get,
|
122
|
+
update: update,
|
123
|
+
join: join
|
124
|
+
)
|
125
|
+
end
|
126
|
+
|
127
|
+
def res(read: false, write: false, manage: false, delete: false, create: false, get: false, update: false, join: false)
|
128
|
+
Permissions.new(
|
129
|
+
type: :resource,
|
130
|
+
read: read,
|
131
|
+
write: write,
|
132
|
+
manage: manage,
|
133
|
+
delete: delete,
|
134
|
+
create: create,
|
135
|
+
get: get,
|
136
|
+
update: update,
|
137
|
+
join: join
|
138
|
+
)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def initialize(options)
|
143
|
+
@type = options[:type]
|
144
|
+
@read = options[:read] || false
|
145
|
+
@write = options[:write] || false
|
146
|
+
@manage = options[:manage] || false
|
147
|
+
@delete = options[:delete] || false
|
148
|
+
@create = options[:create] || false
|
149
|
+
@get = options[:get] || false
|
150
|
+
@update = options[:update] || false
|
151
|
+
@join = options[:join] || false
|
152
|
+
end
|
153
|
+
|
154
|
+
def to_s
|
155
|
+
"Permissions: {:read => #{@read}, :write => #{@write}, :manage => #{@manage} , :delete => #{@delete}, :create => #{@create}, :get => #{@get}, :update => #{@update}, :join => #{@join}}"
|
156
|
+
end
|
157
|
+
|
158
|
+
def calculate_bitmask
|
159
|
+
sum = 0
|
160
|
+
|
161
|
+
sum |= 1 if @read
|
162
|
+
sum |= 2 if @write
|
163
|
+
sum |= 4 if @manage
|
164
|
+
sum |= 8 if @delete
|
165
|
+
sum |= 16 if @create
|
166
|
+
sum |= 32 if @get
|
167
|
+
sum |= 64 if @update
|
168
|
+
sum |= 128 if @join
|
169
|
+
sum
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Pubnub
|
2
|
+
# Holds revoke token functionality
|
3
|
+
class RevokeToken < SingleEvent
|
4
|
+
include Concurrent::Async
|
5
|
+
include Pubnub::Validator::RevokeToken
|
6
|
+
|
7
|
+
def initialize(options, app)
|
8
|
+
@event = :revoke_token
|
9
|
+
super
|
10
|
+
@token = @token.split(' ')
|
11
|
+
.map{ |part| CGI.escape(part) }
|
12
|
+
.join("%20")
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def current_operation
|
18
|
+
Pubnub::Constants::OPERATION_GRANT_TOKEN
|
19
|
+
end
|
20
|
+
|
21
|
+
def valid_envelope(parsed_response, req_res_objects)
|
22
|
+
Pubnub::Envelope.new(
|
23
|
+
event: @event,
|
24
|
+
event_options: @given_options,
|
25
|
+
timetoken: nil,
|
26
|
+
status: {
|
27
|
+
code: req_res_objects[:response].code,
|
28
|
+
client_request: req_res_objects[:request],
|
29
|
+
server_response: req_res_objects[:response],
|
30
|
+
category: Pubnub::Constants::STATUS_ACK,
|
31
|
+
error: false,
|
32
|
+
auto_retried: false,
|
33
|
+
|
34
|
+
current_timetoken: nil,
|
35
|
+
last_timetoken: nil,
|
36
|
+
subscribed_channels: nil,
|
37
|
+
subscribed_channel_groups: nil,
|
38
|
+
|
39
|
+
data: nil,
|
40
|
+
|
41
|
+
config: get_config
|
42
|
+
|
43
|
+
},
|
44
|
+
result: {
|
45
|
+
code: req_res_objects[:response].code,
|
46
|
+
operation: current_operation,
|
47
|
+
client_request: req_res_objects[:request],
|
48
|
+
server_response: req_res_objects[:response],
|
49
|
+
|
50
|
+
data: parsed_response['data']
|
51
|
+
}
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def path
|
57
|
+
'/' + [
|
58
|
+
'v3',
|
59
|
+
'pam',
|
60
|
+
@subscribe_key,
|
61
|
+
'grant',
|
62
|
+
@token
|
63
|
+
].join('/')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -52,6 +52,23 @@ module Pubnub
|
|
52
52
|
)
|
53
53
|
end
|
54
54
|
end
|
55
|
+
|
56
|
+
# Validates given uuid
|
57
|
+
def validate_uuid(uuid)
|
58
|
+
if !uuid || uuid.blank?
|
59
|
+
raise(
|
60
|
+
InitializationError.new,
|
61
|
+
'Missing required :uuid parameter.'
|
62
|
+
)
|
63
|
+
elsif !([String, Symbol].include?(uuid.class) ||
|
64
|
+
uuid.blank?)
|
65
|
+
raise(
|
66
|
+
InitializationError.new,
|
67
|
+
'UUID parameter is not valid. \
|
68
|
+
Should be type of String or Symbol.'
|
69
|
+
)
|
70
|
+
end
|
71
|
+
end
|
55
72
|
end
|
56
73
|
end
|
57
74
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Toplevel Pubnub module.
|
2
|
+
module Pubnub
|
3
|
+
# Validator module that holds all validators modules
|
4
|
+
module Validator
|
5
|
+
# Validator for Grant event
|
6
|
+
module GrantToken
|
7
|
+
include CommonValidator
|
8
|
+
|
9
|
+
def validate!
|
10
|
+
validate_keys!
|
11
|
+
validate_ttl!
|
12
|
+
validate_permissions!(@uuids, ":uuids")
|
13
|
+
validate_permissions!(@channels, ":channels")
|
14
|
+
validate_permissions!(@channel_groups, ":uuids")
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def validate_keys!
|
20
|
+
raise(
|
21
|
+
ArgumentError.new(object: self, message: ':subscribe_key is required for grant token event.'),
|
22
|
+
':subscribe_key is required for grant token event.'
|
23
|
+
) if @subscribe_key.nil? || @subscribe_key.empty?
|
24
|
+
|
25
|
+
raise(
|
26
|
+
ArgumentError.new(object: self, message: ':secret_key is required for grant token event.'),
|
27
|
+
':publish_key is required for grant token event.'
|
28
|
+
) if @secret_key.nil? || @secret_key.empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
def validate_ttl!
|
32
|
+
return unless !@ttl.nil? && !@ttl.is_a?(Integer)
|
33
|
+
|
34
|
+
raise(
|
35
|
+
ArgumentError.new(object: self, message: ':ttl has to be kind of Integer for grant token event.'),
|
36
|
+
':ttl has to be kind of Integer for grant token event.'
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_permissions!(arg, name)
|
41
|
+
return if arg.nil?
|
42
|
+
|
43
|
+
raise(
|
44
|
+
ArgumentError.new(object: self, message: ":#{name} has to be kind of Hash for grant token event."),
|
45
|
+
":#{name} has to be kind of Hash for grant token event."
|
46
|
+
) unless arg.is_a?(Hash)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|