shield 2.1.0 → 2.1.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.
- checksums.yaml +4 -4
- data/.gems +4 -0
- data/.gitignore +1 -0
- data/README.md +23 -26
- data/lib/shield.rb +18 -2
- data/makefile +4 -0
- data/shield.gemspec +21 -0
- data/test/cuba.rb +91 -0
- data/test/helper.rb +23 -0
- data/test/middleware.rb +30 -0
- data/test/model.rb +51 -0
- data/test/model_integration.rb +29 -0
- data/test/nested.rb +41 -0
- data/test/password.rb +21 -0
- data/test/shield.rb +95 -0
- data/test/user.rb +21 -0
- metadata +41 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b42c70f64c2292b685387b09ea89df2a0aff18a3
|
4
|
+
data.tar.gz: 0782a246fddf9b63acf1cced5f5fb5748d170aab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b2758cc4a231e6efcc138cc24dc360391b500f23f1970e12c1f42b72817dd017de871cafe37961c5fca4d3433abd258f22b4d05797da1094c533638e7e58ffe
|
7
|
+
data.tar.gz: a76c6de3bd2a54f4b29e7974404b8f286d07462948670e2bd986ac913271887f1653ca2a8bdc73ba6806b222d377e89d2ab0b6e4c8362240c0de3bc42f8b1ae7
|
data/.gems
ADDED
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
/pkg
|
data/README.md
CHANGED
@@ -1,27 +1,32 @@
|
|
1
|
-
|
1
|
+
Shield
|
2
|
+
======
|
2
3
|
|
3
4
|
Shield
|
4
5
|
|
5
6
|
_n. A solid piece of metal code used to protect your application._
|
6
7
|
|
7
|
-
|
8
|
+
Why another authentication library?
|
9
|
+
-----------------------------------
|
8
10
|
|
9
11
|
1. Because most of the other libraries are too huge.
|
10
12
|
2. Extending other libraries is a pain.
|
11
|
-
3. Writing code is fun :-)
|
13
|
+
3. Writing code is fun :-).
|
12
14
|
|
13
|
-
|
15
|
+
What shield is
|
16
|
+
--------------
|
14
17
|
|
15
|
-
1. Simple (~ 110 lines of Ruby code)
|
16
|
-
2. Doesn't get in the way
|
17
|
-
3. Treats you like a grown up
|
18
|
+
1. Simple (~ 110 lines of Ruby code).
|
19
|
+
2. Doesn't get in the way.
|
20
|
+
3. Treats you like a grown up.
|
18
21
|
|
19
|
-
|
22
|
+
What shield is not
|
23
|
+
------------------
|
20
24
|
|
21
25
|
- is _not_ a ready-made end-to-end authentication solution.
|
22
26
|
- is _not_ biased towards any kind of ORM.
|
23
27
|
|
24
|
-
|
28
|
+
Understanding Shield in 15 minutes
|
29
|
+
----------------------------------
|
25
30
|
|
26
31
|
### Shield::Model
|
27
32
|
|
@@ -82,14 +87,8 @@ Shield uses [Armor][armor] for encrypting passwords. Armor is a pure ruby
|
|
82
87
|
implementation of [PBKDF2][pbkdf2], a password-based key derivation function
|
83
88
|
recommended for the protection of electronically-stored data.
|
84
89
|
|
85
|
-
Shield
|
86
|
-
|
87
|
-
|
88
|
-
Take a look at [test/ohm.rb][ohm-test] and [test/sequel.rb][sequel-test]
|
89
|
-
to learn more.
|
90
|
-
|
91
|
-
To make Shield work with other ORMs (such as DataMapper), make sure to implement
|
92
|
-
an `.[]` method which fetches the user instance by id.
|
90
|
+
To make Shield work with any ORM, make sure that an `.[]` method which
|
91
|
+
fetches the user instance by id is implemented.
|
93
92
|
|
94
93
|
[armor]: https://github.com/cyx/armor
|
95
94
|
[pbkdf2]: http://en.wikipedia.org/wiki/PBKDF2
|
@@ -100,7 +99,7 @@ class User
|
|
100
99
|
|
101
100
|
# ...
|
102
101
|
|
103
|
-
self.[](id)
|
102
|
+
def self.[](id)
|
104
103
|
get id
|
105
104
|
end
|
106
105
|
end
|
@@ -113,15 +112,19 @@ in using either username or email, then you can simply extend `User.fetch`
|
|
113
112
|
a bit by doing:
|
114
113
|
|
115
114
|
```ruby
|
116
|
-
# in Sequel
|
115
|
+
# in Sequel (http://sequel.rubyforge.org)
|
117
116
|
class User < Sequel::Model
|
117
|
+
include Shield::Model
|
118
|
+
|
118
119
|
def self.fetch(identifier)
|
119
120
|
filter(email: identifier).first || filter(username: identifier).first
|
120
121
|
end
|
121
122
|
end
|
122
123
|
|
123
|
-
# in Ohm
|
124
|
+
# in Ohm (http://ohm.keyvalue.org)
|
124
125
|
class User < Ohm::Model
|
126
|
+
include Shield::Model
|
127
|
+
|
125
128
|
attribute :email
|
126
129
|
attribute :username
|
127
130
|
|
@@ -137,12 +140,6 @@ end
|
|
137
140
|
If you want to allow case-insensitive logins for some reason, you can
|
138
141
|
simply normalize the values to their lowercase form.
|
139
142
|
|
140
|
-
[ohm]: http://ohm.keyvalue.org
|
141
|
-
[sequel]: http://sequel.rubyforge.org
|
142
|
-
|
143
|
-
[ohm-test]: https://github.com/cyx/shield/blob/master/test/ohm.rb
|
144
|
-
[sequel-test]: https://github.com/cyx/shield/blob/master/test/sequel.rb
|
145
|
-
|
146
143
|
### Shield::Helpers
|
147
144
|
|
148
145
|
As the name suggests, `Shield::Helpers` is out there to aid you a bit,
|
data/lib/shield.rb
CHANGED
@@ -98,17 +98,33 @@ module Shield
|
|
98
98
|
end
|
99
99
|
|
100
100
|
module Password
|
101
|
+
Error = Class.new(StandardError)
|
102
|
+
|
103
|
+
# == DOS attack fix
|
104
|
+
#
|
105
|
+
# Excessively long passwords (e.g. 1MB strings) would hang
|
106
|
+
# a server.
|
107
|
+
#
|
108
|
+
# @see: https://www.djangoproject.com/weblog/2013/sep/15/security/
|
109
|
+
MAX_LEN = 4096
|
110
|
+
|
101
111
|
def self.encrypt(password, salt = generate_salt)
|
102
|
-
|
112
|
+
digest(password, salt) + salt
|
103
113
|
end
|
104
114
|
|
105
115
|
def self.check(password, encrypted)
|
106
116
|
sha512, salt = encrypted.to_s[0...128], encrypted.to_s[128..-1]
|
107
117
|
|
108
|
-
Armor.compare(
|
118
|
+
Armor.compare(digest(password, salt), sha512)
|
109
119
|
end
|
110
120
|
|
111
121
|
protected
|
122
|
+
def self.digest(password, salt)
|
123
|
+
raise Error if password.length > MAX_LEN
|
124
|
+
|
125
|
+
Armor.digest(password, salt)
|
126
|
+
end
|
127
|
+
|
112
128
|
def self.generate_salt
|
113
129
|
Armor.hex(OpenSSL::Random.random_bytes(32))
|
114
130
|
end
|
data/makefile
ADDED
data/shield.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "shield"
|
3
|
+
s.version = "2.1.1"
|
4
|
+
s.summary = %{Generic authentication protocol for rack applications.}
|
5
|
+
s.description = %Q{
|
6
|
+
Provides all the protocol you need in order to do authentication on
|
7
|
+
your rack application. The implementation specifics can be found in
|
8
|
+
http://github.com/cyx/shield-contrib
|
9
|
+
}
|
10
|
+
s.authors = ["Michel Martens", "Damian Janowski", "Cyril David"]
|
11
|
+
s.email = ["michel@soveran.com", "djanowski@dimaion.com", "me@cyrildavid.com"]
|
12
|
+
s.homepage = "http://github.com/cyx/shield"
|
13
|
+
s.license = "MIT"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
|
17
|
+
s.add_dependency "armor"
|
18
|
+
s.add_development_dependency "cutest"
|
19
|
+
s.add_development_dependency "rack-test"
|
20
|
+
s.add_development_dependency "cuba"
|
21
|
+
end
|
data/test/cuba.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
require_relative "user"
|
3
|
+
require "cuba"
|
4
|
+
|
5
|
+
Cuba.use Rack::Session::Cookie, secret: "foo"
|
6
|
+
Cuba.use Shield::Middleware
|
7
|
+
Cuba.plugin Shield::Helpers
|
8
|
+
|
9
|
+
Cuba.define do
|
10
|
+
on get, "public" do
|
11
|
+
res.write "Public"
|
12
|
+
end
|
13
|
+
|
14
|
+
on get, "private" do
|
15
|
+
if authenticated(User)
|
16
|
+
res.write "Private"
|
17
|
+
else
|
18
|
+
res.status = 401
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
on get, "login" do
|
23
|
+
res.write "Login"
|
24
|
+
end
|
25
|
+
|
26
|
+
on post, "login", param("login"), param("password") do |u, p|
|
27
|
+
if login(User, u, p)
|
28
|
+
remember if req[:remember_me]
|
29
|
+
res.redirect(req[:return] || "/")
|
30
|
+
else
|
31
|
+
res.redirect "/login"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
on "logout" do
|
36
|
+
logout(User)
|
37
|
+
res.redirect "/"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
scope do
|
42
|
+
def app
|
43
|
+
Cuba
|
44
|
+
end
|
45
|
+
|
46
|
+
setup do
|
47
|
+
clear_cookies
|
48
|
+
end
|
49
|
+
|
50
|
+
test "public" do
|
51
|
+
get "/public"
|
52
|
+
assert "Public" == last_response.body
|
53
|
+
end
|
54
|
+
|
55
|
+
test "successful logging in" do
|
56
|
+
get "/private"
|
57
|
+
|
58
|
+
assert_equal "/login?return=%2Fprivate", redirection_url
|
59
|
+
|
60
|
+
post "/login", login: "quentin", password: "password", return: "/private"
|
61
|
+
|
62
|
+
assert_redirected_to "/private"
|
63
|
+
|
64
|
+
assert 1001 == session["User"]
|
65
|
+
end
|
66
|
+
|
67
|
+
test "failed login" do
|
68
|
+
post "/login", :login => "q", :password => "p"
|
69
|
+
assert_redirected_to "/login"
|
70
|
+
|
71
|
+
assert nil == session["User"]
|
72
|
+
end
|
73
|
+
|
74
|
+
test "logging out" do
|
75
|
+
post "/login", :login => "quentin", :password => "password"
|
76
|
+
|
77
|
+
get "/logout"
|
78
|
+
|
79
|
+
assert nil == session["User"]
|
80
|
+
end
|
81
|
+
|
82
|
+
test "remember functionality" do
|
83
|
+
post "/login", :login => "quentin", :password => "password", :remember_me => "1"
|
84
|
+
|
85
|
+
assert_equal session[:remember_for], 86400 * 14
|
86
|
+
|
87
|
+
get "/logout"
|
88
|
+
|
89
|
+
assert_equal nil, session[:remember_for]
|
90
|
+
end
|
91
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "cutest"
|
2
|
+
require "rack/test"
|
3
|
+
|
4
|
+
require_relative "../lib/shield"
|
5
|
+
|
6
|
+
class Cutest::Scope
|
7
|
+
include Rack::Test::Methods
|
8
|
+
|
9
|
+
def assert_redirected_to(path)
|
10
|
+
unless last_response.status == 302
|
11
|
+
flunk
|
12
|
+
end
|
13
|
+
assert_equal path, URI(redirection_url).path
|
14
|
+
end
|
15
|
+
|
16
|
+
def redirection_url
|
17
|
+
last_response.headers["Location"]
|
18
|
+
end
|
19
|
+
|
20
|
+
def session
|
21
|
+
last_request.env["rack.session"]
|
22
|
+
end
|
23
|
+
end
|
data/test/middleware.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
require_relative "user"
|
3
|
+
require "cuba"
|
4
|
+
|
5
|
+
Cuba.use Rack::Session::Cookie, secret: "foo"
|
6
|
+
Cuba.use Shield::Middleware
|
7
|
+
|
8
|
+
Cuba.plugin Shield::Helpers
|
9
|
+
|
10
|
+
Cuba.define do
|
11
|
+
on "secured" do
|
12
|
+
if not authenticated(User)
|
13
|
+
halt [401, { "Content-Type" => "text/html" }, []]
|
14
|
+
end
|
15
|
+
|
16
|
+
res.write "You're in"
|
17
|
+
end
|
18
|
+
|
19
|
+
on "foo" do
|
20
|
+
puts env.inspect
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
test do
|
25
|
+
env = { "PATH_INFO" => "/secured", "SCRIPT_NAME" => "" }
|
26
|
+
status, headers, body = Cuba.call(env)
|
27
|
+
|
28
|
+
assert_equal 302, status
|
29
|
+
assert_equal "/login?return=%2Fsecured", headers["Location"]
|
30
|
+
end
|
data/test/model.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
|
3
|
+
class User < Struct.new(:crypted_password)
|
4
|
+
include Shield::Model
|
5
|
+
end
|
6
|
+
|
7
|
+
test "fetch" do
|
8
|
+
ex = nil
|
9
|
+
|
10
|
+
begin
|
11
|
+
User.fetch("quentin")
|
12
|
+
rescue Exception => ex
|
13
|
+
end
|
14
|
+
|
15
|
+
assert ex.kind_of?(Shield::Model::FetchMissing)
|
16
|
+
assert "User.fetch not implemented" == ex.message
|
17
|
+
end
|
18
|
+
|
19
|
+
test "is_valid_password?" do
|
20
|
+
user = User.new(Shield::Password.encrypt("password"))
|
21
|
+
|
22
|
+
assert User.is_valid_password?(user, "password")
|
23
|
+
assert ! User.is_valid_password?(user, "password1")
|
24
|
+
end
|
25
|
+
|
26
|
+
class User
|
27
|
+
class << self
|
28
|
+
attr_accessor :fetched
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.fetch(username)
|
32
|
+
return fetched if username == "quentin"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
test "authenticate" do
|
37
|
+
user = User.new(Shield::Password.encrypt("pass"))
|
38
|
+
|
39
|
+
User.fetched = user
|
40
|
+
|
41
|
+
assert user == User.authenticate("quentin", "pass")
|
42
|
+
assert nil == User.authenticate("unknown", "pass")
|
43
|
+
assert nil == User.authenticate("quentin", "wrongpass")
|
44
|
+
end
|
45
|
+
|
46
|
+
test "#password=" do
|
47
|
+
u = User.new
|
48
|
+
u.password = "pass1234"
|
49
|
+
|
50
|
+
assert Shield::Password.check("pass1234", u.crypted_password)
|
51
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
|
3
|
+
class User
|
4
|
+
include Shield::Model
|
5
|
+
|
6
|
+
attr_accessor :email, :crypted_password
|
7
|
+
|
8
|
+
def self.fetch(email)
|
9
|
+
$users[email]
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(email, password)
|
13
|
+
@email = email
|
14
|
+
self.password = password
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
setup do
|
19
|
+
$users = {}
|
20
|
+
$users["foo@bar.com"] = User.new("foo@bar.com", "pass1234")
|
21
|
+
end
|
22
|
+
|
23
|
+
test "fetch" do |user|
|
24
|
+
assert_equal user, User.fetch("foo@bar.com")
|
25
|
+
end
|
26
|
+
|
27
|
+
test "authenticate" do |user|
|
28
|
+
assert_equal user, User.authenticate("foo@bar.com", "pass1234")
|
29
|
+
end
|
data/test/nested.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
require_relative "user"
|
3
|
+
require "cuba"
|
4
|
+
|
5
|
+
Cuba.use Rack::Session::Cookie, secret: "foo"
|
6
|
+
Cuba.plugin Shield::Helpers
|
7
|
+
|
8
|
+
class Admin < Cuba
|
9
|
+
use Shield::Middleware, "/admin/login"
|
10
|
+
|
11
|
+
define do
|
12
|
+
on "login" do
|
13
|
+
res.write "Login"
|
14
|
+
end
|
15
|
+
|
16
|
+
on default do
|
17
|
+
res.status = 401
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Cuba.define do
|
23
|
+
on "admin" do
|
24
|
+
run Admin
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
scope do
|
29
|
+
def app
|
30
|
+
Cuba
|
31
|
+
end
|
32
|
+
|
33
|
+
setup do
|
34
|
+
clear_cookies
|
35
|
+
end
|
36
|
+
|
37
|
+
test "return + return flow" do
|
38
|
+
get "/admin"
|
39
|
+
assert_equal "/admin/login?return=%2Fadmin", redirection_url
|
40
|
+
end
|
41
|
+
end
|
data/test/password.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
|
3
|
+
scope do
|
4
|
+
test "encrypt" do
|
5
|
+
encrypted = Shield::Password.encrypt("password")
|
6
|
+
assert Shield::Password.check("password", encrypted)
|
7
|
+
end
|
8
|
+
|
9
|
+
test "with custom 64 character salt" do
|
10
|
+
encrypted = Shield::Password.encrypt("password", "A" * 64)
|
11
|
+
assert Shield::Password.check("password", encrypted)
|
12
|
+
end
|
13
|
+
|
14
|
+
test "DOS fix" do
|
15
|
+
too_long = '*' * (Shield::Password::MAX_LEN + 1)
|
16
|
+
|
17
|
+
assert_raise Shield::Password::Error do
|
18
|
+
Shield::Password.encrypt(too_long)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/test/shield.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require_relative "helper"
|
2
|
+
|
3
|
+
class User < Struct.new(:id)
|
4
|
+
extend Shield::Model
|
5
|
+
|
6
|
+
def self.[](id)
|
7
|
+
User.new(1) unless id.to_s.empty?
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.authenticate(username, password)
|
11
|
+
User.new(1001) if username == "quentin" && password == "password"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Context
|
16
|
+
def initialize(path)
|
17
|
+
@path = path
|
18
|
+
end
|
19
|
+
|
20
|
+
def env
|
21
|
+
{ "SCRIPT_NAME" => "", "PATH_INFO" => @path }
|
22
|
+
end
|
23
|
+
|
24
|
+
def session
|
25
|
+
@session ||= {}
|
26
|
+
end
|
27
|
+
|
28
|
+
class Request < Struct.new(:fullpath)
|
29
|
+
end
|
30
|
+
|
31
|
+
def req
|
32
|
+
Request.new(@path)
|
33
|
+
end
|
34
|
+
|
35
|
+
def redirect(redirect = nil)
|
36
|
+
@redirect = redirect if redirect
|
37
|
+
@redirect
|
38
|
+
end
|
39
|
+
|
40
|
+
include Shield::Helpers
|
41
|
+
end
|
42
|
+
|
43
|
+
setup do
|
44
|
+
Context.new("/events/1")
|
45
|
+
end
|
46
|
+
|
47
|
+
class Admin < Struct.new(:id)
|
48
|
+
def self.[](id)
|
49
|
+
new(id) unless id.to_s.empty?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
test "authenticated" do |context|
|
54
|
+
context.session["User"] = 1
|
55
|
+
|
56
|
+
assert User.new(1) == context.authenticated(User)
|
57
|
+
assert nil == context.authenticated(Admin)
|
58
|
+
end
|
59
|
+
|
60
|
+
test "caches authenticated in @_shield" do |context|
|
61
|
+
context.session["User"] = 1
|
62
|
+
context.authenticated(User)
|
63
|
+
|
64
|
+
assert User.new(1) == context.instance_variable_get(:@_shield)[User]
|
65
|
+
end
|
66
|
+
|
67
|
+
test "login success" do |context|
|
68
|
+
assert context.login(User, "quentin", "password")
|
69
|
+
assert 1001 == context.session["User"]
|
70
|
+
end
|
71
|
+
|
72
|
+
test "login failure" do |context|
|
73
|
+
assert ! context.login(User, "wrong", "creds")
|
74
|
+
assert nil == context.session["User"]
|
75
|
+
end
|
76
|
+
|
77
|
+
test "logout" do |context|
|
78
|
+
context.session["User"] = 1001
|
79
|
+
|
80
|
+
# Now let's make it memoize the User
|
81
|
+
context.authenticated(User)
|
82
|
+
|
83
|
+
context.logout(User)
|
84
|
+
|
85
|
+
assert nil == context.session["User"]
|
86
|
+
assert nil == context.authenticated(User)
|
87
|
+
end
|
88
|
+
|
89
|
+
test "authenticate" do |context|
|
90
|
+
context.session["no_fixation"] = 1
|
91
|
+
context.authenticate(User[1001])
|
92
|
+
|
93
|
+
assert User[1] == context.authenticated(User)
|
94
|
+
assert nil == context.session["no_fixation"]
|
95
|
+
end
|
data/test/user.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
class User
|
2
|
+
include Shield::Model
|
3
|
+
|
4
|
+
def self.[](id)
|
5
|
+
User.new(1001) unless id.to_s.empty?
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.fetch(username)
|
9
|
+
User.new(1001) if username == "quentin"
|
10
|
+
end
|
11
|
+
|
12
|
+
attr :id
|
13
|
+
|
14
|
+
def initialize(id)
|
15
|
+
@id = id
|
16
|
+
end
|
17
|
+
|
18
|
+
def crypted_password
|
19
|
+
@crypted_password ||= Shield::Password.encrypt("password")
|
20
|
+
end
|
21
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shield
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michel Martens
|
@@ -10,48 +10,62 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2014-10-20 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: armor
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ">="
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
|
-
- -
|
26
|
+
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
version: '0'
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: cutest
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
|
-
- -
|
33
|
+
- - ">="
|
34
34
|
- !ruby/object:Gem::Version
|
35
35
|
version: '0'
|
36
36
|
type: :development
|
37
37
|
prerelease: false
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
|
-
- -
|
40
|
+
- - ">="
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: '0'
|
43
43
|
- !ruby/object:Gem::Dependency
|
44
44
|
name: rack-test
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
|
-
- -
|
47
|
+
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
49
|
version: '0'
|
50
50
|
type: :development
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
|
-
- -
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: cuba
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
55
69
|
- !ruby/object:Gem::Version
|
56
70
|
version: '0'
|
57
71
|
description: "\n Provides all the protocol you need in order to do authentication
|
@@ -65,11 +79,25 @@ executables: []
|
|
65
79
|
extensions: []
|
66
80
|
extra_rdoc_files: []
|
67
81
|
files:
|
68
|
-
-
|
82
|
+
- ".gems"
|
83
|
+
- ".gitignore"
|
69
84
|
- LICENSE
|
85
|
+
- README.md
|
70
86
|
- lib/shield.rb
|
87
|
+
- makefile
|
88
|
+
- shield.gemspec
|
89
|
+
- test/cuba.rb
|
90
|
+
- test/helper.rb
|
91
|
+
- test/middleware.rb
|
92
|
+
- test/model.rb
|
93
|
+
- test/model_integration.rb
|
94
|
+
- test/nested.rb
|
95
|
+
- test/password.rb
|
96
|
+
- test/shield.rb
|
97
|
+
- test/user.rb
|
71
98
|
homepage: http://github.com/cyx/shield
|
72
|
-
licenses:
|
99
|
+
licenses:
|
100
|
+
- MIT
|
73
101
|
metadata: {}
|
74
102
|
post_install_message:
|
75
103
|
rdoc_options: []
|
@@ -77,17 +105,17 @@ require_paths:
|
|
77
105
|
- lib
|
78
106
|
required_ruby_version: !ruby/object:Gem::Requirement
|
79
107
|
requirements:
|
80
|
-
- -
|
108
|
+
- - ">="
|
81
109
|
- !ruby/object:Gem::Version
|
82
110
|
version: '0'
|
83
111
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
112
|
requirements:
|
85
|
-
- -
|
113
|
+
- - ">="
|
86
114
|
- !ruby/object:Gem::Version
|
87
115
|
version: '0'
|
88
116
|
requirements: []
|
89
117
|
rubyforge_project:
|
90
|
-
rubygems_version: 2.
|
118
|
+
rubygems_version: 2.2.2
|
91
119
|
signing_key:
|
92
120
|
specification_version: 4
|
93
121
|
summary: Generic authentication protocol for rack applications.
|