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.
@@ -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