cent 0.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []