strait 1.1.0 → 1.2.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 +4 -4
- data/.github/dependabot.yml +18 -0
- data/.github/workflows/release.yml +39 -0
- data/.github/workflows/test.yml +51 -0
- data/Gemfile.lock +28 -26
- data/LICENSE.txt +1 -12
- data/README.md +12 -9
- data/lib/strait/version.rb +1 -1
- data/lib/strait.rb +3 -3
- data/strait.gemspec +3 -3
- metadata +10 -7
- data/.travis.yml +0 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 459f330c3b15b42c2cd218e7bc60f4e1579288f60bb7e2cd6b286a970323f44d
|
|
4
|
+
data.tar.gz: 518f4012eeaa1170e0feddd5797f1b7777e47a0b0b64e5cd189978d14aa1c6ea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4185c8ad2907a75bc3577287193d35c5c7f35216d2ddd6c3e8a0d1e4063d2de043d735a38dc5f0d4134adf4fe0759311e3dbadf2bd5749be3d0e47b5a6692fb2
|
|
7
|
+
data.tar.gz: 21e760fc2801ffacff6a67f342ff7e0f204f4820c07503f0f9d830c2397b47b35c50427b2f4b0d4c2b3aef57029eb58fcb991cc852c7e58c9a4cdd22a5011fae
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: bundler
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: daily
|
|
7
|
+
time: "17:00"
|
|
8
|
+
timezone: America/Los_Angeles
|
|
9
|
+
open-pull-requests-limit: 10
|
|
10
|
+
reviewers:
|
|
11
|
+
- NuckChorris
|
|
12
|
+
ignore:
|
|
13
|
+
- dependency-name: connection_pool
|
|
14
|
+
versions:
|
|
15
|
+
- 2.2.4
|
|
16
|
+
- dependency-name: timecop
|
|
17
|
+
versions:
|
|
18
|
+
- 0.9.3
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Release to rubygems
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- "lib/strait/version.rb"
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
release:
|
|
12
|
+
name: Relase to Rubygems
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout Repository
|
|
17
|
+
uses: actions/checkout@v1
|
|
18
|
+
|
|
19
|
+
- name: Set up Ruby
|
|
20
|
+
uses: ruby/setup-ruby@v1
|
|
21
|
+
with:
|
|
22
|
+
ruby-version: 3.0
|
|
23
|
+
bundler-cache: true
|
|
24
|
+
|
|
25
|
+
- name: Authenticate with Rubygems
|
|
26
|
+
run: |
|
|
27
|
+
mkdir -p $HOME/.gem/
|
|
28
|
+
echo "${RUBYGEMS_CREDENTIALS}" > $HOME/.gem/credentials
|
|
29
|
+
chmod 0600 $HOME/.gem/credentials
|
|
30
|
+
env:
|
|
31
|
+
RUBYGEMS_CREDENTIALS: ${{ secrets.SENKO_SAN_RUBYGEMS_CREDENTIALS }}
|
|
32
|
+
|
|
33
|
+
- name: Publish Gem on Rubygems
|
|
34
|
+
run: bundle exec rake release:rubygem_push
|
|
35
|
+
|
|
36
|
+
- name: Create a Github Release
|
|
37
|
+
run: gh release create $(ruby -r './lib/strait/version' -e "puts Strait::VERSION") --target "${GITHUB_SHA}"
|
|
38
|
+
env:
|
|
39
|
+
GITHUB_TOKEN: ${{ secrets.SENKO_SAN_KEY }}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Strait Test Suite
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
# Branches from forks have the form 'user:branch-name' so we only run
|
|
7
|
+
# this job on pull_request events for branches that look like fork
|
|
8
|
+
# branches. Without this we would end up running this job twice for non
|
|
9
|
+
# forked PRs, once for the push and then once for opening the PR.
|
|
10
|
+
branches:
|
|
11
|
+
- "**:**"
|
|
12
|
+
|
|
13
|
+
env:
|
|
14
|
+
CC_TEST_REPORTER_ID: 1f7851d1df80cc24da6903abf795ee7a81a60b2cceb7eedd147c59c4ec232dd4
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
name: RSpec Test Suite
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
continue-on-error: ${{ matrix.experimental }}
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
ruby:
|
|
25
|
+
- ruby-2.6
|
|
26
|
+
- ruby-2.7
|
|
27
|
+
experimental: [false]
|
|
28
|
+
include:
|
|
29
|
+
- ruby: truffleruby-20
|
|
30
|
+
experimental: true
|
|
31
|
+
- ruby: ruby-3.0
|
|
32
|
+
experimental: true
|
|
33
|
+
- ruby: ruby-3.1
|
|
34
|
+
experimental: true
|
|
35
|
+
|
|
36
|
+
steps:
|
|
37
|
+
- name: Checkout Repository
|
|
38
|
+
uses: actions/checkout@v1
|
|
39
|
+
|
|
40
|
+
- name: Set up Ruby (${{ matrix.ruby }})
|
|
41
|
+
uses: ruby/setup-ruby@v1
|
|
42
|
+
with:
|
|
43
|
+
ruby-version: ${{ matrix.ruby }}
|
|
44
|
+
bundler-cache: true
|
|
45
|
+
|
|
46
|
+
- name: Run Tests
|
|
47
|
+
if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')"
|
|
48
|
+
run: bundle exec rspec
|
|
49
|
+
|
|
50
|
+
- name: Publish code coverage
|
|
51
|
+
uses: paambaati/codeclimate-action@v3.0.0
|
data/Gemfile.lock
CHANGED
|
@@ -1,39 +1,41 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
strait (1.
|
|
4
|
+
strait (1.2.0)
|
|
5
5
|
connection_pool (>= 2.0, < 3.0)
|
|
6
6
|
redis (~> 4.0, >= 3.0)
|
|
7
7
|
|
|
8
8
|
GEM
|
|
9
9
|
remote: https://rubygems.org/
|
|
10
10
|
specs:
|
|
11
|
-
connection_pool (2.2.
|
|
12
|
-
diff-lcs (1.
|
|
13
|
-
docile (1.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
rake (
|
|
17
|
-
redis (4.
|
|
18
|
-
rspec (3.
|
|
19
|
-
rspec-core (~> 3.
|
|
20
|
-
rspec-expectations (~> 3.
|
|
21
|
-
rspec-mocks (~> 3.
|
|
22
|
-
rspec-core (3.
|
|
23
|
-
rspec-support (~> 3.
|
|
24
|
-
rspec-expectations (3.
|
|
11
|
+
connection_pool (2.2.5)
|
|
12
|
+
diff-lcs (1.5.0)
|
|
13
|
+
docile (1.4.0)
|
|
14
|
+
mock_redis (0.31.0)
|
|
15
|
+
ruby2_keywords
|
|
16
|
+
rake (13.0.6)
|
|
17
|
+
redis (4.6.0)
|
|
18
|
+
rspec (3.11.0)
|
|
19
|
+
rspec-core (~> 3.11.0)
|
|
20
|
+
rspec-expectations (~> 3.11.0)
|
|
21
|
+
rspec-mocks (~> 3.11.0)
|
|
22
|
+
rspec-core (3.11.0)
|
|
23
|
+
rspec-support (~> 3.11.0)
|
|
24
|
+
rspec-expectations (3.11.0)
|
|
25
25
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
26
|
-
rspec-support (~> 3.
|
|
27
|
-
rspec-mocks (3.
|
|
26
|
+
rspec-support (~> 3.11.0)
|
|
27
|
+
rspec-mocks (3.11.1)
|
|
28
28
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
29
|
-
rspec-support (~> 3.
|
|
30
|
-
rspec-support (3.
|
|
31
|
-
|
|
29
|
+
rspec-support (~> 3.11.0)
|
|
30
|
+
rspec-support (3.11.0)
|
|
31
|
+
ruby2_keywords (0.0.5)
|
|
32
|
+
simplecov (0.21.2)
|
|
32
33
|
docile (~> 1.1)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
simplecov-html (0.
|
|
36
|
-
|
|
34
|
+
simplecov-html (~> 0.11)
|
|
35
|
+
simplecov_json_formatter (~> 0.1)
|
|
36
|
+
simplecov-html (0.12.3)
|
|
37
|
+
simplecov_json_formatter (0.1.4)
|
|
38
|
+
timecop (0.9.5)
|
|
37
39
|
|
|
38
40
|
PLATFORMS
|
|
39
41
|
ruby
|
|
@@ -41,11 +43,11 @@ PLATFORMS
|
|
|
41
43
|
DEPENDENCIES
|
|
42
44
|
bundler (~> 2.0)
|
|
43
45
|
mock_redis (~> 0.21)
|
|
44
|
-
rake (~>
|
|
46
|
+
rake (~> 13.0)
|
|
45
47
|
rspec (~> 3.0)
|
|
46
48
|
simplecov (~> 0.17)
|
|
47
49
|
strait!
|
|
48
50
|
timecop (~> 0.9)
|
|
49
51
|
|
|
50
52
|
BUNDLED WITH
|
|
51
|
-
2.
|
|
53
|
+
2.3.13
|
data/LICENSE.txt
CHANGED
|
@@ -175,18 +175,7 @@
|
|
|
175
175
|
|
|
176
176
|
END OF TERMS AND CONDITIONS
|
|
177
177
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
To apply the Apache License to your work, attach the following
|
|
181
|
-
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
-
replaced with your own identifying information. (Don't include
|
|
183
|
-
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
-
comment syntax for the file format. We also recommend that a
|
|
185
|
-
file or class name and description of purpose be included on the
|
|
186
|
-
same "printed page" as the copyright notice for easier
|
|
187
|
-
identification within third-party archives.
|
|
188
|
-
|
|
189
|
-
Copyright 2019 Kitsu, Inc.
|
|
178
|
+
Copyright 2021 Kitsu, Inc.
|
|
190
179
|
|
|
191
180
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
181
|
you may not use this file except in compliance with the License.
|
data/README.md
CHANGED
|
@@ -2,16 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
[![Coverage][shield-coverage]][coverage]
|
|
4
4
|
[![Maintainability][shield-maintainability]][maintainability]
|
|
5
|
-
[![
|
|
5
|
+
[![Github Actions][shield-actions]][actions]
|
|
6
|
+
[![Rubygem Version][shield-version]][version]
|
|
6
7
|
|
|
7
8
|
[shield-coverage]: https://img.shields.io/codeclimate/coverage/hummingbird-me/strait.svg?logo=code-climate&style=for-the-badge
|
|
8
9
|
[coverage]: https://codeclimate.com/github/hummingbird-me/strait/progress/coverage
|
|
9
10
|
[shield-maintainability]: https://img.shields.io/codeclimate/maintainability/hummingbird-me/strait.svg?logo=code-climate&style=for-the-badge
|
|
10
11
|
[maintainability]: https://codeclimate.com/github/hummingbird-me/strait/progress/maintainability
|
|
11
|
-
[shield-
|
|
12
|
-
[
|
|
12
|
+
[shield-actions]: https://img.shields.io/github/checks-status/hummingbird-me/strait/main?style=for-the-badge
|
|
13
|
+
[actions]: https://github.com/hummingbird-me/strait/actions
|
|
14
|
+
[shield-version]: https://img.shields.io/gem/v/strait?label=%20&logo=rubygems&logoColor=white&style=for-the-badge
|
|
15
|
+
[version]: https://rubygems.org/gems/strait
|
|
13
16
|
|
|
14
|
-
Strait is a rate-limiting library designed to provide security you don't need to think about.
|
|
17
|
+
Strait is a rate-limiting library designed to provide security you don't need to think about. Whenever you have code to protect, put a Strait in front of it.
|
|
15
18
|
|
|
16
19
|
It strikes an excellent balance between accuracy and memory usage, with a default accuracy of 1/60th of the limit period.
|
|
17
20
|
|
|
@@ -43,7 +46,7 @@ class SecureThingController
|
|
|
43
46
|
end
|
|
44
47
|
```
|
|
45
48
|
|
|
46
|
-
Well dang, that's no good.
|
|
49
|
+
Well dang, that's no good. Anybody could send thousands of requests to this and take your entire site down, right as you're meeting with an important investor!
|
|
47
50
|
|
|
48
51
|
Let's put a Strait in front of it!
|
|
49
52
|
|
|
@@ -64,15 +67,15 @@ class SecureThingController
|
|
|
64
67
|
end
|
|
65
68
|
```
|
|
66
69
|
|
|
67
|
-
Viola, just like that, we've got rate limiting.
|
|
70
|
+
Viola, just like that, we've got rate limiting. Now a user is limited to 5 per minute!
|
|
68
71
|
|
|
69
72
|
## Accuracy
|
|
70
73
|
|
|
71
|
-
To understand why Strait isn't perfectly accurate, we should understand how it's implemented.
|
|
74
|
+
To understand why Strait isn't perfectly accurate, we should understand how it's implemented. Strait is based on [the bucketed-log pattern made popular by Figma][figma-post], which chooses lower memory usage over perfect accuracy. Despite this decreased accuracy, it fails secure, and should have enough accuracy to not be noticed.
|
|
72
75
|
|
|
73
|
-
Each rate limiter stores data as a set of _N buckets per period_.
|
|
76
|
+
Each rate limiter stores data as a set of _N buckets per period_. For example, with 10 buckets and a 1-hour period, each bucket covers 6 minutes. To check the limit, we sum all buckets which overlap the last hour. If the buckets are large (like 6 minutes) this can be up to one bucket longer than the period, resulting in a longer block than 100% accuracy.
|
|
74
77
|
|
|
75
|
-
The default accuracy in Strait is _60 buckets per period_.
|
|
78
|
+
The default accuracy in Strait is _60 buckets per period_. For a 1-hour period, this is up to 1 minute of inaccuracy. For a 1-minute period, it's up to 1-second. For a 1-day period, it's up to 24 minutes. You can adjust this to increase accuracy, but it will also use more memory.
|
|
76
79
|
|
|
77
80
|
[figma-post]: https://www.figma.com/blog/an-alternative-approach-to-rate-limiting/
|
|
78
81
|
|
data/lib/strait/version.rb
CHANGED
data/lib/strait.rb
CHANGED
|
@@ -10,12 +10,12 @@ require 'strait/version'
|
|
|
10
10
|
class Strait
|
|
11
11
|
attr_reader :name, :config
|
|
12
12
|
|
|
13
|
-
def initialize(name, rules: [], **config)
|
|
13
|
+
def initialize(name, rules: [], **config, &block)
|
|
14
14
|
@name = name
|
|
15
15
|
@raw_rules = rules
|
|
16
16
|
@config = Strait::Configuration.default.merge(config)
|
|
17
17
|
|
|
18
|
-
@raw_rules += Strait::DSL.new(&
|
|
18
|
+
@raw_rules += Strait::DSL.new(&block).rules unless block.nil?
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def limit!(user)
|
|
@@ -26,7 +26,7 @@ class Strait
|
|
|
26
26
|
|
|
27
27
|
# Raise an exception for the first rate limit hit
|
|
28
28
|
results.each do |rule, acceptable|
|
|
29
|
-
raise Strait::RateLimitExceeded
|
|
29
|
+
raise Strait::RateLimitExceeded.new(**rule.to_h) unless acceptable
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
data/strait.gemspec
CHANGED
|
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
|
8
8
|
spec.authors = ['Emma Lejeck']
|
|
9
9
|
spec.email = ['nuck@kitsu.io']
|
|
10
10
|
|
|
11
|
-
spec.summary = 'Rate-limiting to defend your nation-state'
|
|
11
|
+
spec.summary = 'Rate-limiting to defend your nation-state from pillagers'
|
|
12
12
|
spec.description = <<~DESC
|
|
13
13
|
Strait is a rate-limiting library designed to provide security you don't need to think about.
|
|
14
14
|
Whenever you have code to protect, put a Strait in front of it.
|
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
|
|
19
19
|
spec.metadata['homepage_uri'] = spec.homepage
|
|
20
20
|
spec.metadata['source_code_uri'] = 'https://github.com/hummingbird-me/strait'
|
|
21
|
-
|
|
21
|
+
spec.metadata["changelog_uri"] = "https://github.com/hummingbird-me/strait/releases"
|
|
22
22
|
|
|
23
23
|
# Specify which files should be added to the gem when it is released.
|
|
24
24
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
|
31
31
|
|
|
32
32
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
|
33
33
|
spec.add_development_dependency 'mock_redis', '~> 0.21'
|
|
34
|
-
spec.add_development_dependency 'rake', '~>
|
|
34
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
35
35
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
36
36
|
spec.add_development_dependency 'simplecov', '~> 0.17'
|
|
37
37
|
spec.add_development_dependency 'timecop', '~> 0.9'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: strait
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Emma Lejeck
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-05-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -44,14 +44,14 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
47
|
+
version: '13.0'
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
54
|
+
version: '13.0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: rspec
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -144,10 +144,12 @@ extensions: []
|
|
|
144
144
|
extra_rdoc_files: []
|
|
145
145
|
files:
|
|
146
146
|
- ".editorconfig"
|
|
147
|
+
- ".github/dependabot.yml"
|
|
148
|
+
- ".github/workflows/release.yml"
|
|
149
|
+
- ".github/workflows/test.yml"
|
|
147
150
|
- ".gitignore"
|
|
148
151
|
- ".rspec"
|
|
149
152
|
- ".rubocop.yml"
|
|
150
|
-
- ".travis.yml"
|
|
151
153
|
- Gemfile
|
|
152
154
|
- Gemfile.lock
|
|
153
155
|
- LICENSE.txt
|
|
@@ -168,6 +170,7 @@ licenses:
|
|
|
168
170
|
metadata:
|
|
169
171
|
homepage_uri: https://github.com/hummingbird-me/strait
|
|
170
172
|
source_code_uri: https://github.com/hummingbird-me/strait
|
|
173
|
+
changelog_uri: https://github.com/hummingbird-me/strait/releases
|
|
171
174
|
post_install_message:
|
|
172
175
|
rdoc_options: []
|
|
173
176
|
require_paths:
|
|
@@ -183,8 +186,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
183
186
|
- !ruby/object:Gem::Version
|
|
184
187
|
version: '0'
|
|
185
188
|
requirements: []
|
|
186
|
-
rubygems_version: 3.
|
|
189
|
+
rubygems_version: 3.3.7
|
|
187
190
|
signing_key:
|
|
188
191
|
specification_version: 4
|
|
189
|
-
summary: Rate-limiting to defend your nation-state
|
|
192
|
+
summary: Rate-limiting to defend your nation-state from pillagers
|
|
190
193
|
test_files: []
|
data/.travis.yml
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
sudo: false
|
|
3
|
-
language: ruby
|
|
4
|
-
cache: bundler
|
|
5
|
-
rvm:
|
|
6
|
-
- 2.6.3
|
|
7
|
-
env:
|
|
8
|
-
global:
|
|
9
|
-
- CC_TEST_REPORTER_ID=1f7851d1df80cc24da6903abf795ee7a81a60b2cceb7eedd147c59c4ec232dd4
|
|
10
|
-
|
|
11
|
-
before_install: gem install bundler -v 2.0.2
|
|
12
|
-
before_script:
|
|
13
|
-
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
|
14
|
-
- chmod +x ./cc-test-reporter
|
|
15
|
-
- ./cc-test-reporter before-build
|
|
16
|
-
script:
|
|
17
|
-
- bundle exec rspec
|
|
18
|
-
after_script:
|
|
19
|
-
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|