cors 1.0.0 → 1.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6e34544029bab24989baf0b992473455fe72c74dc16f8abd9fae3bd48dad3738
4
+ data.tar.gz: 2b86a4a89e1577d08051d5599d44bcb43f2fd90fc04da1688c196cc4b4ad161d
5
+ SHA512:
6
+ metadata.gz: 347db7c99d84fff7342fc6f5c57574caf02135b6a4a87bdd2886afcaa9f1d4d6191a5c187a7b6454161786ea42198ed058329ea7a6ede863b6cae951f45a5b7f
7
+ data.tar.gz: e38b7fbb900d6507acc746348b85b8979264be0619f58f2e1611e77539994300f4ccc5e0bc8e91385e856a3df7168ec8ea781d8dfea1caf5ee295a77f38ee647
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  .yardoc/
2
2
  doc/
3
+ pkg/
@@ -1,24 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cors (1.0.1)
5
+ multi_json
6
+
1
7
  GEM
2
- remote: http://rubygems.org/
8
+ remote: https://rubygems.org/
3
9
  specs:
4
- diff-lcs (1.1.3)
5
- rake (0.9.2.2)
6
- redcarpet (2.1.1)
7
- rspec (2.11.0)
8
- rspec-core (~> 2.11.0)
9
- rspec-expectations (~> 2.11.0)
10
- rspec-mocks (~> 2.11.0)
11
- rspec-core (2.11.1)
12
- rspec-expectations (2.11.3)
13
- diff-lcs (~> 1.1.3)
14
- rspec-mocks (2.11.3)
15
- yard (0.8.2.1)
10
+ diff-lcs (1.3)
11
+ multi_json (1.13.1)
12
+ rake (12.3.3)
13
+ rspec (3.8.0)
14
+ rspec-core (~> 3.8.0)
15
+ rspec-expectations (~> 3.8.0)
16
+ rspec-mocks (~> 3.8.0)
17
+ rspec-core (3.8.2)
18
+ rspec-support (~> 3.8.0)
19
+ rspec-expectations (3.8.4)
20
+ diff-lcs (>= 1.2.0, < 2.0)
21
+ rspec-support (~> 3.8.0)
22
+ rspec-mocks (3.8.1)
23
+ diff-lcs (>= 1.2.0, < 2.0)
24
+ rspec-support (~> 3.8.0)
25
+ rspec-support (3.8.2)
26
+ yard (0.9.20)
16
27
 
17
28
  PLATFORMS
18
29
  ruby
19
30
 
20
31
  DEPENDENCIES
32
+ cors!
21
33
  rake
22
- redcarpet
23
34
  rspec
24
35
  yard
36
+
37
+ BUNDLED WITH
38
+ 1.16.6
data/README.md CHANGED
@@ -1,15 +1,22 @@
1
- # CORS policy validation- and signing library
1
+ # CORS policy validation- and signing library
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/elabs/cors.png)](http://travis-ci.org/elabs/cors)
3
+ [![Build Status](https://secure.travis-ci.org/varvet/cors.png)](http://travis-ci.org/varvet/cors)
4
4
 
5
5
  Cross-origin resource sharing (CORS) is great; it allows your visitors to asynchronously upload files to
6
- e.g. Filepicker or Amazon S3, without the files having to round-trip through your web server. Unfortunately,
6
+ e.g. Amazon S3, without the files having to round-trip through your web server. Unfortunately,
7
7
  giving your users complete write access to your online storage also exposes you to malicious intent.
8
8
 
9
9
  To combat harmful usage, good upload services that allow client-side upload, support a mechanism that allows
10
10
  you to validate and sign all upload requests to your online storage. By validating every request, you can
11
11
  give your visitors a nice upload experience, while keeping the bad visitors at bay.
12
12
 
13
+ ## Deprecation
14
+
15
+ The functionality of CORS is now provided by the ruby AWS SDK. We recommend
16
+ using that instead, as CORS will no longer receive updates:
17
+
18
+ [Amazon S3 SDK PresignedPost](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/PresignedPost.html)
19
+
13
20
  ## Usage
14
21
 
15
22
  ```ruby
@@ -36,10 +43,10 @@ end
36
43
 
37
44
  ## Supported services
38
45
 
39
- Out-of-the box, the CORS library comes with support for the Amazon S3 REST API. Support
40
- for Filepicker is planned.
46
+ Out-of-the box, the CORS library comes with support for the Amazon S3 REST API.
41
47
 
42
- - [Amazon S3 REST API](http://docs.amazonwebservices.com/AmazonS4/latest/dev/RESTAuthentication.html)
48
+ - [Amazon S3 REST API Authentication Header](http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAuthentication.html#ConstructingTheAuthenticationHeader)
49
+ - [Amazon S3 REST API POST Upload Policy](http://docs.amazonwebservices.com/AmazonS3/latest/dev/HTTPPOSTForms.html#HTTPPOSTConstructPolicy)
43
50
 
44
51
  ## License
45
52
 
@@ -10,7 +10,7 @@ Gem::Specification.new do |gem|
10
10
  gem.email = ["kim@burgestrand.se"]
11
11
  gem.homepage = "http://github.com/elabs/cors"
12
12
  gem.summary = "CORS policy validation- and signing library for Amazon S3 REST API."
13
- gem.description = <<-DESCRIPTION.gsub(/ +/, "")
13
+ gem.description = <<~DESCRIPTION
14
14
  Cross-origin resource sharing (CORS) is great; it allows your visitors to
15
15
  asynchronously upload files to e.g. Filepicker or Amazon S3, without the
16
16
  files having to round-trip through your web server. Unfortunately, giving
@@ -25,11 +25,18 @@ Gem::Specification.new do |gem|
25
25
 
26
26
  The CORS gem comes with support for the Amazon S3 REST API.
27
27
  DESCRIPTION
28
+ gem.post_install_message = <<~POST_INSTALL_MESSAGE
29
+ [DEPRECATED] The CORS gem is deprecated and will not receive further updates.
30
+ The functionality of CORS is now provided by the ruby AWS SDK:
31
+
32
+ https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/PresignedPost.html
33
+ POST_INSTALL_MESSAGE
28
34
 
29
35
  gem.files = `git ls-files`.split($/)
30
36
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
31
37
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
32
38
  gem.require_paths = ["lib"]
33
39
 
34
- gem.add_development_dependency "rspec", "~> 2.0"
40
+ gem.add_dependency "multi_json"
41
+ gem.add_development_dependency "rspec"
35
42
  end
@@ -3,6 +3,7 @@ require "cors/version"
3
3
  require "cors/rules"
4
4
  require "cors/policy"
5
5
  require "cors/policy/s3"
6
+ require "cors/policy/s3_post"
6
7
 
7
8
  # CORS policy validation and signature generation.
8
9
  #
@@ -71,7 +71,7 @@ module CORS
71
71
  # @see errors
72
72
  # @see valid?
73
73
  def initialize(attributes)
74
- self.attributes = Hash[attributes.map { |k, v| [k.to_s.downcase, v] }]
74
+ self.attributes = Hash[normalize_attributes(attributes)]
75
75
  self.errors = rules.validate(self.attributes)
76
76
  end
77
77
 
@@ -94,16 +94,25 @@ module CORS
94
94
  errors.empty?
95
95
  end
96
96
 
97
- # @note must be overridden by includers!
98
- # @return [String] the compiled manifest
99
- def manifest
100
- raise NotImplementedError, "#manifest has not been defined on #{inspect}"
97
+ # Signs the manifest, but only if it is {#valid?}.
98
+ #
99
+ # @note should not be overridden by the includers!
100
+ # @return (see #sign!)
101
+ def sign(*args, &block)
102
+ sign!(*args, &block) if valid?
101
103
  end
102
104
 
103
- # @note must be overridden by includers!
105
+ # @note should be overridden by includers!
104
106
  # @return [String] signature derived from the manifest
105
- def sign(*)
107
+ def sign!(*)
106
108
  raise NotImplementedError, "#sign has not been defined on #{inspect}"
107
109
  end
110
+
111
+ protected
112
+
113
+ def normalize_attributes(attributes)
114
+ attributes = attributes.map { |k, v| [k.to_s.downcase, v] }
115
+ attributes.select { |(k, _)| rules[k] }
116
+ end
108
117
  end
109
118
  end
@@ -28,8 +28,7 @@ module CORS::Policy
28
28
  #
29
29
  # @param [String] access_key
30
30
  # @param [String] secret_access_key
31
- def sign(access_key, secret_access_key)
32
- return if not valid?
31
+ def sign!(access_key, secret_access_key)
33
32
  digest = OpenSSL::HMAC.digest("sha1", secret_access_key, manifest)
34
33
  signature = Base64.strict_encode64(digest)
35
34
  "AWS #{access_key}:#{signature}"
@@ -0,0 +1,66 @@
1
+ # encoding: utf-8
2
+ require "multi_json"
3
+ require "base64"
4
+ require "time"
5
+ require "set"
6
+
7
+ module CORS::Policy
8
+ # POST form upload policy for Amazon S3.
9
+ class S3Post
10
+ include CORS::Policy
11
+
12
+ # Generate the policy used to sign the request.
13
+ #
14
+ # @param [Time] expiration
15
+ # @return [Hash] policy as a hash
16
+ def policy(expiration)
17
+ conditions = []
18
+ properties = attributes.dup
19
+
20
+ if properties.has_key?("content-length")
21
+ length = escape(properties.delete("content-length"))
22
+ conditions << [ "content-length-range", length, length ]
23
+ end
24
+
25
+ {
26
+ "expiration" => expiration.gmtime.iso8601,
27
+ "conditions" => conditions + properties.map do |(name, value)|
28
+ [ "eq", "$#{escape(name)}", escape(value) ]
29
+ end
30
+ }
31
+ end
32
+
33
+ # Generate a policy and encode it in URL-safe Base64 encoding.
34
+ #
35
+ # @param [Time] expiration
36
+ # @return [String] the policy, in JSON, in URL-safe base64 encoding.
37
+ def policy_base64(expiration)
38
+ json = MultiJson.dump(policy(expiration))
39
+ Base64.urlsafe_encode64(json)
40
+ end
41
+
42
+ # Sign the {#policy} for the given expiration.
43
+ #
44
+ # @param [String] secret_access_key
45
+ # @param [Time] expiration
46
+ # @return [String] signed policy in Base64-encoding.
47
+ def sign!(secret_access_key, expiration)
48
+ digest = OpenSSL::HMAC.digest("sha1", secret_access_key, policy_base64(expiration))
49
+ Base64.strict_encode64(digest)
50
+ end
51
+
52
+ protected
53
+
54
+ def escape(string)
55
+ return string unless string.is_a?(String)
56
+
57
+ unicode_safe = string.codepoints.each_with_object("") do |i, result|
58
+ result << if i <= 127 then i.chr else
59
+ "\\u#{i.to_s(16).rjust(4, "0")}"
60
+ end
61
+ end
62
+
63
+ unicode_safe.sub(/\A$/, "\$")
64
+ end
65
+ end
66
+ end
@@ -15,6 +15,7 @@ module CORS
15
15
  # @yieldparam [Rules] self
16
16
  def initialize
17
17
  @rules = []
18
+ @rules_map = Hash.new { |h, k| h[k] = [] }
18
19
  yield self if block_given?
19
20
  end
20
21
 
@@ -40,6 +41,14 @@ module CORS
40
41
  end
41
42
  end
42
43
 
44
+ # Retrieve a list of rules for a given attribute.
45
+ #
46
+ # @param name same name as given to {#required} or {#optional}
47
+ # @return [Array<Hash<:name, :matcher, :required>>, nil] list of rules for attribute, or nil.
48
+ def [](name)
49
+ @rules_map.fetch(name, nil)
50
+ end
51
+
43
52
  # Declare a required rule; the value must be present, and it must
44
53
  # match the given constraints or block matcher.
45
54
  #
@@ -76,6 +85,7 @@ module CORS
76
85
 
77
86
  { name: name, matcher: matcher, required: true }.tap do |rule|
78
87
  @rules << rule
88
+ @rules_map[name] << rule
79
89
  end
80
90
  end
81
91
 
@@ -1,4 +1,4 @@
1
1
  module CORS
2
2
  # @see http://semver.org/
3
- VERSION = "1.0.0"
3
+ VERSION = "1.0.1"
4
4
  end
@@ -0,0 +1,60 @@
1
+ describe CORS::Policy::S3Post do
2
+ let(:now) do
3
+ Time.at(1351696066)
4
+ end
5
+
6
+ let(:valid_attributes) do
7
+ {
8
+ "bucket" => "shokunin",
9
+ "key" => "upload/BEEFBEEFBEEF.jpg",
10
+ "x-amz-meta-filename" => "$dollar$.jpg",
11
+ "acl" => "public-read",
12
+ "content-type" => "image/jpeg",
13
+ "content-length" => 678,
14
+ }
15
+ end
16
+
17
+ let(:rules) do
18
+ lambda do |manifest|
19
+ manifest.required "bucket", "shokunin"
20
+ manifest.required "key", %r!\Aupload/[a-f0-9A-F]{12}\.(jpg|png)!
21
+ manifest.required "acl", "public-read"
22
+ manifest.optional "x-amz-meta-filename", //
23
+ manifest.required "content-type", %r|\Aimage/|
24
+ manifest.required "content-length" do |bytesize|
25
+ (0..1024).cover?(bytesize)
26
+ end
27
+ end
28
+ end
29
+
30
+ let(:manifest) { CORS::Policy::S3Post.create(&rules) }
31
+
32
+ describe "#manifest" do
33
+ it "generates the policy document as a hash" do
34
+ policy = manifest.new(valid_attributes).policy(now)
35
+ expect(policy["conditions"]).to eq([
36
+ [ "content-length-range", 678, 678 ],
37
+ [ "eq", "$bucket", "shokunin" ],
38
+ [ "eq", "$key", "upload/BEEFBEEFBEEF.jpg" ],
39
+ [ "eq", "$x-amz-meta-filename", "\$dollar$.jpg" ],
40
+ [ "eq", "$acl", "public-read" ],
41
+ [ "eq", "$content-type", "image/jpeg" ],
42
+ ])
43
+ end
44
+ end
45
+
46
+ describe "#policy" do
47
+ it "returns the Base64-encoded manifest" do
48
+ request = manifest.new(valid_attributes)
49
+ decoded = Base64.urlsafe_decode64(request.policy_base64(now))
50
+ expect(MultiJson.load(decoded)).to eq(request.policy(now))
51
+ end
52
+ end
53
+
54
+ describe "#sign!" do
55
+ it "unconditionally signs the manifest" do
56
+ request = manifest.new(valid_attributes)
57
+ expect(request.sign!("properties", now)).to eq("U1YETIAOqT9mEuCebm5B6BM6feQ=")
58
+ end
59
+ end
60
+ end
@@ -7,7 +7,7 @@ describe CORS::Policy::S3 do
7
7
  "x-amz-meta-filename" => "roflcopter.gif",
8
8
  "x-amz-date" => "2012-10-22T16:10:47+02:00",
9
9
  "x-amz-meta-ROFLCOPTER" => ["yes", "no", "maybe"],
10
- "x-not-amz-header" => "I am ignored",
10
+ "x-amz-meta-ignored" => "I am ignored",
11
11
  "filename" => "uploads/roflcopter.gif"
12
12
  }
13
13
  end
@@ -22,6 +22,10 @@ describe CORS::Policy::S3 do
22
22
  manifest.required "x-amz-date" do |date|
23
23
  "2012-10-22T16:10:47+02:00" == date
24
24
  end
25
+ manifest.optional "x-amz-meta-filename", //
26
+ manifest.optional "x-amz-meta-roflcopter" do
27
+ true
28
+ end
25
29
  manifest.required "filename", %r|uploads/|
26
30
  end
27
31
  end
@@ -31,7 +35,7 @@ describe CORS::Policy::S3 do
31
35
  describe "#manifest" do
32
36
  it "is built according to specifications" do
33
37
  manifest = CORS::Policy::S3.create(&rules).new(valid_attributes)
34
- manifest.manifest.should eq <<-MANIFEST.gsub(/^ +/, "").rstrip
38
+ expect(manifest.manifest).to eq <<-MANIFEST.gsub(/^ +/, "").rstrip
35
39
  PUT
36
40
  CCummMp6o4ZgypU7ePh7QA==
37
41
  image/jpeg
@@ -44,16 +48,10 @@ describe CORS::Policy::S3 do
44
48
  end
45
49
  end
46
50
 
47
- describe "#sign" do
48
- it "signs the manifest if it is valid" do
49
- manifest = CORS::Policy::S3.create(&rules).new(valid_attributes)
50
- manifest.sign("LAWL", "HELLO").should eq "AWS LAWL:WZGsk2VzLz85B6oU19a5+fvzxXM="
51
- end
52
-
53
- it "does not sign if the manifest is invalid" do
54
- manifest = CORS::Policy::S3.create(&rules).new(valid_attributes)
55
- manifest.should_receive(:valid?).and_return(false)
56
- manifest.sign("LAWL", "HELLO").should be_nil
51
+ describe "#sign!" do
52
+ it "unconditionally signs the manifest" do
53
+ policy = manifest.new(valid_attributes)
54
+ expect(policy.sign!("LAWL", "HELLO")).to eq "AWS LAWL:WZGsk2VzLz85B6oU19a5+fvzxXM="
57
55
  end
58
56
  end
59
57
  end
@@ -27,11 +27,15 @@ describe CORS::Policy do
27
27
  end
28
28
 
29
29
  it "normalizes the attribute keys" do
30
- manifest.new(cOOl: :Yo).attributes.should eq({ "cool" => :Yo })
30
+ expect(manifest.new(anYTHIng: :Yo).attributes).to eq({ "anything" => :Yo })
31
+ end
32
+
33
+ it "removes attributes not covered by any rules" do
34
+ expect(manifest.new(cOOl: :Yo).attributes).to eq({})
31
35
  end
32
36
 
33
37
  it "populates the hash of errors" do
34
- manifest.new({}).errors.should_not be_empty
38
+ expect(manifest.new({}).errors).to_not be_empty
35
39
  end
36
40
  end
37
41
 
@@ -41,20 +45,36 @@ describe CORS::Policy do
41
45
  end
42
46
 
43
47
  it "returns the raw rules" do
44
- manifest.rules.should be_a CORS::Rules
48
+ expect(manifest.rules).to be_a CORS::Rules
45
49
  end
46
50
  end
47
51
 
48
52
  describe "#valid?" do
49
53
  it "returns true if validation succeeds" do
50
54
  manifest.new(valid_attributes).tap do |manifest|
51
- manifest.should be_valid
52
- manifest.errors.should eq({})
55
+ expect(manifest).to be_valid
56
+ expect(manifest.errors).to eq({})
53
57
  end
54
58
  end
55
59
 
56
60
  it "returns false if validation fails" do
57
- manifest.new({}).should_not be_valid
61
+ expect(manifest.new({})).to_not be_valid
62
+ end
63
+ end
64
+
65
+ describe "#sign" do
66
+ it "delegates to sign! if the manifest is valid" do
67
+ request = manifest.new(valid_attributes)
68
+ allow(request).to receive(:sign!).and_return("OK")
69
+ expect(request.sign(:a, :b)).to eq "OK"
70
+ expect(request).to have_received(:sign!)
71
+ end
72
+
73
+ it "does nothing if the manifest is not valid" do
74
+ request = manifest.new({})
75
+ allow(request).to receive(:sign!)
76
+ expect(request).not_to have_received(:sign!)
77
+ expect(request.sign(:a, :b)).to be_nil
58
78
  end
59
79
  end
60
80
  end
@@ -9,11 +9,33 @@ describe CORS::Rules do
9
9
  end
10
10
 
11
11
  it "is enumerable" do
12
- rules.each_with_object([]) { |rule, result| result << rule }.should eq(list)
12
+ expect(rules.each_with_object([]) { |rule, result| result << rule }).to eq(list)
13
13
  end
14
14
 
15
15
  it "returns an enumerator without a block" do
16
- rules.each.with_object([]) { |rule, result| result << rule }.should eq(list)
16
+ expect(rules.each.with_object([]) { |rule, result| result << rule }).to eq(list)
17
+ end
18
+ end
19
+
20
+ describe "#[]" do
21
+ let(:yay) { [] }
22
+ let(:boo) { [] }
23
+
24
+ let(:rules) do
25
+ CORS::Rules.new do |r|
26
+ yay << r.required("yay", //)
27
+ yay << r.required("yay", /./)
28
+ boo << r.optional("boo", //)
29
+ end
30
+ end
31
+
32
+ it "returns the list of rules for a property" do
33
+ expect(rules["yay"]).to eq yay
34
+ expect(rules["boo"]).to eq boo
35
+ end
36
+
37
+ it "returns nil if there are no rules for the property" do
38
+ expect(rules["does_not_exist"]).to be_nil
17
39
  end
18
40
  end
19
41
 
@@ -26,37 +48,37 @@ describe CORS::Rules do
26
48
  rules = CORS::Rules.new { |r| r.required "method", // }
27
49
  errors = rules.validate({})
28
50
 
29
- errors.should eq({ "method" => [:required, rules.first] })
51
+ expect(errors).to eq({ "method" => [:required, rules.first] })
30
52
  end
31
53
 
32
54
  it "results in an error when the value does not match" do
33
55
  rules = CORS::Rules.new { |r| r.required "content-type", %r|image/jpe?g| }
34
56
  errors = rules.validate({ "content-type" => "image/png" })
35
57
 
36
- errors.should eq({ "content-type" => [:match, rules.first] })
58
+ expect(errors).to eq({ "content-type" => [:match, rules.first] })
37
59
  end
38
60
 
39
61
  it "can match a regexp" do
40
62
  rules = CORS::Rules.new { |r| r.required "content-type", %r|image/jpe?g| }
41
63
 
42
- rules.validate({ "content-type" => "image/jpeg" }).should be_empty
43
- rules.validate({ "content-type" => "image/jpg" }).should be_empty
44
- rules.validate({ "content-type" => "image/png" }).should_not be_empty
64
+ expect(rules.validate({ "content-type" => "image/jpeg" })).to be_empty
65
+ expect(rules.validate({ "content-type" => "image/jpg" })).to be_empty
66
+ expect(rules.validate({ "content-type" => "image/png" })).to_not be_empty
45
67
  end
46
68
 
47
69
  it "can match a literal string" do
48
70
  rules = CORS::Rules.new { |r| r.required "content-type", "image/jpeg" }
49
71
 
50
- rules.validate({ "content-type" => "image/jpeg" }).should be_empty
51
- rules.validate({ "content-type" => "image/jpg" }).should_not be_empty
72
+ expect(rules.validate({ "content-type" => "image/jpeg" })).to be_empty
73
+ expect(rules.validate({ "content-type" => "image/jpg" })).to_not be_empty
52
74
  end
53
75
 
54
76
  it "can match an array" do
55
77
  rules = CORS::Rules.new { |r| r.required "content-type", ["image/jpeg", "image/png"] }
56
78
 
57
- rules.validate({ "content-type" => "image/jpeg" }).should be_empty
58
- rules.validate({ "content-type" => "image/png" }).should be_empty
59
- rules.validate({ "content-type" => "image/jpg" }).should_not be_empty
79
+ expect(rules.validate({ "content-type" => "image/jpeg" })).to be_empty
80
+ expect(rules.validate({ "content-type" => "image/png" })).to be_empty
81
+ expect(rules.validate({ "content-type" => "image/jpg" })).to_not be_empty
60
82
  end
61
83
 
62
84
  it "can match a block" do
@@ -66,8 +88,8 @@ describe CORS::Rules do
66
88
  end
67
89
  end
68
90
 
69
- rules.validate({ "content-type" => "image/jpeg" }).should be_empty
70
- rules.validate({ "content-type" => "image/png" }).should_not be_empty
91
+ expect(rules.validate({ "content-type" => "image/jpeg" })).to be_empty
92
+ expect(rules.validate({ "content-type" => "image/png" })).to_not be_empty
71
93
  end
72
94
  end
73
95
 
@@ -76,14 +98,14 @@ describe CORS::Rules do
76
98
  rules = CORS::Rules.new { |r| r.optional "method", // }
77
99
  errors = rules.validate({})
78
100
 
79
- errors.should be_empty
101
+ expect(errors).to be_empty
80
102
  end
81
103
 
82
104
  it "results in an error when the value is present but does not match" do
83
105
  rules = CORS::Rules.new { |r| r.optional "content-type", %r|image/jpe?g| }
84
106
  errors = rules.validate({ "content-type" => "image/png" })
85
107
 
86
- errors.should eq({ "content-type" => [:match, rules.first] })
108
+ expect(errors).to eq({ "content-type" => [:match, rules.first] })
87
109
  end
88
110
  end
89
111
  end
metadata CHANGED
@@ -1,65 +1,65 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cors
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
5
- prerelease:
4
+ version: 1.0.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Kim Burgestrand
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-10-30 00:00:00.000000000 Z
11
+ date: 2019-08-08 00:00:00.000000000 Z
13
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: multi_json
15
+ requirement: !ruby/object:Gem::Requirement
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
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
14
27
  - !ruby/object:Gem::Dependency
15
28
  name: rspec
16
29
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
30
  requirements:
19
- - - ~>
31
+ - - ">="
20
32
  - !ruby/object:Gem::Version
21
- version: '2.0'
33
+ version: '0'
22
34
  type: :development
23
35
  prerelease: false
24
36
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
37
  requirements:
27
- - - ~>
38
+ - - ">="
28
39
  - !ruby/object:Gem::Version
29
- version: '2.0'
30
- description: ! 'Cross-originresourcesharing(CORS)isgreat;itallowsyourvisitorsto
31
-
32
- asynchronouslyuploadfilestoe.g.FilepickerorAmazonS3,withoutthe
33
-
34
- fileshavingtoround-tripthroughyourwebserver.Unfortunately,giving
35
-
36
- youruserscompletewriteaccesstoyouronlinestoragealsoexposesyouto
37
-
38
- maliciousintent.
39
-
40
-
41
- Tocombatharmfulusage,gooduploadservicesthatallowclient-side
42
-
43
- upload,supportamechanismthatallowsyoutovalidateandsignallupload
44
-
45
- requeststoyouronlinestorage.Byvalidatingeveryrequest,youcangive
46
-
47
- yourvisitorsaniceuploadexperience,whilekeepingthebadvisitorsat
40
+ version: '0'
41
+ description: |
42
+ Cross-origin resource sharing (CORS) is great; it allows your visitors to
43
+ asynchronously upload files to e.g. Filepicker or Amazon S3, without the
44
+ files having to round-trip through your web server. Unfortunately, giving
45
+ your users complete write access to your online storage also exposes you to
46
+ malicious intent.
48
47
 
48
+ To combat harmful usage, good upload services that allow client-side
49
+ upload, support a mechanism that allows you to validate and sign all upload
50
+ requests to your online storage. By validating every request, you can give
51
+ your visitors a nice upload experience, while keeping the bad visitors at
49
52
  bay.
50
53
 
51
-
52
- TheCORSgemcomeswithsupportfortheAmazonS3RESTAPI.
53
-
54
- '
54
+ The CORS gem comes with support for the Amazon S3 REST API.
55
55
  email:
56
56
  - kim@burgestrand.se
57
57
  executables: []
58
58
  extensions: []
59
59
  extra_rdoc_files: []
60
60
  files:
61
- - .gitignore
62
- - .rspec
61
+ - ".gitignore"
62
+ - ".rspec"
63
63
  - Gemfile
64
64
  - Gemfile.lock
65
65
  - README.md
@@ -68,38 +68,44 @@ files:
68
68
  - lib/cors.rb
69
69
  - lib/cors/policy.rb
70
70
  - lib/cors/policy/s3.rb
71
+ - lib/cors/policy/s3_post.rb
71
72
  - lib/cors/rules.rb
72
73
  - lib/cors/version.rb
73
- - spec/cors_spec.rb
74
+ - spec/policies/s3_post_spec.rb
74
75
  - spec/policies/s3_spec.rb
76
+ - spec/policy_spec.rb
75
77
  - spec/rules_spec.rb
76
78
  - spec/spec_helper.rb
77
79
  homepage: http://github.com/elabs/cors
78
80
  licenses: []
79
- post_install_message:
81
+ metadata: {}
82
+ post_install_message: |
83
+ [DEPRECATED] The CORS gem is deprecated and will not receive further updates.
84
+ The functionality of CORS is now provided by the ruby AWS SDK:
85
+
86
+ https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/PresignedPost.html
80
87
  rdoc_options: []
81
88
  require_paths:
82
89
  - lib
83
90
  required_ruby_version: !ruby/object:Gem::Requirement
84
- none: false
85
91
  requirements:
86
- - - ! '>='
92
+ - - ">="
87
93
  - !ruby/object:Gem::Version
88
94
  version: '0'
89
95
  required_rubygems_version: !ruby/object:Gem::Requirement
90
- none: false
91
96
  requirements:
92
- - - ! '>='
97
+ - - ">="
93
98
  - !ruby/object:Gem::Version
94
99
  version: '0'
95
100
  requirements: []
96
101
  rubyforge_project:
97
- rubygems_version: 1.8.24
102
+ rubygems_version: 2.7.6
98
103
  signing_key:
99
- specification_version: 3
104
+ specification_version: 4
100
105
  summary: CORS policy validation- and signing library for Amazon S3 REST API.
101
106
  test_files:
102
- - spec/cors_spec.rb
107
+ - spec/policies/s3_post_spec.rb
103
108
  - spec/policies/s3_spec.rb
109
+ - spec/policy_spec.rb
104
110
  - spec/rules_spec.rb
105
111
  - spec/spec_helper.rb