cable_x 0.1.0 → 0.1.5

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: 76917008d7ce08585ee10c4920f94f7fea9e52fcd04f031617cc94689f7034f1
4
- data.tar.gz: ea77fe44decf6ce838664e1af8a4c71680274b31fb6119c8af8c2592c1692f59
3
+ metadata.gz: 0ae31a8435e6fcf9142eb27dbd761a8ee99525efe91f5c439ecffa0b6429b090
4
+ data.tar.gz: 474f402b907b5288b4a41d2217421805bb7746a08389c86e4c8df2a898e88c90
5
5
  SHA512:
6
- metadata.gz: 6bcec2f189429bc13d423c35b67cc496f4d40894439a1c81ac5fe437ea1c94909d9665f811ddc6298e4e4fb316985bce15494fe96fe9cc340f5e4208cb7d490e
7
- data.tar.gz: 1ed2df1944dc39fadee3ded7de04f489574e54e7d82d8c252a883065aae964dbaa37dec34b7c1a6d7792d7e44ad9c2c9fbd5113f54d7b5059b7d0bc0efaa499c
6
+ metadata.gz: 716524bc5935eefbe1df7c52806ff5eb91584c45d301cc4d28913a04903791d58f974e6419089ad0224ba1c98a31368e282297fdacd8e178b78b889e9eb116a1
7
+ data.tar.gz: 9c058b68e43f8ef0d519b6299ed3be6e1adb53271741c90b24521b12871316ab5e02862e857fee99af101206bf1339eff495c5cb1648a149dacf9a73d6ee459e
data/README.md CHANGED
@@ -1,8 +1,14 @@
1
+ [![Maintainability](https://api.codeclimate.com/v1/badges/58f79a904f11911be561/maintainability)](https://codeclimate.com/github/Code-Vedas/rails-cable-x/maintainability)
2
+ ![](https://ruby-gem-downloads-badge.herokuapp.com/cable_x?type=total&color=brightgreen)
3
+ [![Gem Version](https://badge.fury.io/rb/cable_x.svg)](https://badge.fury.io/rb/cable_x)
4
+ [![Coverage Status](https://coveralls.io/repos/github/Code-Vedas/rails-cable-x/badge.svg?branch=master)](https://coveralls.io/github/Code-Vedas/rails-cable-x?branch=master)
5
+ [![Build Status](https://travis-ci.com/code-vedas/rails-cable-x.svg?branch=master)](https://travis-ci.com/code-vedas/rails-cable-x)
6
+
1
7
  # CableX
2
- Short description and motivation.
8
+ Standard MVC over cable for realtime applications to enjoy seamless experience over cable. Use specialized clients for [Angular](https://github.com/Code-Vedas/ngx-cable-x),[JS](https://github.com/Code-Vedas/cable-x-js),[React](https://github.com/Code-Vedas/cable-x-js),Android, IOS
3
9
 
10
+ Clients for Android, IOS, Angular, React, JS coming soon.
4
11
  ## Usage
5
- How to use my plugin.
6
12
 
7
13
  ## Installation
8
14
  Add this line to your application's Gemfile:
@@ -1,15 +1,74 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative './rate_limit/block_check'
4
+ require_relative './rate_limit/rate_limit'
5
+ require_relative './rate_limit/rate_limit_redis'
6
+
3
7
  module CableX
4
8
  module Cable
5
9
  ##
6
10
  # Connection class to serve entry point
7
11
  class Connection < ActionCable::Connection::Base
8
- attr_accessor :device_id
12
+ include RateLimit::RateLimitRedis
13
+ include RateLimit::CheckRateLimit
14
+ include RateLimit::BlockCheck
15
+
16
+ class << self
17
+ attr_accessor :rate_limit, :redis_config
18
+ end
19
+
20
+ attr_accessor :device_id, :rate_limit, :redis_config, :redis
9
21
  identified_by :device_id
10
22
 
11
23
  def connect
12
- self.device_id = SecureRandom.hex(20)
24
+ self.device_id = Digest::SHA1.hexdigest(request_str)
25
+ setup_rate_limit
26
+ rescue StandardError => _e
27
+ reject_unauthorized_connection
28
+ end
29
+
30
+ def receive(message)
31
+ if (blocked_unit = check_block) || (blocked_unit = do_rate_limit)
32
+ disconnect_client(blocked_unit)
33
+ elsif check_message(message)
34
+ super(message)
35
+ else
36
+ malformed_message_response
37
+ end
38
+ end
39
+
40
+ def close(reason, reconnect = false)
41
+ transmit(type: ActionCable::INTERNAL[:message_types][:disconnect],
42
+ reason: reason,
43
+ reconnect: reconnect)
44
+ websocket.close
45
+ end
46
+
47
+ def malformed_message_response
48
+ transmit(type: 'error',
49
+ message: 'malformed_message')
50
+ end
51
+
52
+ def check_message(message)
53
+ JSON.parse(message) rescue false
54
+ end
55
+
56
+ def setup_rate_limit
57
+ self.rate_limit = self.class.rate_limit
58
+ self.redis_config = self.class.redis_config
59
+ if rate_limit
60
+ self.redis = Redis.new(url: redis_config[:url])
61
+ raise StandardError, 'Rate limiting: Slow down!. Try after some time' if check_block
62
+ end
63
+ true
64
+ end
65
+
66
+ def request_str
67
+ headers_to_get = %w[SERVER_PROTOCOL SERVER_SOFTWARE REQUEST_METHOD REQUEST_PATH HTTP_USER_AGENT\
68
+ HTTP_CONNECTION HTTP_ORIGIN REMOTE_ADDR ORIGINAL_FULLPATH ORIGINAL_SCRIPT_NAME\
69
+ action_dispatch.authorized_host]
70
+ headers = request.headers.to_h
71
+ headers_to_get.map { |key| headers[key] }.join('-').gsub(' ', '')
13
72
  end
14
73
  end
15
74
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CableX
4
+ module Cable
5
+ module RateLimit
6
+ ##
7
+ # Process Rate Limit
8
+ module BlockCheck
9
+ def check_block
10
+ check_block_unit('second') || check_block_unit('minute') || check_block_unit('hour') if rate_limit
11
+ end
12
+
13
+ def check_block_unit(unit)
14
+ unit if redis_exists block_device_key(unit)
15
+ end
16
+
17
+ def block_device(unit)
18
+ redis_set block_device_key(unit), true, rate_limit[:cool_down].send('second') * 1000
19
+ unit
20
+ end
21
+
22
+ def disconnect_client(unit)
23
+ close("Rate limiting: Limit exceeded for per #{unit} Slow down!. Try after some time", false)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ # "Rate limiting: Slow down!. Try after some time"
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CableX
4
+ module Cable
5
+ module RateLimit
6
+ ##
7
+ # Process Rate Limit
8
+ module CheckRateLimit
9
+ def do_rate_limit
10
+ check_rate_limit if rate_limit
11
+ end
12
+
13
+ def check_rate_limit
14
+ check_unit('second') || check_unit('minute') || check_unit('hour')
15
+ end
16
+
17
+ def check_unit(unit)
18
+ check_value = rate_limit[unit.to_s.to_sym]
19
+ return unless check_value
20
+
21
+ key = device_key unit
22
+ redis_set key, 0, 1.send(unit) * 1000 unless redis_exists(key)
23
+ redis_incr key
24
+ block_connection = (redis_get(key) || -1).to_i >= check_value
25
+ return unless block_connection
26
+
27
+ block_device unit
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CableX
4
+ module Cable
5
+ module RateLimit
6
+ ##
7
+ # Process Rate Limit
8
+ module RateLimitRedis
9
+ def redis_set(key, value, expire_millisecond)
10
+ redis.set key, value, px: expire_millisecond
11
+ end
12
+
13
+ def redis_incr(key)
14
+ redis.incr key
15
+ end
16
+
17
+ def redis_exists(key)
18
+ redis.exists? key
19
+ end
20
+
21
+ def redis_get(key)
22
+ redis.get key
23
+ end
24
+
25
+ def device_key(schedule)
26
+ "#{redis_config[:channel_prefix]}-rl-#{schedule}-#{device_id}"
27
+ end
28
+
29
+ def block_device_key(schedule)
30
+ "#{redis_config[:channel_prefix]}-rl-block-#{schedule}-#{device_id}"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -12,12 +12,21 @@ module CableX
12
12
  isolate_namespace CableX
13
13
 
14
14
  def self.server
15
- config = Rails.application.config_for(:cable_x) rescue nil
16
- self.allowed_request_origins = config[:allowed_request_origins] if config
15
+ setup_rate_limiting
17
16
  server = CableX::Server.server
18
17
  server.config.connection_class = -> { CableX::Cable::Connection }
19
18
  server.config.allowed_request_origins = allowed_request_origins
20
19
  server
21
20
  end
21
+
22
+ def self.setup_rate_limiting
23
+ cable_config = Rails.application.config_for(:cable) rescue nil
24
+ cable_x_config = Rails.application.config_for(:cable_x) rescue nil
25
+ self.allowed_request_origins = cable_x_config[:allowed_request_origins]
26
+ return unless cable_x_config && cable_config && cable_config[:adapter] == 'redis'
27
+
28
+ CableX::Cable::Connection.redis_config = cable_config
29
+ CableX::Cable::Connection.rate_limit = cable_x_config[:rate_limit]
30
+ end
22
31
  end
23
32
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CableX
4
- VERSION = '0.1.0'
4
+ VERSION = File.read('Version').split("\n").first.gsub('v', '')
5
5
  end
metadata CHANGED
@@ -1,57 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cable_x
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nitesh Purohit
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-20 00:00:00.000000000 Z
11
+ date: 2020-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '5.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '5.1'
27
- - !ruby/object:Gem::Dependency
28
- name: coveralls
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: 0.8.23
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: 0.8.23
41
- - !ruby/object:Gem::Dependency
42
- name: rspec-rails
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: 4.0.0
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: 4.0.0
55
27
  description: Standard MVC over cable for realtime applications to enjoy seamless experience
56
28
  over cable. Use specialized clients for Android, IOS, Angular, React, JS
57
29
  email:
@@ -66,6 +38,9 @@ files:
66
38
  - lib/cable_x.rb
67
39
  - lib/cable_x/cable/channel.rb
68
40
  - lib/cable_x/cable/connection.rb
41
+ - lib/cable_x/cable/rate_limit/block_check.rb
42
+ - lib/cable_x/cable/rate_limit/rate_limit.rb
43
+ - lib/cable_x/cable/rate_limit/rate_limit_redis.rb
69
44
  - lib/cable_x/channel/cable_x_channel.rb
70
45
  - lib/cable_x/channel/process/controller.rb
71
46
  - lib/cable_x/channel/process/request.rb
@@ -99,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
74
  - !ruby/object:Gem::Version
100
75
  version: 1.8.11
101
76
  requirements: []
102
- rubygems_version: 3.0.3
77
+ rubygems_version: 3.0.8
103
78
  signing_key:
104
79
  specification_version: 4
105
80
  summary: Standard MVC over cable for realtime applications to enjoy seamless experience