shield 1.0.0 → 2.0.0.rc1
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 +7 -0
- data/README.md +32 -12
- data/lib/shield.rb +11 -26
- metadata +58 -51
- data/Rakefile +0 -6
- data/test/cuba.rb +0 -89
- data/test/helper.rb +0 -26
- data/test/middleware.rb +0 -29
- data/test/model.rb +0 -51
- data/test/nested.rb +0 -40
- data/test/ohm.rb +0 -30
- data/test/password.rb +0 -13
- data/test/sequel.rb +0 -36
- data/test/shield.rb +0 -93
- data/test/sinatra.rb +0 -92
- data/test/user.rb +0 -21
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8410669419f1ee546b28f102220c8fcdc6eb01c2
|
4
|
+
data.tar.gz: 526347651447f2c7bea76a8324d340f1f4c187b1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 68216a7e3345bd6f97ce1e4b70253b466d97010c3692ce146e3e057f0b1791c37173513e98b64da57dc34186ec9ce720ef7985effaaf48324cda9171c51a3d76
|
7
|
+
data.tar.gz: bd8da373fd73659fed23e1e71642ff506cc38ac0cc5883f1654038102a017688c69e303b75cb7198fd883593a8b9f481d8bd4490bf1e453f5abe378c05f997d1
|
data/README.md
CHANGED
@@ -74,16 +74,38 @@ nil == User.authenticate("foo@bar.com", "pass1234")
|
|
74
74
|
|
75
75
|
# If we try a different password on the other hand,
|
76
76
|
# we get `nil`.
|
77
|
-
nil == User.
|
77
|
+
nil == User.authenticate("foo@bar.com", "wrong")
|
78
78
|
# => true
|
79
79
|
```
|
80
80
|
|
81
|
-
Shield
|
81
|
+
Shield uses [Armor][armor] for encrypting passwords. Armor is a pure ruby
|
82
|
+
implementation of [PBKDF2][pbkdf2], a password-based key derivation function
|
83
|
+
recommended for the protection of electronically-stored data.
|
84
|
+
|
85
|
+
Shield also includes tests for [ohm][ohm] and [sequel][sequel] and makes sure
|
82
86
|
that each release works with the latest respective versions.
|
83
87
|
|
84
88
|
Take a look at [test/ohm.rb][ohm-test] and [test/sequel.rb][sequel-test]
|
85
89
|
to learn more.
|
86
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.
|
93
|
+
|
94
|
+
[armor]: https://github.com/cyx/armor
|
95
|
+
[pbkdf2]: http://en.wikipedia.org/wiki/PBKDF2
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
class User
|
99
|
+
include Shield::Model
|
100
|
+
|
101
|
+
# ...
|
102
|
+
|
103
|
+
self.[](id)
|
104
|
+
get id
|
105
|
+
end
|
106
|
+
end
|
107
|
+
```
|
108
|
+
|
87
109
|
### Logging in with an email and username?
|
88
110
|
|
89
111
|
If your requirements dictate that you need to be able to support logging
|
@@ -140,7 +162,7 @@ both Cuba and Sinatra.
|
|
140
162
|
```ruby
|
141
163
|
require "sinatra"
|
142
164
|
|
143
|
-
#
|
165
|
+
# Satisfies assumption number 1 above.
|
144
166
|
use Rack::Session::Cookie
|
145
167
|
|
146
168
|
# Mixes `Shield::Helpers` into your routes context.
|
@@ -157,7 +179,8 @@ get "/login" do
|
|
157
179
|
end
|
158
180
|
|
159
181
|
post "/login" do
|
160
|
-
if login(User, params[:login], params[:password]
|
182
|
+
if login(User, params[:login], params[:password])
|
183
|
+
remember(authenticated(User)) if params[:remember_me]
|
161
184
|
redirect(params[:return] || "/")
|
162
185
|
else
|
163
186
|
redirect "/login"
|
@@ -218,13 +241,10 @@ Content-Type: text/html
|
|
218
241
|
|
219
242
|
Notice that it specifies `/private` as the return URL.
|
220
243
|
|
221
|
-
##
|
244
|
+
## Installation
|
222
245
|
|
223
|
-
|
224
|
-
created a starting point that includes **Login**, **Signup** and
|
225
|
-
**Forgot Password** functionality.
|
246
|
+
You can install it using rubygems:
|
226
247
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
[cuba-app]: http://github.com/citrusbyte/cuba-app
|
248
|
+
```
|
249
|
+
gem install shield
|
250
|
+
```
|
data/lib/shield.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require "
|
1
|
+
require "armor"
|
2
2
|
require "uri"
|
3
3
|
|
4
4
|
module Shield
|
@@ -49,11 +49,13 @@ module Shield
|
|
49
49
|
session[user.class.to_s] = user.id
|
50
50
|
end
|
51
51
|
|
52
|
-
def login(model, username, password
|
53
|
-
|
52
|
+
def login(model, username, password)
|
53
|
+
user = model.authenticate(username, password)
|
54
|
+
authenticate(user) if user
|
55
|
+
end
|
54
56
|
|
55
|
-
|
56
|
-
|
57
|
+
def remember(user, expire = 1209600)
|
58
|
+
session[:remember_for] = expire
|
57
59
|
end
|
58
60
|
|
59
61
|
def logout(model)
|
@@ -95,36 +97,19 @@ module Shield
|
|
95
97
|
end
|
96
98
|
|
97
99
|
module Password
|
98
|
-
def self.iterations
|
99
|
-
@iterations ||= 5000
|
100
|
-
end
|
101
|
-
|
102
|
-
def self.iterations=(iterations)
|
103
|
-
@iterations = iterations
|
104
|
-
end
|
105
|
-
|
106
100
|
def self.encrypt(password, salt = generate_salt)
|
107
|
-
digest(password, salt) + salt
|
101
|
+
Armor.digest(password, salt) + salt
|
108
102
|
end
|
109
103
|
|
110
104
|
def self.check(password, encrypted)
|
111
|
-
sha512, salt = encrypted.to_s[0
|
105
|
+
sha512, salt = encrypted.to_s[0...128], encrypted.to_s[128..-1]
|
112
106
|
|
113
|
-
digest(password, salt)
|
107
|
+
Armor.compare(Armor.digest(password, salt), sha512)
|
114
108
|
end
|
115
109
|
|
116
110
|
protected
|
117
|
-
def self.digest(password, salt)
|
118
|
-
PBKDF2.new do |p|
|
119
|
-
p.password = password
|
120
|
-
p.salt = salt
|
121
|
-
p.iterations = iterations
|
122
|
-
p.hash_function = :sha512
|
123
|
-
end.hex_string
|
124
|
-
end
|
125
|
-
|
126
111
|
def self.generate_salt
|
127
|
-
|
112
|
+
Armor.hex(OpenSSL::Random.random_bytes(32))
|
128
113
|
end
|
129
114
|
end
|
130
115
|
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shield
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 2.0.0.rc1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Michel Martens
|
@@ -11,86 +10,107 @@ authors:
|
|
11
10
|
autorequire:
|
12
11
|
bindir: bin
|
13
12
|
cert_chain: []
|
14
|
-
date:
|
13
|
+
date: 2013-04-15 00:00:00.000000000 Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
|
-
name:
|
18
|
-
requirement:
|
19
|
-
none: false
|
16
|
+
name: armor
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
20
18
|
requirements:
|
21
|
-
- -
|
19
|
+
- - '>='
|
22
20
|
- !ruby/object:Gem::Version
|
23
21
|
version: '0'
|
24
22
|
type: :runtime
|
25
23
|
prerelease: false
|
26
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - '>='
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '0'
|
27
29
|
- !ruby/object:Gem::Dependency
|
28
30
|
name: cutest
|
29
|
-
requirement:
|
30
|
-
none: false
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
31
32
|
requirements:
|
32
|
-
- -
|
33
|
+
- - '>='
|
33
34
|
- !ruby/object:Gem::Version
|
34
35
|
version: '0'
|
35
36
|
type: :development
|
36
37
|
prerelease: false
|
37
|
-
version_requirements:
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - '>='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
38
43
|
- !ruby/object:Gem::Dependency
|
39
44
|
name: cuba
|
40
|
-
requirement:
|
41
|
-
none: false
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
42
46
|
requirements:
|
43
|
-
- -
|
47
|
+
- - '>='
|
44
48
|
- !ruby/object:Gem::Version
|
45
49
|
version: '0'
|
46
50
|
type: :development
|
47
51
|
prerelease: false
|
48
|
-
version_requirements:
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
49
57
|
- !ruby/object:Gem::Dependency
|
50
58
|
name: sinatra
|
51
|
-
requirement:
|
52
|
-
none: false
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
53
60
|
requirements:
|
54
|
-
- -
|
61
|
+
- - '>='
|
55
62
|
- !ruby/object:Gem::Version
|
56
63
|
version: '0'
|
57
64
|
type: :development
|
58
65
|
prerelease: false
|
59
|
-
version_requirements:
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
60
71
|
- !ruby/object:Gem::Dependency
|
61
72
|
name: rack-test
|
62
|
-
requirement:
|
63
|
-
none: false
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
64
74
|
requirements:
|
65
|
-
- -
|
75
|
+
- - '>='
|
66
76
|
- !ruby/object:Gem::Version
|
67
77
|
version: '0'
|
68
78
|
type: :development
|
69
79
|
prerelease: false
|
70
|
-
version_requirements:
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
71
85
|
- !ruby/object:Gem::Dependency
|
72
86
|
name: sequel
|
73
|
-
requirement:
|
74
|
-
none: false
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
75
88
|
requirements:
|
76
|
-
- -
|
89
|
+
- - '>='
|
77
90
|
- !ruby/object:Gem::Version
|
78
91
|
version: '0'
|
79
92
|
type: :development
|
80
93
|
prerelease: false
|
81
|
-
version_requirements:
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
82
99
|
- !ruby/object:Gem::Dependency
|
83
100
|
name: ohm
|
84
|
-
requirement:
|
85
|
-
none: false
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
86
102
|
requirements:
|
87
103
|
- - ~>
|
88
104
|
- !ruby/object:Gem::Version
|
89
105
|
version: '0.1'
|
90
106
|
type: :development
|
91
107
|
prerelease: false
|
92
|
-
version_requirements:
|
93
|
-
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ~>
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0.1'
|
113
|
+
description: "\n Provides all the protocol you need in order to do authentication
|
94
114
|
on\n your rack application. The implementation specifics can be found in\n http://github.com/cyx/shield-contrib\n
|
95
115
|
\ "
|
96
116
|
email:
|
@@ -103,41 +123,28 @@ extra_rdoc_files: []
|
|
103
123
|
files:
|
104
124
|
- README.md
|
105
125
|
- LICENSE
|
106
|
-
- Rakefile
|
107
126
|
- lib/shield.rb
|
108
|
-
- test/cuba.rb
|
109
|
-
- test/helper.rb
|
110
|
-
- test/middleware.rb
|
111
|
-
- test/model.rb
|
112
|
-
- test/nested.rb
|
113
|
-
- test/ohm.rb
|
114
|
-
- test/password.rb
|
115
|
-
- test/sequel.rb
|
116
|
-
- test/shield.rb
|
117
|
-
- test/sinatra.rb
|
118
|
-
- test/user.rb
|
119
127
|
homepage: http://github.com/cyx/shield
|
120
128
|
licenses: []
|
129
|
+
metadata: {}
|
121
130
|
post_install_message:
|
122
131
|
rdoc_options: []
|
123
132
|
require_paths:
|
124
133
|
- lib
|
125
134
|
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
-
none: false
|
127
135
|
requirements:
|
128
|
-
- -
|
136
|
+
- - '>='
|
129
137
|
- !ruby/object:Gem::Version
|
130
138
|
version: '0'
|
131
139
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
-
none: false
|
133
140
|
requirements:
|
134
|
-
- -
|
141
|
+
- - '>'
|
135
142
|
- !ruby/object:Gem::Version
|
136
|
-
version:
|
143
|
+
version: 1.3.1
|
137
144
|
requirements: []
|
138
145
|
rubyforge_project:
|
139
|
-
rubygems_version:
|
146
|
+
rubygems_version: 2.0.3
|
140
147
|
signing_key:
|
141
|
-
specification_version:
|
148
|
+
specification_version: 4
|
142
149
|
summary: Generic authentication protocol for rack applications.
|
143
150
|
test_files: []
|
data/Rakefile
DELETED
data/test/cuba.rb
DELETED
@@ -1,89 +0,0 @@
|
|
1
|
-
require File.expand_path("helper", File.dirname(__FILE__))
|
2
|
-
require File.expand_path("user", File.dirname(__FILE__))
|
3
|
-
|
4
|
-
Cuba.use Rack::Session::Cookie
|
5
|
-
Cuba.use Shield::Middleware
|
6
|
-
Cuba.plugin Shield::Helpers
|
7
|
-
|
8
|
-
Cuba.define do
|
9
|
-
on get, "public" do
|
10
|
-
res.write "Public"
|
11
|
-
end
|
12
|
-
|
13
|
-
on get, "private" do
|
14
|
-
if authenticated(User)
|
15
|
-
res.write "Private"
|
16
|
-
else
|
17
|
-
res.status = 401
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
on get, "login" do
|
22
|
-
res.write "Login"
|
23
|
-
end
|
24
|
-
|
25
|
-
on post, "login", param("login"), param("password") do |u, p|
|
26
|
-
if login(User, u, p, req[:remember_me])
|
27
|
-
res.redirect(req[:return] || "/")
|
28
|
-
else
|
29
|
-
res.redirect "/login"
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
on "logout" do
|
34
|
-
logout(User)
|
35
|
-
res.redirect "/"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
scope do
|
40
|
-
def app
|
41
|
-
Cuba
|
42
|
-
end
|
43
|
-
|
44
|
-
setup do
|
45
|
-
clear_cookies
|
46
|
-
end
|
47
|
-
|
48
|
-
test "public" do
|
49
|
-
get "/public"
|
50
|
-
assert "Public" == last_response.body
|
51
|
-
end
|
52
|
-
|
53
|
-
test "successful logging in" do
|
54
|
-
get "/private"
|
55
|
-
|
56
|
-
assert_equal "/login?return=%2Fprivate", redirection_url
|
57
|
-
|
58
|
-
post "/login", login: "quentin", password: "password", return: "/private"
|
59
|
-
|
60
|
-
assert_redirected_to "/private"
|
61
|
-
|
62
|
-
assert 1001 == session["User"]
|
63
|
-
end
|
64
|
-
|
65
|
-
test "failed login" do
|
66
|
-
post "/login", :login => "q", :password => "p"
|
67
|
-
assert_redirected_to "/login"
|
68
|
-
|
69
|
-
assert nil == session["User"]
|
70
|
-
end
|
71
|
-
|
72
|
-
test "logging out" do
|
73
|
-
post "/login", :login => "quentin", :password => "password"
|
74
|
-
|
75
|
-
get "/logout"
|
76
|
-
|
77
|
-
assert nil == session["User"]
|
78
|
-
end
|
79
|
-
|
80
|
-
test "remember functionality" do
|
81
|
-
post "/login", :login => "quentin", :password => "password", :remember_me => "1"
|
82
|
-
|
83
|
-
assert_equal session[:remember_for], 86400 * 14
|
84
|
-
|
85
|
-
get "/logout"
|
86
|
-
|
87
|
-
assert_equal nil, session[:remember_for]
|
88
|
-
end
|
89
|
-
end
|
data/test/helper.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
$:.unshift(File.expand_path("../lib", File.dirname(__FILE__)))
|
2
|
-
|
3
|
-
require "shield"
|
4
|
-
require "cutest"
|
5
|
-
require "rack/test"
|
6
|
-
require "cuba"
|
7
|
-
require "sinatra/base"
|
8
|
-
|
9
|
-
class Cutest::Scope
|
10
|
-
include Rack::Test::Methods
|
11
|
-
|
12
|
-
def assert_redirected_to(path)
|
13
|
-
unless last_response.status == 302
|
14
|
-
flunk
|
15
|
-
end
|
16
|
-
assert_equal path, URI(last_response.headers["Location"]).path
|
17
|
-
end
|
18
|
-
|
19
|
-
def redirection_url
|
20
|
-
last_response.headers["Location"]
|
21
|
-
end
|
22
|
-
|
23
|
-
def session
|
24
|
-
last_request.env["rack.session"]
|
25
|
-
end
|
26
|
-
end
|
data/test/middleware.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
require File.expand_path("helper", File.dirname(__FILE__))
|
2
|
-
require File.expand_path("user", File.dirname(__FILE__))
|
3
|
-
|
4
|
-
Cuba.use Rack::Session::Cookie
|
5
|
-
Cuba.use Shield::Middleware
|
6
|
-
|
7
|
-
Cuba.plugin Shield::Helpers
|
8
|
-
|
9
|
-
Cuba.define do
|
10
|
-
on "secured" do
|
11
|
-
if not authenticated(User)
|
12
|
-
halt [401, { "Content-Type" => "text/html" }, []]
|
13
|
-
end
|
14
|
-
|
15
|
-
res.write "You're in"
|
16
|
-
end
|
17
|
-
|
18
|
-
on "foo" do
|
19
|
-
puts env.inspect
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
test do
|
24
|
-
env = { "PATH_INFO" => "/secured", "SCRIPT_NAME" => "" }
|
25
|
-
status, headers, body = Cuba.call(env)
|
26
|
-
|
27
|
-
assert_equal 302, status
|
28
|
-
assert_equal "/login?return=%2Fsecured", headers["Location"]
|
29
|
-
end
|
data/test/model.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
require File.expand_path("helper", File.dirname(__FILE__))
|
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
|
data/test/nested.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require File.expand_path("helper", File.dirname(__FILE__))
|
2
|
-
require File.expand_path("user", File.dirname(__FILE__))
|
3
|
-
|
4
|
-
Cuba.use Rack::Session::Cookie
|
5
|
-
Cuba.plugin Shield::Helpers
|
6
|
-
|
7
|
-
class Admin < Cuba
|
8
|
-
use Shield::Middleware, "/admin/login"
|
9
|
-
|
10
|
-
define do
|
11
|
-
on "login" do
|
12
|
-
res.write "Login"
|
13
|
-
end
|
14
|
-
|
15
|
-
on default do
|
16
|
-
res.status = 401
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
Cuba.define do
|
22
|
-
on "admin" do
|
23
|
-
run Admin
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
scope do
|
28
|
-
def app
|
29
|
-
Cuba
|
30
|
-
end
|
31
|
-
|
32
|
-
setup do
|
33
|
-
clear_cookies
|
34
|
-
end
|
35
|
-
|
36
|
-
test "return + return flow" do
|
37
|
-
get "/admin"
|
38
|
-
assert_equal "/admin/login?return=%2Fadmin", redirection_url
|
39
|
-
end
|
40
|
-
end
|
data/test/ohm.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require_relative "helper"
|
2
|
-
require "ohm"
|
3
|
-
|
4
|
-
class User < Ohm::Model
|
5
|
-
include Shield::Model
|
6
|
-
|
7
|
-
attribute :email
|
8
|
-
attribute :crypted_password
|
9
|
-
index :email
|
10
|
-
|
11
|
-
def self.fetch(email)
|
12
|
-
find(email: email).first
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
prepare do
|
17
|
-
Ohm.flush
|
18
|
-
end
|
19
|
-
|
20
|
-
setup do
|
21
|
-
User.create(email: "foo@bar.com", password: "pass1234")
|
22
|
-
end
|
23
|
-
|
24
|
-
test "fetch" do |user|
|
25
|
-
assert_equal user, User.fetch("foo@bar.com")
|
26
|
-
end
|
27
|
-
|
28
|
-
test "authenticate" do |user|
|
29
|
-
assert_equal user, User.authenticate("foo@bar.com", "pass1234")
|
30
|
-
end
|
data/test/password.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
require File.expand_path("helper", File.dirname(__FILE__))
|
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
|
-
end
|
data/test/sequel.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require_relative "helper"
|
2
|
-
require "sequel"
|
3
|
-
|
4
|
-
DB = Sequel.sqlite
|
5
|
-
|
6
|
-
DB.run(%(
|
7
|
-
CREATE TABLE users (
|
8
|
-
id INTEGER PRIMARY KEY,
|
9
|
-
email VARCHAR(255) UNIQUE,
|
10
|
-
crypted_password VARCHAR(255)
|
11
|
-
)
|
12
|
-
))
|
13
|
-
|
14
|
-
class User < Sequel::Model
|
15
|
-
include Shield::Model
|
16
|
-
|
17
|
-
def self.fetch(email)
|
18
|
-
filter(email: email).first
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
prepare do
|
23
|
-
User.truncate
|
24
|
-
end
|
25
|
-
|
26
|
-
setup do
|
27
|
-
User.create(email: "foo@bar.com", password: "pass1234")
|
28
|
-
end
|
29
|
-
|
30
|
-
test "fetch" do |user|
|
31
|
-
assert_equal user, User.fetch("foo@bar.com")
|
32
|
-
end
|
33
|
-
|
34
|
-
test "authenticate" do |user|
|
35
|
-
assert_equal user, User.authenticate("foo@bar.com", "pass1234")
|
36
|
-
end
|
data/test/shield.rb
DELETED
@@ -1,93 +0,0 @@
|
|
1
|
-
require File.expand_path("helper", File.dirname(__FILE__))
|
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.authenticate(User[1001])
|
91
|
-
|
92
|
-
assert User[1] == context.authenticated(User)
|
93
|
-
end
|
data/test/sinatra.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
require File.expand_path("helper", File.dirname(__FILE__))
|
2
|
-
require File.expand_path("user", File.dirname(__FILE__))
|
3
|
-
|
4
|
-
class SinatraApp < Sinatra::Base
|
5
|
-
use Shield::Middleware
|
6
|
-
enable :sessions
|
7
|
-
helpers Shield::Helpers
|
8
|
-
|
9
|
-
get "/public" do
|
10
|
-
"Public"
|
11
|
-
end
|
12
|
-
|
13
|
-
get "/private" do
|
14
|
-
error(401) unless authenticated(User)
|
15
|
-
|
16
|
-
"Private"
|
17
|
-
end
|
18
|
-
|
19
|
-
get "/login" do
|
20
|
-
"Login"
|
21
|
-
end
|
22
|
-
|
23
|
-
post "/login" do
|
24
|
-
if login(User, params[:login], params[:password], params[:remember_me])
|
25
|
-
redirect(params[:return] || "/")
|
26
|
-
else
|
27
|
-
redirect "/login"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
get "/logout" do
|
32
|
-
logout(User)
|
33
|
-
redirect "/"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
scope do
|
38
|
-
def app
|
39
|
-
SinatraApp.new
|
40
|
-
end
|
41
|
-
|
42
|
-
setup do
|
43
|
-
clear_cookies
|
44
|
-
end
|
45
|
-
|
46
|
-
test "public" do
|
47
|
-
get "/public"
|
48
|
-
assert "Public" == last_response.body
|
49
|
-
end
|
50
|
-
|
51
|
-
test "successful logging in" do
|
52
|
-
get "/private"
|
53
|
-
|
54
|
-
assert_equal "/login?return=%2Fprivate", redirection_url
|
55
|
-
|
56
|
-
post "/login", :login => "quentin", :password => "password",
|
57
|
-
:return => "/private"
|
58
|
-
|
59
|
-
assert_redirected_to "/private"
|
60
|
-
|
61
|
-
assert 1001 == session["User"]
|
62
|
-
end
|
63
|
-
|
64
|
-
test "failed login" do
|
65
|
-
post "/login", :login => "q", :password => "p"
|
66
|
-
assert_redirected_to "/login"
|
67
|
-
|
68
|
-
assert nil == session["User"]
|
69
|
-
end
|
70
|
-
|
71
|
-
test "logging out" do
|
72
|
-
post "/login", :login => "quentin", :password => "password"
|
73
|
-
|
74
|
-
get "/logout"
|
75
|
-
|
76
|
-
assert nil == session["User"]
|
77
|
-
end
|
78
|
-
|
79
|
-
test "remember functionality" do
|
80
|
-
post "/login", :login => "quentin", :password => "password", :remember_me => "1"
|
81
|
-
|
82
|
-
assert_equal session[:remember_for], 86400 * 14
|
83
|
-
|
84
|
-
get "/logout"
|
85
|
-
|
86
|
-
assert_equal nil, session[:remember_for]
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
if $0 == __FILE__
|
91
|
-
SinatraApp.run!
|
92
|
-
end
|
data/test/user.rb
DELETED
@@ -1,21 +0,0 @@
|
|
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
|