pubnub 4.6.2 → 4.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5cdeb3e7194c3ec7799eef208411d9278556e36a1eb75ea736b7891aebc537d3
4
- data.tar.gz: 06347ae57e8a41fac5870cc3406e64acd846350d5dd4e5156e6e01d592d62320
3
+ metadata.gz: 60893402c5e2e35de1e5f78237b7a031920bf5c1eb3533c33bfc0b20441d2616
4
+ data.tar.gz: e3d018155805ab0a09453d8560aaf1ddcc35fe9d040229c0a3e9ec1c235bafdd
5
5
  SHA512:
6
- metadata.gz: 9b1bb676791d2be910ac576917456041e7ba6b188f4585900d42a6b05ecc8a07a8e965615ea94fac0325bebfc87508b89f70df9c3c72e5e97356340220ccb0e3
7
- data.tar.gz: 63418083e5e96c00d36183ebec6be0d6c7d6d326bea0b80bc90dd203171f2820d49793f0d79cdc2888c96841b472d9765b3d69c83f8b8579b5cba9ba0fc3db28
6
+ metadata.gz: '09fd547306bf18cc940d87ca6fe568c9e7fca6b5a6a309dc7e0fb159af537d604b0ff846857df420716d9092963d116bb08be6fb573de55c9913599eafae8873'
7
+ data.tar.gz: bd33c010676d951a71cadcc76184357441c911e4ab763a95e34f783033a942c88ecffb3e3afecb0fc74184964eff11d43e07cb6e908161045e8a730b9438b25a
data/.github/CODEOWNERS CHANGED
@@ -1 +1,3 @@
1
- * @parfeon @CraigLn
1
+ * @parfeon @CraigLn @bartk @kleewho
2
+ .github/* @parfeon @CraigLn @bartk @kleewho
3
+ README.md @techwritermat @kazydek
@@ -0,0 +1,27 @@
1
+ name: Commands processor
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+
7
+ jobs:
8
+ process:
9
+ name: Process command
10
+ if: ${{ github.event.issue.pull_request && endsWith(github.repository, '-private') != true && startsWith(github.event.comment.body, '@client-engineering-bot ') }}
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout repository
14
+ uses: actions/checkout@v2
15
+ - name: Checkout release actions
16
+ uses: actions/checkout@v2
17
+ with:
18
+ repository: pubnub/client-engineering-deployment-tools
19
+ ref: v1
20
+ token: ${{ secrets.GH_TOKEN }}
21
+ path: .github/.release/actions
22
+ - name: Process changelog entries
23
+ uses: ./.github/.release/actions/actions/commands
24
+ with:
25
+ token: ${{ secrets.GH_TOKEN }}
26
+ listener: client-engineering-bot
27
+ jira-api-key: ${{ secrets.JIRA_API_KEY }}
@@ -0,0 +1,17 @@
1
+ {
2
+ ".pubnub.yml": [
3
+ { "pattern": "^version: \"(.+)\"$", "cleared": true },
4
+ { "pattern": "\\s+package-name: pubnub-(v?(\\d+\\.?){2,}([a-zA-Z0-9-]+(\\.?\\d+)?)?).gem$", "cleared": true },
5
+ { "pattern": "/releases/download/(v?(\\d+\\.?){2,}([a-zA-Z0-9-]+(\\.?\\d+)?)?)/pubnub-.*.gem$", "cleared": false },
6
+ { "pattern": "/releases/download/.*/pubnub-(v?(\\d+\\.?){2,}([a-zA-Z0-9-]+(\\.?\\d+)?)?).gem$", "cleared": true }
7
+ ],
8
+ "VERSION": [
9
+ { "pattern": "(v?(\\d+\\.?){2,}([a-zA-Z0-9-]+(\\.?\\d+)?)?)", "cleared": true }
10
+ ],
11
+ "Gemfile.lock": [
12
+ { "pattern": "^\\s{2,}pubnub \\((v?(\\d+\\.?){2,}([a-zA-Z0-9-]+(\\.?\\d+)?)?)\\)$", "cleared": true }
13
+ ],
14
+ "lib/pubnub/version.rb": [
15
+ { "pattern": "^\\s{2,}VERSION = '(v?(\\d+\\.?){2,}([a-zA-Z0-9-]+(\\.?\\d+)?)?)'.freeze", "cleared": true }
16
+ ]
17
+ }
@@ -0,0 +1,58 @@
1
+ name: Automated product release
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [ master ]
6
+ types: [ closed ]
7
+
8
+
9
+ jobs:
10
+ check-release:
11
+ name: Check release required
12
+ runs-on: ubuntu-latest
13
+ if: ${{ github.event.pull_request.merged && endsWith(github.repository, '-private') != true }}
14
+ outputs:
15
+ release: ${{ steps.check.outputs.ready }}
16
+ steps:
17
+ - name: Checkout actions
18
+ uses: actions/checkout@v2
19
+ with:
20
+ repository: pubnub/client-engineering-deployment-tools
21
+ ref: v1
22
+ token: ${{ secrets.GH_TOKEN }}
23
+ path: .github/.release/actions
24
+ - id: check
25
+ name: Check pre-release completed
26
+ uses: ./.github/.release/actions/actions/checks/release
27
+ with:
28
+ token: ${{ secrets.GH_TOKEN }}
29
+ publish:
30
+ name: Publish package
31
+ runs-on: ubuntu-latest
32
+ needs: check-release
33
+ if: ${{ needs.check-release.outputs.release == 'true' }}
34
+ steps:
35
+ - name: Checkout repository
36
+ uses: actions/checkout@v2
37
+ with:
38
+ # This should be the same as the one specified for on.pull_request.branches
39
+ ref: master
40
+ - name: Checkout actions
41
+ uses: actions/checkout@v2
42
+ with:
43
+ repository: pubnub/client-engineering-deployment-tools
44
+ ref: v1
45
+ token: ${{ secrets.GH_TOKEN }}
46
+ path: .github/.release/actions
47
+ - name: Publish to RubyGems
48
+ uses: ./.github/.release/actions/actions/services/rubygems
49
+ with:
50
+ token: ${{ secrets.GH_TOKEN }}
51
+ gem-username: ${{ secrets.GEMS_ACCOUNT }}
52
+ gem-token: ${{ secrets.GEMS_API_KEY }}
53
+ - name: Create Release
54
+ uses: ./.github/.release/actions/actions/services/github-release
55
+ with:
56
+ token: ${{ secrets.GH_TOKEN }}
57
+ jira-api-key: ${{ secrets.JIRA_API_KEY }}
58
+ last-service: true
@@ -0,0 +1,46 @@
1
+ name: run_acceptance_tests
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ build:
7
+ name: Perform Acceptance BDD tests
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - name: Checkout project
11
+ uses: actions/checkout@v2
12
+ - name: Checkout mock-server action
13
+ uses: actions/checkout@v2
14
+ with:
15
+ repository: pubnub/client-engineering-deployment-tools
16
+ ref: github-actions
17
+ token: ${{ secrets.GH_TOKEN }}
18
+ path: client-engineering-deployment-tools
19
+ - name: Run mock server action
20
+ uses: ./client-engineering-deployment-tools/actions/mock-server
21
+ with:
22
+ token: ${{ secrets.GH_TOKEN }}
23
+ - name: Install dependencies
24
+ run: |
25
+ sudo gem install bundler &&
26
+ bundle install
27
+ - name: Run acceptance tests (optional)
28
+ run: bundle exec cucumber sdk-specifications/features/ -p mock -p run_beta -p report_beta
29
+ continue-on-error: true
30
+ - name: Run acceptance tests (required)
31
+ run: bundle exec cucumber sdk-specifications/features/ -p mock -p run_main -p report_main
32
+ - name: Combine test results
33
+ if: always()
34
+ run: |
35
+ sudo npm install -g junit-report-merger &&
36
+ jrm ./main.xml "./main/**/*.xml" &&
37
+ jrm ./beta.xml "./beta/**/*.xml"
38
+ - name: Expose main report
39
+ uses: actions/upload-artifact@v2
40
+ if: always()
41
+ with:
42
+ name: acceptance-test-reports
43
+ path: |
44
+ main.xml
45
+ beta.xml
46
+ retention-days: 7
data/.gitignore CHANGED
@@ -8,3 +8,21 @@ log/*
8
8
  examples/test.rb
9
9
  coverage
10
10
  dev_scripts
11
+
12
+ # GitHub Actions #
13
+ ##################
14
+ .github/.release
15
+ .bundle/ruby
16
+
17
+ .travis/README.md
18
+ .travis/scripts
19
+
20
+ deployment_keys
21
+ deployment_keys-private
22
+ deployment_keys.tar
23
+
24
+ .travis/github-labels-policy.json
25
+ .travis/github-labels.json
26
+ /.rvmrc
27
+ /.bundle/
28
+ /features/*.feature
data/.pubnub.yml CHANGED
@@ -1,6 +1,11 @@
1
1
  ---
2
- version: "4.6.2"
2
+ version: "4.7.0"
3
3
  changelog:
4
+ - date: 2021-11-09
5
+ version: v4.7.0
6
+ changes:
7
+ - type: feature
8
+ text: "Grant_token allows generation of signed token with permissions for channels, channel groups and uuids."
4
9
  -
5
10
  changes:
6
11
  -
@@ -600,7 +605,7 @@ sdks:
600
605
  - x86-64
601
606
  - distribution-type: package
602
607
  distribution-repository: RubyGems
603
- package-name: pubnub-4.6.1.gem
608
+ package-name: pubnub-4.7.0.gem
604
609
  location: https://rubygems.org/gems/pubnub
605
610
  requires:
606
611
  - name: addressable
@@ -705,8 +710,8 @@ sdks:
705
710
  - x86-64
706
711
  - distribution-type: library
707
712
  distribution-repository: GitHub release
708
- package-name: pubnub-4.6.1.gem
709
- location: https://github.com/pubnub/ruby/releases/download/v4.6.2/pubnub-4.6.1.gem
713
+ package-name: pubnub-v4.7.0.gem
714
+ location: https://github.com/pubnub/ruby/releases/download/v4.7.0/pubnub-4.7.0.gem
710
715
  requires:
711
716
  - name: addressable
712
717
  min-version: 2.0.0
data/.travis.yml CHANGED
@@ -16,10 +16,6 @@ stages:
16
16
 
17
17
  jobs:
18
18
  include:
19
- - stage: "test"
20
- name: 'Ruby 2.4.10'
21
- rvm: '2.4.10'
22
- script: bundle exec rspec
23
19
  - name: 'Ruby 2.5.8'
24
20
  rvm: '2.5.8'
25
21
  script: bundle exec rspec
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## v4.7.0
2
+ November 09 2021
3
+
4
+ #### Added
5
+ - Grant_token allows generation of signed token with permissions for channels, channel groups and uuids.
6
+
1
7
  ##### v4.6.2
2
8
 
3
9
  - Add new `sdks` section to `.pubnub.yml` with information about available artifacts and distribution variants.
data/Gemfile CHANGED
@@ -7,10 +7,12 @@ group :test do
7
7
  gem 'rr'
8
8
  gem 'rspec'
9
9
  gem 'rspec-retry'
10
+ gem 'rspec-expectations'
10
11
  gem 'rubocop'
11
12
  gem 'simplecov', '>= 0.12', require: false
12
13
  gem 'vcr'
13
14
  gem 'webmock'
15
+ gem 'cucumber'
14
16
  end
15
17
 
16
18
  group :development, :test do
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pubnub (4.6.2)
4
+ pubnub (4.7.0)
5
5
  addressable (>= 2.0.0)
6
6
  concurrent-ruby (~> 1.1.5)
7
7
  concurrent-ruby-edge (~> 0.5.0)
@@ -19,6 +19,7 @@ GEM
19
19
  awesome_print (1.8.0)
20
20
  binding_of_caller (0.8.0)
21
21
  debug_inspector (>= 0.0.1)
22
+ builder (3.2.4)
22
23
  codacy-coverage (2.2.1)
23
24
  simplecov
24
25
  coderay (1.1.3)
@@ -27,6 +28,37 @@ GEM
27
28
  concurrent-ruby (~> 1.1.5)
28
29
  crack (0.4.3)
29
30
  safe_yaml (~> 1.0.0)
31
+ cucumber (7.0.0)
32
+ builder (~> 3.2, >= 3.2.4)
33
+ cucumber-core (~> 10.0, >= 10.0.1)
34
+ cucumber-create-meta (~> 6.0, >= 6.0.1)
35
+ cucumber-cucumber-expressions (~> 12.1, >= 12.1.1)
36
+ cucumber-gherkin (~> 20.0, >= 20.0.1)
37
+ cucumber-html-formatter (~> 16.0, >= 16.0.1)
38
+ cucumber-messages (~> 17.0, >= 17.0.1)
39
+ cucumber-wire (~> 6.0, >= 6.0.1)
40
+ diff-lcs (~> 1.4, >= 1.4.4)
41
+ mime-types (~> 3.3, >= 3.3.1)
42
+ multi_test (~> 0.1, >= 0.1.2)
43
+ sys-uname (~> 1.2, >= 1.2.2)
44
+ cucumber-core (10.0.1)
45
+ cucumber-gherkin (~> 20.0, >= 20.0.1)
46
+ cucumber-messages (~> 17.0, >= 17.0.1)
47
+ cucumber-tag-expressions (~> 3.0, >= 3.0.1)
48
+ cucumber-create-meta (6.0.1)
49
+ cucumber-messages (~> 17.0, >= 17.0.1)
50
+ sys-uname (~> 1.2, >= 1.2.2)
51
+ cucumber-cucumber-expressions (12.1.3)
52
+ cucumber-gherkin (20.0.1)
53
+ cucumber-messages (~> 17.0, >= 17.0.1)
54
+ cucumber-html-formatter (16.0.1)
55
+ cucumber-messages (~> 17.0, >= 17.0.1)
56
+ cucumber-messages (17.1.1)
57
+ cucumber-tag-expressions (3.0.1)
58
+ cucumber-wire (6.1.1)
59
+ cucumber-core (~> 10.0, >= 10.0.1)
60
+ cucumber-cucumber-expressions (~> 12.1, >= 12.1.2)
61
+ cucumber-messages (~> 17.0, >= 17.0.1)
30
62
  debug_inspector (0.0.3)
31
63
  diff-lcs (1.4.4)
32
64
  docile (1.3.2)
@@ -68,6 +100,7 @@ GEM
68
100
  dry-equalizer (~> 0.2)
69
101
  dry-initializer (~> 3.0)
70
102
  dry-schema (~> 1.5)
103
+ ffi (1.13.1)
71
104
  ffi (1.13.1-java)
72
105
  hashdiff (1.0.1)
73
106
  httpclient (2.8.3)
@@ -75,6 +108,10 @@ GEM
75
108
  json (2.3.1)
76
109
  json (2.3.1-java)
77
110
  method_source (1.0.0)
111
+ mime-types (3.3.1)
112
+ mime-types-data (~> 3.2015)
113
+ mime-types-data (3.2021.0901)
114
+ multi_test (0.1.2)
78
115
  parallel (1.19.2)
79
116
  parser (2.7.1.4)
80
117
  ast (~> 2.4.1)
@@ -130,6 +167,8 @@ GEM
130
167
  simplecov-html (0.12.2)
131
168
  spoon (0.0.6)
132
169
  ffi
170
+ sys-uname (1.2.2)
171
+ ffi (~> 1.1)
133
172
  timers (4.3.0)
134
173
  unicode-display_width (1.7.0)
135
174
  vcr (6.0.0)
@@ -145,12 +184,14 @@ PLATFORMS
145
184
  DEPENDENCIES
146
185
  awesome_print
147
186
  codacy-coverage
187
+ cucumber
148
188
  pry
149
189
  pry-rescue
150
190
  pry-stack_explorer
151
191
  pubnub!
152
192
  rr
153
193
  rspec
194
+ rspec-expectations
154
195
  rspec-retry
155
196
  rubocop
156
197
  simplecov (>= 0.12)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.6.2
1
+ 4.7.0
@@ -0,0 +1,7 @@
1
+ default: -p mock -p run_main
2
+ run_main: -t "not @skip and not @na=ruby and not @beta"
3
+ report_main: -f junit --out main
4
+ run_beta: -t "not @skip and not @na=ruby and @beta"
5
+ report_beta: -f junit --out beta
6
+ mock: SERVER_MOCK=true PAM_SUB_KEY=subKey PAM_PUB_KEY=pubKey PAM_SEC_KEY=secKey SERVER_HOST=localhost SERVER_PORT=8090
7
+ prod: SERVER_MOCK=false
@@ -0,0 +1,167 @@
1
+ require 'pubnub'
2
+
3
+ token_with_all = "qEF2AkF0GmEI03xDdHRsGDxDcmVzpURjaGFuoWljaGFubmVsLTEY70NncnChb2NoYW5uZWxfZ3JvdXAtMQVDdXNyoENzcGOgRHV1aWShZnV1aWQtMRhoQ3BhdKVEY2hhbqFtXmNoYW5uZWwtXFMqJBjvQ2dycKF0XjpjaGFubmVsX2dyb3VwLVxTKiQFQ3VzcqBDc3BjoER1dWlkoWpedXVpZC1cUyokGGhEbWV0YaBEdXVpZHR0ZXN0LWF1dGhvcml6ZWQtdXVpZENzaWdYIPpU-vCe9rkpYs87YUrFNWkyNq8CVvmKwEjVinnDrJJc"
4
+
5
+ Given('I have a keyset with access manager enabled') do
6
+ expect(ENV['PAM_SUB_KEY']).not_to be_nil
7
+ expect(ENV['PAM_PUB_KEY']).not_to be_nil
8
+ expect(ENV['PAM_SEC_KEY']).not_to be_nil
9
+ @pn_configuration['subscribe_key'] = ENV['PAM_SUB_KEY']
10
+ @pn_configuration['publish_key'] = ENV['PAM_PUB_KEY']
11
+ @pn_configuration['secret_key'] = ENV['PAM_SEC_KEY']
12
+ logger = Logger.new(STDOUT)
13
+ logger.level = Logger::DEBUG
14
+ @pn_configuration['logger'] = logger
15
+
16
+ @pubnub = Pubnub.new(@pn_configuration)
17
+ end
18
+
19
+ Given('the authorized UUID {string}') do |uuid|
20
+ @grant_token_state[:authorized_uuid] = uuid
21
+ end
22
+
23
+ Given('the TTL {int}') do |ttl|
24
+ @grant_token_state[:ttl] = ttl
25
+ end
26
+
27
+ Given('the {string} {resourceType} resource access permissions') do |name, resource_type|
28
+ @grant_token_state[:current_name] = name
29
+
30
+ @grant_token_state[:current_grant][name] = {
31
+ :name => name,
32
+ :resource_type => resource_type,
33
+ :permission_type => []
34
+ }
35
+ end
36
+
37
+ And('grant resource permission {permissionType}') do |permission_type|
38
+ current_name = @grant_token_state[:current_name]
39
+ @grant_token_state[:current_grant][current_name][:permission_type].push(permission_type)
40
+ end
41
+
42
+ Given('the {string} {resourceType} pattern access permissions') do |pattern, resource_type|
43
+ @grant_token_state[:current_pattern] = pattern
44
+ @grant_token_state[:current_grant][pattern] = {
45
+ :pattern => pattern,
46
+ :resource_type => resource_type,
47
+ :permission_type => []
48
+ }
49
+ end
50
+
51
+ And('grant pattern permission {permissionType}') do |permission_type|
52
+ current_pattern = @grant_token_state[:current_pattern]
53
+ @grant_token_state[:current_grant][current_pattern][:permission_type].push(permission_type)
54
+ end
55
+
56
+
57
+ When('I grant a token specifying those permissions') do
58
+ res = call_grant_token(@pubnub, @grant_token_state)
59
+ @grant_token_state[:parsed_token] = @pubnub.parse_token(res.result[:data]["token"])
60
+ end
61
+
62
+ Then('the token contains the authorized UUID {string}') do |expected_uuid|
63
+ expect(@grant_token_state[:parsed_token]["uuid"]).to eq expected_uuid
64
+ end
65
+
66
+ Then('the token contains the TTL {int}') do |ttl|
67
+ expect(@grant_token_state[:parsed_token]["ttl"]).to eq ttl
68
+ end
69
+
70
+ Then('the token has {string} {resourceType} resource access permissions') do |resource, resource_type|
71
+ case resource_type
72
+ when "CHANNEL"
73
+ @grant_token_state[:token_resource] = @grant_token_state[:parsed_token]["res"]["chan"][resource]
74
+ when "CHANNEL_GROUP"
75
+ @grant_token_state[:token_resource] = @grant_token_state[:parsed_token]["res"]["grp"][resource]
76
+ when "UUID"
77
+ @grant_token_state[:token_resource] = @grant_token_state[:parsed_token]["res"]["uuid"][resource]
78
+ else
79
+ fail
80
+ end
81
+
82
+ expect(@grant_token_state[:token_resource]).not_to eq nil
83
+ end
84
+
85
+ Then('token resource permission {permissionType}') do |permission_type|
86
+ expect(has_permission(@grant_token_state[:token_resource], permission_type)).to eq true
87
+ end
88
+
89
+ Then('the token has {string} {resourceType} pattern access permissions') do |pattern, resourceType|
90
+ case resourceType
91
+ when "CHANNEL"
92
+ @grant_token_state[:token_resource] = @grant_token_state[:parsed_token]["pat"]["chan"][pattern]
93
+ when "CHANNEL_GROUP"
94
+ @grant_token_state[:token_resource] = @grant_token_state[:parsed_token]["pat"]["grp"][pattern]
95
+ when "UUID"
96
+ @grant_token_state[:token_resource] = @grant_token_state[:parsed_token]["pat"]["uuid"][pattern]
97
+ else
98
+ fail
99
+ end
100
+
101
+ expect(@grant_token_state[:token_resource]).not_to eq nil
102
+ end
103
+
104
+ And('token pattern permission {permissionType}') do |permission_type|
105
+ expect(has_permission(@grant_token_state[:token_resource], permission_type)).to eq true
106
+ end
107
+
108
+ Then('the token does not contain an authorized uuid') do
109
+ expect(@grant_token_state[:parsed_token]["uuid"]).to eq nil
110
+ end
111
+
112
+ Given('deny resource permission {permissionType}') do |permission_type|
113
+ current_name = @grant_token_state[:current_name]
114
+ @grant_token_state[:current_grant][current_name][:permission_type].filter { |p| p != permission_type }
115
+ end
116
+
117
+ When('I attempt to grant a token specifying those permissions') do
118
+ @grant_token_state[:error_response] = call_grant_token(@pubnub, @grant_token_state)
119
+ end
120
+
121
+ Then('an error is returned') do
122
+ expect(@grant_token_state[:error_response]).not_to eq nil
123
+ end
124
+
125
+ Then('the error status code is {int}') do |code|
126
+ expect(@grant_token_state[:error_response].status[:code]).to eq code
127
+ end
128
+
129
+ Then('the error message is {string}') do |error_message|
130
+ expect(parse_error_body(@grant_token_state[:error_response])["error"]["message"]).to eq error_message
131
+ end
132
+
133
+ Then('the error source is {string}') do |error_source|
134
+ expect(parse_error_body(@grant_token_state[:error_response])["error"]["source"]).to eq error_source
135
+ end
136
+
137
+ Then('the error detail message is {string}') do |details_message|
138
+ expect(parse_error_body(@grant_token_state[:error_response])["error"]["details"][0]["message"]).to eq details_message
139
+ end
140
+
141
+ Then('the error detail location is {string}') do |details_location|
142
+ expect(parse_error_body(@grant_token_state[:error_response])["error"]["details"][0]["location"]).to eq details_location
143
+ end
144
+
145
+ Then('the error detail location type is {string}') do |location_type|
146
+ expect(parse_error_body(@grant_token_state[:error_response])["error"]["details"][0]["locationType"]).to eq location_type
147
+ end
148
+
149
+ Given('I have a known token containing an authorized UUID') do
150
+ @grant_token_state[:token] = token_with_all
151
+ end
152
+
153
+ When('I parse the token') do
154
+ @grant_token_state[:parsed_token] = @pubnub.parse_token(@grant_token_state[:token])
155
+ end
156
+
157
+ Then('the parsed token output contains the authorized UUID {string}') do |expected_uuid|
158
+ expect(@grant_token_state[:parsed_token]["uuid"]).to eq expected_uuid
159
+ end
160
+
161
+ Given('I have a known token containing UUID resource permissions') do
162
+ @grant_token_state[:token] = token_with_all
163
+ end
164
+
165
+ Given('I have a known token containing UUID pattern Permissions') do
166
+ @grant_token_state[:token] = token_with_all
167
+ end
@@ -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,97 @@
1
+ require 'net/http'
2
+ require 'json'
3
+
4
+ Before do |scenario|
5
+ @grant_token_state = {}
6
+ @grant_token_state[:current_grant] = {}
7
+ @pn_configuration = {}
8
+
9
+ when_mock_server_used {
10
+ puts "Using mock"
11
+ expect(ENV['SERVER_HOST']).not_to be_nil
12
+ expect(ENV['SERVER_PORT']).not_to be_nil
13
+ @pn_configuration = {
14
+ origin: ENV['SERVER_HOST'] + ":" + ENV['SERVER_PORT'],
15
+ isSecure: false,
16
+ }
17
+ }
18
+
19
+ when_mock_server_used {
20
+ init_mock(scenario)
21
+ }
22
+ end
23
+
24
+ After do |scenario|
25
+ when_mock_server_used {
26
+ expect_mock(scenario)
27
+ }
28
+ end
29
+
30
+ def when_mock_server_used(&block)
31
+ if ENV['SERVER_MOCK']&.to_s&.downcase == 'true'
32
+ block.call
33
+ end
34
+ end
35
+
36
+ def init_mock(scenario)
37
+ contract_name = contract_name(scenario)
38
+ if contract_name
39
+ call_init_endpoint(contract_name)
40
+ end
41
+ end
42
+
43
+ def call_init_endpoint(contract_name)
44
+ Net::HTTP.get_response("#{ENV['SERVER_HOST']}", "/init?__contract__script__=#{contract_name}", "#{ENV['SERVER_PORT']}")
45
+ end
46
+
47
+ def expect_mock(scenario)
48
+ contract_name = contract_name(scenario)
49
+ if contract_name
50
+ expect_result = call_expect_endpoint()
51
+ print(expect_result)
52
+ if still_pending?(expect_result) || some_failed?(expect_result)
53
+ message = "Scenario #{extract_contract(expect_result)} considered failure:
54
+ pending - #{extract_pending(expect_result)},
55
+ failed - #{extract_failed(expect_result)}"
56
+ RSpec::Expectations.fail_with(message)
57
+ end
58
+ end
59
+ end
60
+
61
+ def extract_contract(expect_result)
62
+ expect_result['contract']
63
+ end
64
+
65
+ def extract_pending(expect_result)
66
+ expect_result['expectations']['pending'].join(", ")
67
+ end
68
+
69
+ def extract_failed(expect_result)
70
+ expect_result['expectations']['failed'].join(", ")
71
+ end
72
+
73
+ def still_pending?(expect_result)
74
+ pending = expect_result['expectations']['pending']
75
+ not pending.empty?
76
+ end
77
+
78
+ def some_failed?(expect_result)
79
+ pending = expect_result['expectations']['failed']
80
+ not pending.empty?
81
+ end
82
+
83
+ def call_expect_endpoint
84
+ expect_response = Net::HTTP.get_response("#{ENV['SERVER_HOST']}", "/expect", "#{ENV['SERVER_PORT']}")
85
+
86
+ if expect_response == nil || expect_response.body == nil
87
+ RSpec::Expectations.fail_with("Expect response body is null")
88
+ else
89
+ JSON.parse(expect_response.body)
90
+ end
91
+ end
92
+
93
+ def contract_name(scenario)
94
+ scenario.source_tag_names&.
95
+ select { |tagName| tagName.start_with?("@contract") }&.
96
+ map { |tagName| tagName.split("=")[1] }&.first
97
+ end
@@ -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
@@ -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 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
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,7 @@ 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'
37
40
  require 'pubnub/validators/heartbeat'
38
41
  require 'pubnub/validators/here_now'
39
42
  require 'pubnub/validators/history'
@@ -67,6 +70,7 @@ require 'pubnub/validators/set_channel_members'
67
70
  require 'pubnub/validators/set_memberships'
68
71
  require 'pubnub/validators/remove_channel_members'
69
72
  require 'pubnub/validators/remove_memberships'
73
+ require 'pubnub/cbor'
70
74
 
71
75
  Dir[File.join(File.dirname(__dir__), 'pubnub', 'events', '*.rb')].each do |file|
72
76
  require file
@@ -319,6 +323,15 @@ module Pubnub
319
323
  @telemetry.await.fetch_average(event).value
320
324
  end
321
325
 
326
+ def parse_token(token)
327
+ token_bytes = Base64.urlsafe_decode64(token)
328
+ Cbor.new.decode(token_bytes.bytes)
329
+ end
330
+
331
+ def set_token(token)
332
+ @env[:token] = token
333
+ end
334
+
322
335
  private
323
336
 
324
337
  def create_state_pools(event)
@@ -57,6 +57,7 @@ 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
60
61
  OPERATION_REVOKE = :revoke
61
62
  OPERATION_DELETE = :delete
62
63
  OPERATION_LIST_ALL_CHANNEL_GROUPS = :list_all_channel_groups
@@ -86,13 +87,14 @@ module Pubnub
86
87
  OPERATION_SUBSCRIBE, OPERATION_HEARTBEAT, OPERATION_PRESENCE, OPERATION_TIME, OPERATION_HISTORY,
87
88
  OPERATION_HERE_NOW, OPERATION_GLOBAL_HERE_NOW, OPERATION_GET_STATE, OPERATION_LIST_ALL_CHANNEL_GROUPS,
88
89
  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, OPERATION_MESSAGE_COUNTS,
90
- OPERATION_ADD_CHANNELS_TO_PUSH, OPERATION_LIST_PUSH_PROVISIONS, OPERATION_REMOVE_CHANNELS_FROM_PUSH,
91
- OPERATION_REMOVE_DEVICE_FROM_PUSH, OPERATION_SIGNAL, OPERATION_SET_UUID_METADATA, OPERATION_GET_UUID_METADATA,
92
- OPERATION_GET_ALL_UUID_METADATA, OPERATION_REMOVE_UUID_METADATA, OPERATION_SET_CHANNEL_METADATA,
93
- OPERATION_GET_CHANNEL_METADATA, OPERATION_GET_ALL_CHANNELS_METADATA, OPERATION_REMOVE_CHANNEL_METADATA,
94
- OPERATION_GET_CHANNEL_MEMBERS, OPERATION_SET_CHANNEL_MEMBERS, OPERATION_REMOVE_CHANNEL_MEMBERS,
95
- OPERATION_GET_MEMBERSHIPS, OPERATION_SET_MEMBERSHIPS, OPERATION_REMOVE_MEMBERSHIPS
90
+ OPERATION_AUDIT, OPERATION_GRANT, OPERATION_GRANT_TOKEN, OPERATION_REVOKE, OPERATION_WHERE_NOW,
91
+ OPERATION_MESSAGE_COUNTS, OPERATION_ADD_CHANNELS_TO_PUSH, OPERATION_LIST_PUSH_PROVISIONS,
92
+ OPERATION_REMOVE_CHANNELS_FROM_PUSH, OPERATION_REMOVE_DEVICE_FROM_PUSH, OPERATION_SIGNAL,
93
+ OPERATION_SET_UUID_METADATA, OPERATION_GET_UUID_METADATA, OPERATION_GET_ALL_UUID_METADATA,
94
+ OPERATION_REMOVE_UUID_METADATA, OPERATION_SET_CHANNEL_METADATA, OPERATION_GET_CHANNEL_METADATA,
95
+ OPERATION_GET_ALL_CHANNELS_METADATA, OPERATION_REMOVE_CHANNEL_METADATA, OPERATION_GET_CHANNEL_MEMBERS,
96
+ OPERATION_SET_CHANNEL_MEMBERS, OPERATION_REMOVE_CHANNEL_MEMBERS, OPERATION_GET_MEMBERSHIPS,
97
+ OPERATION_SET_MEMBERSHIPS, OPERATION_REMOVE_MEMBERSHIPS
96
98
  ].freeze
97
99
 
98
100
  # 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,6 +102,14 @@ 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
115
  when Pubnub::Constants::OPERATION_DELETE, Pubnub::Constants::OPERATION_REMOVE_CHANNEL_METADATA, Pubnub::Constants::OPERATION_REMOVE_UUID_METADATA
@@ -136,8 +144,9 @@ module Pubnub
136
144
  pnsdk: @app.sdk_version
137
145
  }
138
146
 
147
+ token = @app.env[:token]
139
148
  empty_if_blank = {
140
- auth: @auth_key,
149
+ auth: token ? token : @auth_key,
141
150
  uuid: @app.env[:uuid],
142
151
  @telemetry_name => @current_telemetry
143
152
  }
@@ -164,7 +173,7 @@ module Pubnub
164
173
  end count limit reverse presence_callback store skip_validate
165
174
  state channel_group channel_groups compressed meta customs include_token
166
175
  replicate with_presence cipher_key_selector include_meta join update get
167
- add remove push_token push_gateway environment topic
176
+ add remove push_token push_gateway environment topic authorized_uuid
168
177
  ]
169
178
 
170
179
  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,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
+
@@ -1,4 +1,4 @@
1
1
  # Toplevel Pubnub module.
2
2
  module Pubnub
3
- VERSION = '4.6.2'.freeze
3
+ VERSION = '4.7.0'.freeze
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pubnub
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.6.2
4
+ version: 4.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - PubNub
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-09 00:00:00.000000000 Z
11
+ date: 2021-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -130,6 +130,10 @@ files:
130
130
  - ".bundle/config"
131
131
  - ".codeclimate.yml"
132
132
  - ".github/CODEOWNERS"
133
+ - ".github/workflows/commands-handler.yml"
134
+ - ".github/workflows/release.yml"
135
+ - ".github/workflows/release/versions.json"
136
+ - ".github/workflows/run_acceptance_tests.yml"
133
137
  - ".github/workflows/validate-pubnub-yml.yml"
134
138
  - ".github/workflows/validate-yml.js"
135
139
  - ".gitignore"
@@ -145,7 +149,12 @@ files:
145
149
  - README.md
146
150
  - Rakefile
147
151
  - VERSION
152
+ - config/cucumber.yml
148
153
  - docs.md
154
+ - features/step_definitions/grant_token_steps.rb
155
+ - features/support/env.rb
156
+ - features/support/helper.rb
157
+ - features/support/hooks.rb
149
158
  - gemfiles/celluloid_017.gemfile
150
159
  - gemfiles/celluloid_017.gemfile.lock
151
160
  - gemfiles/celluloid_018.gemfile
@@ -155,6 +164,7 @@ files:
155
164
  - gemfiles/concurrent-ruby-1.0.5.gem
156
165
  - gemfiles/concurrent-ruby-edge-0.3.1.gem
157
166
  - lib/pubnub.rb
167
+ - lib/pubnub/cbor.rb
158
168
  - lib/pubnub/client.rb
159
169
  - lib/pubnub/client/events.rb
160
170
  - lib/pubnub/client/getters_setters.rb
@@ -180,6 +190,7 @@ files:
180
190
  - lib/pubnub/events/get_memberships.rb
181
191
  - lib/pubnub/events/get_uuid_metadata.rb
182
192
  - lib/pubnub/events/grant.rb
193
+ - lib/pubnub/events/grant_token.rb
183
194
  - lib/pubnub/events/heartbeat.rb
184
195
  - lib/pubnub/events/here_now.rb
185
196
  - lib/pubnub/events/history.rb
@@ -235,6 +246,7 @@ files:
235
246
  - lib/pubnub/validators/get_memberships.rb
236
247
  - lib/pubnub/validators/get_uuid_metadata.rb
237
248
  - lib/pubnub/validators/grant.rb
249
+ - lib/pubnub/validators/grant_token.rb
238
250
  - lib/pubnub/validators/heartbeat.rb
239
251
  - lib/pubnub/validators/here_now.rb
240
252
  - lib/pubnub/validators/history.rb
@@ -281,8 +293,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
281
293
  - !ruby/object:Gem::Version
282
294
  version: '0'
283
295
  requirements: []
284
- rubygems_version: 3.2.19
296
+ rubygems_version: 3.1.2
285
297
  signing_key:
286
298
  specification_version: 4
287
299
  summary: PubNub Official Ruby gem.
288
- test_files: []
300
+ test_files:
301
+ - features/step_definitions/grant_token_steps.rb
302
+ - features/support/env.rb
303
+ - features/support/helper.rb
304
+ - features/support/hooks.rb