cent 0.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47ce99ab8c4bbdc34e55ed10c59c5cc88f8dc94114f57cb0cc6a2114f504da07
4
- data.tar.gz: 8ed06495a1b706309ee0797522a20e60b7a2be89c8ce139d4a78a1c10f539fae
3
+ metadata.gz: ccda06fa2a0da286f06e74761175bb6e822930267d8bd6edf0058359c8a8efe4
4
+ data.tar.gz: 7a4f9398de445b0853edbdbb464339692af7a35e3777d1b71240159073f39134
5
5
  SHA512:
6
- metadata.gz: 3257d7b4bb382e9937148e21d920978df68aba42b697e3214f1eb1f64c73538dcf041ece277ebdec64349486a524c5b047a350a71e0e97df94873980a764356b
7
- data.tar.gz: a31e53c242a2b58594cd4583982281e79bd7795d535d3e18b23f48b559e31cba19a1a73ac1f6536b870487b2e34b87a309cc6b63db3b7995c14048de1c8fbb5d
6
+ metadata.gz: 7b53b22a81d6d8ef2f9cb02af14ed35675713e77a040be770e07f6f5f1c166eed649fa0b5937e0424a877067b7ffdc31a4e0e22010eb00e85536b86f02cf3830
7
+ data.tar.gz: 21d2c90b9e905d40611f6ba0010042a8ffbef7bf13ed13abce683b003a5bfcddc3bf52db0b34d5d72c5e050855041f563b487e85ec4071c332be1362659033b4
@@ -0,0 +1,18 @@
1
+ name: Ruby
2
+
3
+ on: [push,pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v2
10
+ - name: Set up Ruby
11
+ uses: ruby/setup-ruby@v1
12
+ with:
13
+ ruby-version: 2.7.1
14
+ - name: Run the default task
15
+ run: |
16
+ gem install bundler -v 2.2.10
17
+ bundle install
18
+ bundle exec rake
@@ -0,0 +1,33 @@
1
+ name: Release Ruby Gem
2
+
3
+ on:
4
+ # Manually publish
5
+ workflow_dispatch:
6
+ jobs:
7
+ build-and-release:
8
+ name: Release
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ packages: write
12
+ contents: read
13
+
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@v2
17
+
18
+ - name: Set up Ruby 2.6
19
+ uses: ruby/setup-ruby@477b21f02be01bcb8030d50f37cfec92bfa615b6
20
+ with:
21
+ ruby-version: 2.6
22
+ - run: bundle install
23
+
24
+ - name: Publish to RubyGems
25
+ run: |
26
+ mkdir -p $HOME/.gem
27
+ touch $HOME/.gem/credentials
28
+ chmod 0600 $HOME/.gem/credentials
29
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
30
+ gem build *.gemspec
31
+ gem push *.gem
32
+ env:
33
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_API_KEY}}"
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .ruby-gemset
16
+ .ruby-versions
17
+ *.iml
18
+ .idea/
19
+ .rspec_status
20
+
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,11 @@
1
+ require:
2
+ - rubocop-rspec
3
+ - rubocop-rake
4
+ AllCops:
5
+ TargetRubyVersion: 2.5
6
+ NewCops: enable
7
+ RSpec/ExampleLength:
8
+ Max: 15
9
+ Metrics/BlockLength:
10
+ Exclude:
11
+ - 'spec/**/*'
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ 2.0.0
2
+ =====
3
+
4
+ * Complete rewrite of a Ruby Client to work with Centrifugo V2 Server API
5
+
6
+ 1.2.0
7
+ =====
8
+
9
+ * update assets to latest library versions: SockJS to 1.1.1 and centrifuge-js to 1.3.7
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in cent.gemspec
6
+ gemspec
7
+
8
+ gem 'rake', '~> 13.0'
9
+
10
+ gem 'rspec', '~> 3.0'
11
+ gem 'webmock', '~> 3.7.5'
12
+
13
+ gem 'rubocop', '~> 1.7'
14
+ gem 'rubocop-rake'
15
+ gem 'rubocop-rspec'
16
+
17
+ gem 'pry'
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Centrifugal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,282 @@
1
+ # Cent
2
+ [![Code Climate](https://codeclimate.com/github/centrifugal/centrifuge-ruby/badges/gpa.svg)](https://codeclimate.com/github/centrifugal/centrifuge-ruby)
3
+ ![Build Status](https://github.com/centrifugal/rubycent/actions/workflows/main.yml/badge.svg)
4
+
5
+ [Centrifugo HTTP API v2](https://centrifugal.github.io/centrifugo/server/http_api/) client in Ruby.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'cent'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install cent
22
+
23
+ ## Usage
24
+
25
+ Functionality is split between two classes:
26
+ - `Cent::Client` to call API methods
27
+ - `Cent::Notary` to generate tokens
28
+
29
+ ### Token Generation
30
+
31
+ ```ruby
32
+ notary = Cent::Notary.new(secret: 'secret')
33
+ ```
34
+
35
+ By default it uses HS256 to generate tokens, but you can set it to one of the HMAC, RSA or ECDSA family.
36
+
37
+ #### RSA
38
+
39
+ ```ruby
40
+ secret = OpenSSL::PKey::RSA.new(File.read('./rsa_secret.pem'))
41
+ notary = Cent::Notary.new(secret: secret, algorithm: 'RS256')
42
+ ```
43
+
44
+ #### ECDSA
45
+
46
+ ```ruby
47
+ secret = OpenSSL::PKey::EC.new(File.read('./ecdsa_secret.pem'))
48
+ notary = Cent::Notary.new(secret: secret, algorithm: 'ES256')
49
+ ```
50
+
51
+ #### Connection token
52
+
53
+ When connecting to Centrifugo client [must provide connection JWT token](https://centrifugal.github.io/centrifugo/server/authentication/) with several predefined credential claims.
54
+
55
+ ```ruby
56
+ notary.issue_connection_token(sub: '42')
57
+
58
+ #=> "eyJhbGciOiJIUzI1NiJ9..."
59
+ ```
60
+
61
+ `info` and `exp` are supported as well:
62
+
63
+ ```ruby
64
+ notary.issue_connection_token(sub: '42', info: { scope: 'admin' }, exp: 1629050099)
65
+
66
+ #=> "eyJhbGciOiJIUzI1NiJ9..."
67
+ ```
68
+
69
+ ### Private channel token
70
+
71
+ All channels starting with $ considered private and require a **channel token** to subscribe.
72
+ Private channel subscription token is also JWT([see the claims](https://centrifugal.github.io/centrifugo/server/private_channels/))
73
+
74
+ ```ruby
75
+ notary.issue_channel_token(client: 'client', channel: 'channel', exp: 1629050099, info: { scope: 'admin' })
76
+
77
+ #=> "eyJhbGciOiJIUzI1NiJ9..."
78
+ ```
79
+
80
+ ### API Client
81
+
82
+ A client requires your Centrifugo API key to execute all requests.
83
+
84
+ ```ruby
85
+ client = Cent::Client.new(api_key: 'key')
86
+ ```
87
+
88
+ you can customize your connection as you wish, just remember it's a [Faraday::Connection](https://lostisland.github.io/faraday/usage/#customizing-faradayconnection) instance:
89
+
90
+ ```ruby
91
+ client = Cent::Client.new(api_key: 'key', endpoint: 'https://centrifu.go/api') do |connection|
92
+ connection.headers['User-Agent'] = 'Centrifugo Ruby Client'
93
+ connection.options.open_timeout = 3
94
+ connection.options.timeout = 7
95
+ connection.adapter :typhoeus
96
+ end
97
+ ```
98
+
99
+ #### Publish
100
+
101
+ Send data to the channel.
102
+
103
+ [https://centrifugal.github.io/centrifugo/server/http_api/#publish](https://centrifugal.github.io/centrifugo/server/http_api/#publish)
104
+
105
+ ```ruby
106
+ client.publish(channel: 'chat', data: 'hello') # => {}
107
+ ```
108
+
109
+ #### Broadcast
110
+
111
+ Sends data to multiple channels.
112
+
113
+ [https://centrifugal.github.io/centrifugo/server/http_api/#broadcast](https://centrifugal.github.io/centrifugo/server/http_api/#broadcast)
114
+
115
+ ```ruby
116
+ client.broadcast(channels: ["clients", "staff"], data: 'hello') # => {}
117
+ ```
118
+
119
+ #### Unsubscribe
120
+
121
+ Unsubscribe user from channel. Receives to arguments: channel and user (user ID you want to unsubscribe)
122
+
123
+ [https://centrifugal.github.io/centrifugo/server/http_api/#unsubscribe](https://centrifugal.github.io/centrifugo/server/http_api/#unsubscribe)
124
+
125
+ ```ruby
126
+ client.unsubscribe(channel: 'chat', user: '1') # => {}
127
+ ```
128
+
129
+ #### Disconnect
130
+
131
+ Allows to disconnect user by it's ID. Receives user ID as an argument.
132
+
133
+ [https://centrifugal.github.io/centrifugo/server/http_api/#disconnect](https://centrifugal.github.io/centrifugo/server/http_api/#disconnect)
134
+
135
+ ```ruby
136
+ # Disconnect user with `id = 1`
137
+ #
138
+ client.disconnect(user: '1') # => {}
139
+ ```
140
+
141
+ #### Presence
142
+
143
+ Get channel presence information(all clients currently subscribed on this channel).
144
+
145
+ [https://centrifugal.github.io/centrifugo/server/http_api/#presence](https://centrifugal.github.io/centrifugo/server/http_api/#presence)
146
+
147
+ ```ruby
148
+ client.presence(channel: 'chat')
149
+
150
+ # {
151
+ # 'result' => {
152
+ # 'presence' => {
153
+ # 'c54313b2-0442-499a-a70c-051f8588020f' => {
154
+ # 'client' => 'c54313b2-0442-499a-a70c-051f8588020f',
155
+ # 'user' => '42'
156
+ # },
157
+ # 'adad13b1-0442-499a-a70c-051f858802da' => {
158
+ # 'client' => 'adad13b1-0442-499a-a70c-051f858802da',
159
+ # 'user' => '42'
160
+ # }
161
+ # }
162
+ # }
163
+ # }
164
+ ```
165
+
166
+ #### Presence stats
167
+
168
+ Get short channel presence information.
169
+
170
+ [https://centrifugal.github.io/centrifugo/server/http_api/#presence_stats](https://centrifugal.github.io/centrifugo/server/http_api/#precence_stats)
171
+
172
+ ```ruby
173
+ client.presence_stats(channel: 'chat')
174
+
175
+ # {
176
+ # "result" => {
177
+ # "num_clients" => 0,
178
+ # "num_users" => 0
179
+ # }
180
+ # }
181
+ ```
182
+
183
+ #### History
184
+
185
+ Get channel history information (list of last messages published into channel).
186
+
187
+ [https://centrifugal.github.io/centrifugo/server/http_api/#history](https://centrifugal.github.io/centrifugo/server/http_api/#hisotry)
188
+
189
+ ```ruby
190
+ client.history(channel: 'chat')
191
+
192
+ # {
193
+ # 'result' => {
194
+ # 'publications' => [
195
+ # {
196
+ # 'data' => {
197
+ # 'text' => 'hello'
198
+ # }
199
+ # },
200
+ # {
201
+ # 'data' => {
202
+ # 'text' => 'hi!'
203
+ # }
204
+ # }
205
+ # ]
206
+ # }
207
+ # }
208
+ ```
209
+
210
+ #### Channels
211
+
212
+ Get list of active(with one or more subscribers) channels.
213
+
214
+ [https://centrifugal.github.io/centrifugo/server/http_api/#channels](https://centrifugal.github.io/centrifugo/server/http_api/#channels)
215
+
216
+ ```ruby
217
+ client.channels
218
+
219
+ # {
220
+ # 'result' => {
221
+ # 'channels' => [
222
+ # 'chat'
223
+ # ]
224
+ # }
225
+ # }
226
+ ```
227
+
228
+ #### Info
229
+
230
+ Get running Centrifugo nodes information.
231
+
232
+ [https://centrifugal.github.io/centrifugo/server/http_api/#info](https://centrifugal.github.io/centrifugo/server/http_api/#info)
233
+
234
+ ```ruby
235
+ client.info
236
+
237
+ # {
238
+ # 'result' => {
239
+ # 'nodes' => [
240
+ # {
241
+ # 'name' => 'Alexanders-MacBook-Pro.local_8000',
242
+ # 'num_channels' => 0,
243
+ # 'num_clients' => 0,
244
+ # 'num_users' => 0,
245
+ # 'uid' => 'f844a2ed-5edf-4815-b83c-271974003db9',
246
+ # 'uptime' => 0,
247
+ # 'version' => ''
248
+ # }
249
+ # ]
250
+ # }
251
+ # }
252
+ ```
253
+
254
+ ### Errors
255
+
256
+ Network errors are not wrapped and will raise `Faraday::ClientError`.
257
+
258
+ In cases when Centrifugo returns 200 with `error` key in the body we wrap it and return custom error:
259
+
260
+ ```ruby
261
+ # Raised when response from Centrifugo contains any error as result of API command execution.
262
+ #
263
+ begin
264
+ client.publish(channel: 'channel', data: { foo: :bar })
265
+ rescue Cent::ResponseError => ex
266
+ ex.message # => "Invalid format"
267
+ end
268
+ ```
269
+
270
+ ## Development
271
+
272
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
273
+
274
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
275
+
276
+ ## Contributing
277
+
278
+ Bug reports and pull requests are welcome on GitHub at https://github.com/centrifugal/rubycent. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
279
+
280
+ ## License
281
+
282
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require 'rubocop/rake_task'
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'cent'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'pry'
15
+ Pry.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/cent.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/cent/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'cent'
7
+ spec.version = Cent::VERSION
8
+ spec.authors = ['Sergey Prikhodko']
9
+ spec.email = ['prikha@gmail.com']
10
+
11
+ spec.summary = 'Centrifugo API V2 Ruby Client'
12
+ spec.description = <<~DESC
13
+ Provides helper classes Cent::Client and Cent::Notary.
14
+
15
+ `Cent::Client` is made to communicate to the server API
16
+ `Client::Notary` is a simple JWT wrapper to generate authorization tokens for the frontend
17
+ DESC
18
+ spec.homepage = 'https://github.com/centrifugal/rubycent'
19
+ spec.license = 'MIT'
20
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
21
+
22
+ spec.metadata['homepage_uri'] = spec.homepage
23
+ spec.metadata['source_code_uri'] = 'https://github.com/centrifugal/rubycent'
24
+
25
+ # Specify which files should be added to the gem when it is released.
26
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
28
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:spec|Gemfile)/}) }
29
+ end
30
+
31
+ spec.require_paths = ['lib']
32
+
33
+ spec.add_dependency 'faraday', '<2.0.0', '~> 1.7.0'
34
+ spec.add_dependency 'faraday_middleware', '<2.0.0', '~> 1.0'
35
+ spec.add_dependency 'jwt', '~> 2.2.1'
36
+ end
data/lib/cent.rb ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cent/version'
4
+ require 'cent/notary'
5
+ require 'cent/client'
6
+
7
+ # Centrifugo Ruby Client
8
+ module Cent
9
+ # Here will be code...
10
+ end
@@ -0,0 +1,273 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'faraday_middleware'
5
+ require 'cent/http'
6
+
7
+ module Cent
8
+ # Cent::Client
9
+ #
10
+ # Main object that handles configuration and requests to centrifugo API
11
+ #
12
+ class Client
13
+ # @param endpoint [String]
14
+ # (default: 'http://localhost:8000/api') Centrifugo HTTP API URL
15
+ #
16
+ # @param api_key [String]
17
+ # Centrifugo API key(used to perform requests)
18
+ #
19
+ # @yield [Faraday::Connection] yields connection object so that it can be configured
20
+ #
21
+ # @example Construct new client instance
22
+ # Cent::Client.new(
23
+ # endpoint: 'http://localhost:8000/api',
24
+ # api_key: 'api key'
25
+ # )
26
+ #
27
+ def initialize(api_key:, endpoint: 'http://localhost:8000/api')
28
+ headers = {
29
+ 'Content-Type' => 'application/json',
30
+ 'Authorization' => "apikey #{api_key}"
31
+ }
32
+
33
+ @connection = Faraday.new(endpoint, headers: headers) do |conn|
34
+ conn.request :json # encode req bodies as JSON
35
+
36
+ conn.response :json # decode response bodies as JSON
37
+ conn.response :raise_error
38
+
39
+ yield conn if block_given?
40
+ end
41
+ end
42
+
43
+ # Publish data into channel
44
+ #
45
+ # @param channel [String]
46
+ # Name of the channel to publish
47
+ #
48
+ # @param data [Hash]
49
+ # Data for publication in the channel
50
+ #
51
+ # @example Publish `content: 'hello'` into `chat` channel
52
+ # client.publish(channel: 'chat', data: 'hello') #=> {}
53
+ #
54
+ # @see (https://centrifugal.github.io/centrifugo/server/http_api/#publish)
55
+ #
56
+ # @raise [Cent::Error, Cent::ResponseError]
57
+ #
58
+ # @return [Hash] Return empty hash in case of successful publish
59
+ #
60
+ def publish(channel:, data:)
61
+ execute('publish', channel: channel, data: data)
62
+ end
63
+
64
+ # Publish data into multiple channels
65
+ # (Similar to `#publish` but allows to send the same data into many channels)
66
+ #
67
+ # @param channels [Array<String>] Collection of channels names to publish
68
+ # @param data [Hash] Data for publication in the channels
69
+ #
70
+ # @example Broadcast `content: 'hello'` into `channel_1`, 'channel_2' channels
71
+ # client.broadcast(channels: ['channel_1', 'channel_2'], data: 'hello') #=> {}
72
+ #
73
+ # @see (https://centrifugal.github.io/centrifugo/server/http_api/#broadcast)
74
+ #
75
+ # @raise [Cent::Error, Cent::ResponseError]
76
+ #
77
+ # @return [Hash] Return empty hash in case of successful broadcast
78
+ #
79
+ def broadcast(channels:, data:)
80
+ execute('broadcast', channels: channels, data: data)
81
+ end
82
+
83
+ # Unsubscribe user from channel
84
+ #
85
+ # @param channel [String]
86
+ # Channel name to unsubscribe from
87
+ #
88
+ # @param user [String, Integer]
89
+ # User ID you want to unsubscribe
90
+ #
91
+ # @example Unsubscribe user with `id = 1` from `chat` channel
92
+ # client.unsubscribe(channel: 'chat', user: '1') #=> {}
93
+ #
94
+ # @see (https://centrifugal.github.io/centrifugo/server/http_api/#unsubscribe)
95
+ #
96
+ # @raise [Cent::Error, Cent::ResponseError]
97
+ #
98
+ # @return [Hash] Return empty hash in case of successful unsubscribe
99
+ #
100
+ def unsubscribe(channel:, user:)
101
+ execute('unsubscribe', channel: channel, user: user)
102
+ end
103
+
104
+ # Disconnect user by it's ID
105
+ #
106
+ # @param user [String, Integer]
107
+ # User ID you want to disconnect
108
+ #
109
+ # @example Disconnect user with `id = 1`
110
+ # client.disconnect(user: '1') #=> {}
111
+ #
112
+ # @see (https://centrifugal.github.io/centrifugo/server/http_api/#disconnect)
113
+ #
114
+ # @raise [Cent::Error, Cent::ResponseError]
115
+ #
116
+ # @return [Hash] Return empty hash in case of successful disconnect
117
+ #
118
+ def disconnect(user:)
119
+ execute('disconnect', user: user)
120
+ end
121
+
122
+ # Get channel presence information
123
+ # (all clients currently subscribed on this channel)
124
+ #
125
+ # @param channel [String] Name of the channel
126
+ #
127
+ # @example Get presence information for channel `chat`
128
+ # client.presence(channel: 'chat') #=> {
129
+ # "result" => {
130
+ # "presence" => {
131
+ # "c54313b2-0442-499a-a70c-051f8588020f" => {
132
+ # "client" => "c54313b2-0442-499a-a70c-051f8588020f",
133
+ # "user" => "42"
134
+ # },
135
+ # "adad13b1-0442-499a-a70c-051f858802da" => {
136
+ # "client" => "adad13b1-0442-499a-a70c-051f858802da",
137
+ # "user" => "42"
138
+ # }
139
+ # }
140
+ # }
141
+ # }
142
+ #
143
+ # @see (https://centrifugal.github.io/centrifugo/server/http_api/#presence)
144
+ #
145
+ # @raise [Cent::Error, Cent::ResponseError]
146
+ #
147
+ # @return [Hash]
148
+ # Return hash with information about all clients currently subscribed on this channel
149
+ #
150
+ def presence(channel:)
151
+ execute('presence', channel: channel)
152
+ end
153
+
154
+ # Get short channel presence information
155
+ #
156
+ # @param channel [String] Name of the channel
157
+ #
158
+ # @example Get short presence information for channel `chat`
159
+ # client.presence_stats(channel: 'chat') #=> {
160
+ # "result" => {
161
+ # "num_clients" => 0,
162
+ # "num_users" => 0
163
+ # }
164
+ # }
165
+ #
166
+ # @see (https://centrifugal.github.io/centrifugo/server/http_api/#presence_stats)
167
+ #
168
+ # @raise [Cent::Error, Cent::ResponseError]
169
+ #
170
+ # @return [Hash]
171
+ # Return hash with short presence information about channel
172
+ #
173
+ def presence_stats(channel:)
174
+ execute('presence_stats', channel: channel)
175
+ end
176
+
177
+ # Get channel history information
178
+ # (list of last messages published into channel)
179
+ #
180
+ # @param channel [String] Name of the channel
181
+ #
182
+ # @example Get history for channel `chat`
183
+ # client.history(channel: 'chat') #=> {
184
+ # "result" => {
185
+ # "publications" => [
186
+ # {
187
+ # "data" => {
188
+ # "text" => "hello"
189
+ # },
190
+ # "uid" => "BWcn14OTBrqUhTXyjNg0fg"
191
+ # },
192
+ # {
193
+ # "data" => {
194
+ # "text" => "hi!"
195
+ # },
196
+ # "uid" => "Ascn14OTBrq14OXyjNg0hg"
197
+ # }
198
+ # ]
199
+ # }
200
+ # }
201
+ #
202
+ # @see (https://centrifugal.github.io/centrifugo/server/http_api/#history)
203
+ #
204
+ # @raise [Cent::Error, Cent::ResponseError]
205
+ #
206
+ # @return [Hash]
207
+ # Return hash with a list of last messages published into channel
208
+ #
209
+ def history(channel:)
210
+ execute('history', channel: channel)
211
+ end
212
+
213
+ # Get list of active(with one or more subscribers) channels.
214
+ #
215
+ # @example Get active channels list
216
+ # client.channels #=> {
217
+ # "result" => {
218
+ # "channels" => [
219
+ # "chat"
220
+ # ]
221
+ # }
222
+ # }
223
+ #
224
+ # @see (https://centrifugal.github.io/centrifugo/server/http_api/#channels)
225
+ #
226
+ # @raise [Cent::Error, Cent::ResponseError]
227
+ #
228
+ # @return [Hash]
229
+ # Return hash with a list of active channels
230
+ #
231
+ def channels
232
+ execute('channels', {})
233
+ end
234
+
235
+ # Get information about running Centrifugo nodes
236
+ #
237
+ # @example Get running centrifugo nodes list
238
+ # client.info #=> {
239
+ # "result" => {
240
+ # "nodes" => [
241
+ # {
242
+ # "name" => "Alexanders-MacBook-Pro.local_8000",
243
+ # "num_channels" => 0,
244
+ # "num_clients" => 0,
245
+ # "num_users" => 0,
246
+ # "uid" => "f844a2ed-5edf-4815-b83c-271974003db9",
247
+ # "uptime" => 0,
248
+ # "version" => ""
249
+ # }
250
+ # ]
251
+ # }
252
+ # }
253
+ #
254
+ # @see (https://centrifugal.github.io/centrifugo/server/http_api/#info)
255
+ #
256
+ # @raise [Cent::Error, Cent::ResponseError]
257
+ #
258
+ # @return [Hash]
259
+ # Return hash with a list of last messages published into channel
260
+ #
261
+ def info
262
+ execute('info', {})
263
+ end
264
+
265
+ private
266
+
267
+ def execute(method, data)
268
+ body = { method: method, params: data }
269
+
270
+ Cent::HTTP.new(connection: @connection).post(body: body)
271
+ end
272
+ end
273
+ end
data/lib/cent/error.rb ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cent
4
+ # Cent::Error
5
+ #
6
+ # Wrapper for all errors(failures).
7
+ #
8
+ class Error < StandardError; end
9
+ end
data/lib/cent/http.rb ADDED
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cent/error'
4
+
5
+ module Cent
6
+ # Cent::ResponseError
7
+ #
8
+ # Raised when response from Centrifugo contains any error as result of API command execution.
9
+ #
10
+ class ResponseError < Error
11
+ attr_reader :code
12
+
13
+ def initialize(code:, message:)
14
+ @code = code
15
+ super message
16
+ end
17
+ end
18
+
19
+ # Cent::HTTP
20
+ #
21
+ # Holds request call and response handling logic
22
+ #
23
+ class HTTP
24
+ attr_reader :connection
25
+
26
+ # @param connection [Faraday::Connection] HTTP Connection object
27
+ #
28
+ def initialize(connection:)
29
+ @connection = connection
30
+ end
31
+
32
+ # Perform POST request to centrifugo API
33
+ # @param body [Hash] Request body(non serialized)
34
+ #
35
+ # @raise [Cent::ResponseError]
36
+ #
37
+ # @return [Hash] Parsed response body
38
+ #
39
+ def post(body: nil)
40
+ response = connection.post(nil, body)
41
+
42
+ raise ResponseError, response.body['error'].transform_keys(&:to_sym) if response.body.key?('error')
43
+
44
+ response.body
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jwt'
4
+ require 'cent/error'
5
+
6
+ module Cent
7
+ # Cent::Notary
8
+ #
9
+ # Handle token generation
10
+ #
11
+ class Notary
12
+ # @param secret [String | OpenSSL::PKey::RSA | OpenSSL::PKey::EC] Secret key for the algorithm of your choice.
13
+ # @param algorithm [String] Specify algorithm(one from HMAC, RSA or ECDSA family). Default is HS256.
14
+ #
15
+ # @example Construct new client instance
16
+ # notary = Cent::Notary.new(secret: 'secret')
17
+ #
18
+ def initialize(secret:, algorithm: 'HS256')
19
+ raise Error, 'Secret can not be nil' if secret.nil?
20
+
21
+ @secret = secret
22
+ @algorithm = algorithm
23
+ end
24
+
25
+ # Generate connection JWT for the given user
26
+ #
27
+ # @param sub [String]
28
+ # Standard JWT claim which must contain an ID of current application user.
29
+ #
30
+ # @option channel [String]
31
+ # Channel that client tries to subscribe to (string).
32
+ #
33
+ # @param exp [Integer]
34
+ # (default: nil) UNIX timestamp seconds when token will expire.
35
+ #
36
+ # @param info [Hash]
37
+ # (default: {}) This claim is optional - this is additional information about
38
+ # client connection that can be provided for Centrifugo.
39
+ #
40
+ # @example Get user JWT with expiration and extra info
41
+ # notary.issue_connection_token(sub: '1', exp: 3600, info: { 'role' => 'admin' })
42
+ # #=> "eyJhbGciOiJIUzI1NiJ9.eyJzdWIi..."
43
+ #
44
+ # @see (https://centrifugal.github.io/centrifugo/server/authentication/)
45
+ #
46
+ # @return [String]
47
+ #
48
+ def issue_connection_token(sub:, info: nil, exp: nil)
49
+ payload = {
50
+ 'sub' => sub,
51
+ 'info' => info,
52
+ 'exp' => exp
53
+ }.compact
54
+
55
+ JWT.encode(payload, secret, algorithm)
56
+ end
57
+
58
+ # Generate JWT for private channels
59
+ #
60
+ # @param client [String]
61
+ # Client ID which wants to subscribe on channel
62
+ #
63
+ # @option channel [String]
64
+ # Channel that client tries to subscribe to (string).
65
+ #
66
+ # @param exp [Integer]
67
+ # (default: nil) UNIX timestamp seconds when token will expire.
68
+ #
69
+ # @param info [Hash]
70
+ # (default: {}) This claim is optional - this is additional information about
71
+ # client connection that can be provided for Centrifugo.
72
+ #
73
+ # @example Get private channel JWT with expiration and extra info
74
+ # notary.issue_channel_token(client: 'client', channel: 'channel', exp: 3600, info: { 'message' => 'wat' })
75
+ # #=> eyJhbGciOiJIUzI1NiJ9.eyJjbGllbnQiOiJjbG..."
76
+ #
77
+ # @see (https://centrifugal.github.io/centrifugo/server/private_channels/)
78
+ #
79
+ # @return [String]
80
+ #
81
+ def issue_channel_token(client:, channel:, info: nil, exp: nil)
82
+ payload = {
83
+ 'client' => client,
84
+ 'channel' => channel,
85
+ 'info' => info,
86
+ 'exp' => exp
87
+ }.compact
88
+
89
+ JWT.encode(payload, secret, algorithm)
90
+ end
91
+
92
+ private
93
+
94
+ attr_reader :secret, :algorithm
95
+ end
96
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cent
4
+ VERSION = '2.0.0'
5
+ end
metadata CHANGED
@@ -1,124 +1,105 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Alexander Emelin
7
+ - Sergey Prikhodko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-16 00:00:00.000000000 Z
11
+ date: 2021-08-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: httpclient
14
+ name: faraday
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
17
+ - - "~>"
25
18
  - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: multi_json
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
19
+ version: 1.7.0
20
+ - - "<"
32
21
  - !ruby/object:Gem::Version
33
- version: '0'
22
+ version: 2.0.0
34
23
  type: :runtime
35
24
  prerelease: false
36
25
  version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: bundler
43
- requirement: !ruby/object:Gem::Requirement
44
26
  requirements:
45
27
  - - "~>"
46
28
  - !ruby/object:Gem::Version
47
- version: '1.7'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
29
+ version: 1.7.0
30
+ - - "<"
53
31
  - !ruby/object:Gem::Version
54
- version: '1.7'
32
+ version: 2.0.0
55
33
  - !ruby/object:Gem::Dependency
56
- name: rake
34
+ name: faraday_middleware
57
35
  requirement: !ruby/object:Gem::Requirement
58
36
  requirements:
59
37
  - - "~>"
60
38
  - !ruby/object:Gem::Version
61
- version: '10.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '10.0'
69
- - !ruby/object:Gem::Dependency
70
- name: rspec
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
39
+ version: '1.0'
40
+ - - "<"
74
41
  - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
42
+ version: 2.0.0
43
+ type: :runtime
77
44
  prerelease: false
78
45
  version_requirements: !ruby/object:Gem::Requirement
79
46
  requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: webmock
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
47
+ - - "~>"
88
48
  - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
49
+ version: '1.0'
50
+ - - "<"
95
51
  - !ruby/object:Gem::Version
96
- version: '0'
52
+ version: 2.0.0
97
53
  - !ruby/object:Gem::Dependency
98
- name: vcr
54
+ name: jwt
99
55
  requirement: !ruby/object:Gem::Requirement
100
56
  requirements:
101
- - - ">="
57
+ - - "~>"
102
58
  - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
59
+ version: 2.2.1
60
+ type: :runtime
105
61
  prerelease: false
106
62
  version_requirements: !ruby/object:Gem::Requirement
107
63
  requirements:
108
- - - ">="
64
+ - - "~>"
109
65
  - !ruby/object:Gem::Version
110
- version: '0'
111
- description: Ruby gem for Centrifugo real-time messaging server
66
+ version: 2.2.1
67
+ description: |
68
+ Provides helper classes Cent::Client and Cent::Notary.
69
+
70
+ `Cent::Client` is made to communicate to the server API
71
+ `Client::Notary` is a simple JWT wrapper to generate authorization tokens for the frontend
112
72
  email:
113
- - frvzmb@gmail.com
73
+ - prikha@gmail.com
114
74
  executables: []
115
75
  extensions: []
116
76
  extra_rdoc_files: []
117
- files: []
77
+ files:
78
+ - ".github/workflows/main.yml"
79
+ - ".github/workflows/release.yml"
80
+ - ".gitignore"
81
+ - ".rspec"
82
+ - ".rubocop.yml"
83
+ - CHANGELOG.md
84
+ - Gemfile
85
+ - LICENSE.txt
86
+ - README.md
87
+ - Rakefile
88
+ - bin/console
89
+ - bin/setup
90
+ - cent.gemspec
91
+ - lib/cent.rb
92
+ - lib/cent/client.rb
93
+ - lib/cent/error.rb
94
+ - lib/cent/http.rb
95
+ - lib/cent/notary.rb
96
+ - lib/cent/version.rb
118
97
  homepage: https://github.com/centrifugal/rubycent
119
98
  licenses:
120
99
  - MIT
121
- metadata: {}
100
+ metadata:
101
+ homepage_uri: https://github.com/centrifugal/rubycent
102
+ source_code_uri: https://github.com/centrifugal/rubycent
122
103
  post_install_message:
123
104
  rdoc_options: []
124
105
  require_paths:
@@ -127,15 +108,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
127
108
  requirements:
128
109
  - - ">="
129
110
  - !ruby/object:Gem::Version
130
- version: '0'
111
+ version: 2.5.0
131
112
  required_rubygems_version: !ruby/object:Gem::Requirement
132
113
  requirements:
133
114
  - - ">="
134
115
  - !ruby/object:Gem::Version
135
116
  version: '0'
136
117
  requirements: []
137
- rubygems_version: 3.0.3
118
+ rubygems_version: 3.0.3.1
138
119
  signing_key:
139
120
  specification_version: 4
140
- summary: Ruby gem for Centrifugo real-time messaging server
121
+ summary: Centrifugo API V2 Ruby Client
141
122
  test_files: []