shield 1.0.0 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.authenicate("foo@bar.com", "wrong")
77
+ nil == User.authenticate("foo@bar.com", "wrong")
78
78
  # => true
79
79
  ```
80
80
 
81
- Shield includes tests for [ohm][ohm] and [sequel][sequel] and makes sure
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
- # Satisifies assumption number 1 above.
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], params[:remember_me])
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
- ## Jump starting your way.
244
+ ## Installation
222
245
 
223
- For people interested in using Cuba, Ohm, Shield and Bootstrap we've
224
- created a starting point that includes **Login**, **Signup** and
225
- **Forgot Password** functionality.
246
+ You can install it using rubygems:
226
247
 
227
- Head on over to the [cuba-app][cuba-app] repository if you want
228
- to know more.
229
-
230
- [cuba-app]: http://github.com/citrusbyte/cuba-app
248
+ ```
249
+ gem install shield
250
+ ```
@@ -1,4 +1,4 @@
1
- require "pbkdf2"
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, remember = false, expire = 1209600)
53
- return unless user = model.authenticate(username, password)
52
+ def login(model, username, password)
53
+ user = model.authenticate(username, password)
54
+ authenticate(user) if user
55
+ end
54
56
 
55
- session[:remember_for] = expire if remember
56
- authenticate(user)
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..127], encrypted.to_s[128..-1]
105
+ sha512, salt = encrypted.to_s[0...128], encrypted.to_s[128..-1]
112
106
 
113
- digest(password, salt) == sha512
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
- Digest::SHA512.hexdigest(Time.now.to_f.to_s)[0, 64]
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: 1.0.0
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: 2012-04-20 00:00:00.000000000 Z
13
+ date: 2013-04-15 00:00:00.000000000 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
- name: pbkdf2
18
- requirement: &70267284083060 !ruby/object:Gem::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: *70267284083060
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: &70267284081680 !ruby/object:Gem::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: *70267284081680
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: &70267284077380 !ruby/object:Gem::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: *70267284077380
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: &70267284076600 !ruby/object:Gem::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: *70267284076600
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: &70267284075620 !ruby/object:Gem::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: *70267284075620
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: &70267284074720 !ruby/object:Gem::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: *70267284074720
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: &70267284073820 !ruby/object:Gem::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: *70267284073820
93
- description: ! "\n Provides all the protocol you need in order to do authentication
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: '0'
143
+ version: 1.3.1
137
144
  requirements: []
138
145
  rubyforge_project:
139
- rubygems_version: 1.8.11
146
+ rubygems_version: 2.0.3
140
147
  signing_key:
141
- specification_version: 3
148
+ specification_version: 4
142
149
  summary: Generic authentication protocol for rack applications.
143
150
  test_files: []
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- desc "Run all tests using cutest."
2
- task :test do
3
- system("cutest -r ./test/helper ./test/*.rb")
4
- end
5
-
6
- task :default => :test
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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