cable_x 0.1.0 → 0.1.5

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: 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