authlane 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +42 -15
- data/lib/authlane/helper.rb +38 -16
- data/lib/authlane/serializeduser.rb +14 -2
- data/lib/authlane/version.rb +1 -1
- data/lib/sinatra/authlane.rb +29 -26
- data/spec/authlane_helper_spec.rb +51 -1
- data/spec/authlane_serializeduser_spec.rb +23 -0
- data/spec/sinatra_authlane_spec.rb +40 -7
- data/spec/sinatra_custom_serializeduser_spec.rb +52 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60d5057e5de15303320296fc4968ee7e2e4599b1
|
4
|
+
data.tar.gz: 37bcce0af17f5e6061c380d622de64648f4fce9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7e5575bfdf4a157890f5653c1ef53b8d3d5843ff068fe7ed48d6863da4613e6208102ebc22d958062b5c8019cb842a35614f45b53bc971a7e488699032e59e2
|
7
|
+
data.tar.gz: e5bc08034ee0ffe129238e1d04c3df7c13ef0cb0688b0b644536385d75e558baf9bac0314172bff973c2208c4cef17e95e5f790882e28d4df53e747a50ab0e5f
|
data/README.md
CHANGED
@@ -4,11 +4,24 @@ The **AuthLane** Sinatra Extension allows easy User authentication with support
|
|
4
4
|
|
5
5
|
The actual authentication logic (*strategy*) is defined by the Application using a namespaced DSL provided by this extension, while the general Extension configuration is handled with Sinatra's `set` method, which will be described in more detail below.
|
6
6
|
|
7
|
-
##
|
7
|
+
## Installation
|
8
8
|
|
9
|
-
|
9
|
+
Get the Gem:
|
10
10
|
|
11
11
|
```
|
12
|
+
gem install authlane
|
13
|
+
```
|
14
|
+
|
15
|
+
Or let Bundler do the work:
|
16
|
+
|
17
|
+
``` ruby
|
18
|
+
# Gemfile
|
19
|
+
gem 'authlane'
|
20
|
+
```
|
21
|
+
|
22
|
+
**AuthLane** utilizes the standard Sinatra Extension format for *classic*-style applications:
|
23
|
+
|
24
|
+
``` ruby
|
12
25
|
require 'sinatra'
|
13
26
|
require 'sinatra/authlane'
|
14
27
|
|
@@ -21,7 +34,7 @@ end
|
|
21
34
|
|
22
35
|
As well as `modular`-style applications:
|
23
36
|
|
24
|
-
```
|
37
|
+
``` ruby
|
25
38
|
require 'sinatra/base'
|
26
39
|
require 'sinatra/cookies'
|
27
40
|
require 'sinatra/authlane'
|
@@ -33,28 +46,22 @@ class App < Sinatra::Base
|
|
33
46
|
get '/user' do
|
34
47
|
protect!
|
35
48
|
|
36
|
-
# Application stuff for signed in users
|
49
|
+
# Application stuff for signed in users
|
37
50
|
end
|
38
51
|
end
|
39
|
-
|
40
|
-
|
41
|
-
Both setups however require a separate **Session** *Rack middleware*, like `Rack::Session::Cookies`, which you need to provide for your *Sinatra* application (refer to [Sinatra's documentation](http://www.sinatrarb.com/intro.html#Using%20Sessions) on using Sessions).
|
42
|
-
|
43
|
-
> **Note:** The inclusion of `sinatra/cookies` helper methods is a requirement by *AuthLane*, which currently it - at least when used modular - does not do automatically.
|
44
|
-
|
45
|
-
## Configuring *AuthLane*
|
52
|
+
```
|
46
53
|
|
47
|
-
|
54
|
+
## Configuration
|
48
55
|
|
49
56
|
**AuthLane**'s configuration data is available under Sinatra's `settings` object with the key `:authlane` as a Hash, so changing config values is simply done with Sinatra's `set` method.
|
50
57
|
|
51
|
-
```
|
58
|
+
``` ruby
|
52
59
|
set :authlane, :failed_route => '/login'
|
53
60
|
```
|
54
61
|
|
55
62
|
The following settings can be customize (the used values are their defaults):
|
56
63
|
|
57
|
-
```
|
64
|
+
``` ruby
|
58
65
|
set :authlane, :failed_route => '/user/unauthorized',
|
59
66
|
:session_key => :authlane,
|
60
67
|
:remember_cookie => :authlane_token,
|
@@ -75,4 +82,24 @@ Customize the Cookie's name that stores the token hash used for the *Remember Me
|
|
75
82
|
|
76
83
|
#### `:serialize_user`
|
77
84
|
|
78
|
-
The `:serialized_user` settings contains an Array of Symbols telling AuthLane which attributes of the User model that is used to identify Application users should be serialized into `SerializedUser
|
85
|
+
The `:serialized_user` settings contains an Array of Symbols telling AuthLane which attributes of the User model that is used to identify Application users should be serialized into a `SerializedUser` object. It is recommended to not store the whole User object, but note that the *id* (or however the unique identifier of the object is named) attribute is required.
|
86
|
+
|
87
|
+
Alternatively, you can specify your own Class to be used.
|
88
|
+
|
89
|
+
``` ruby
|
90
|
+
set :authlane, :serialize_user => CustomUser
|
91
|
+
```
|
92
|
+
|
93
|
+
The `CustomUser`'s `initialize` method receives one argument, which is the User object. What that object is exactly depends on your **Auth strategy** implementation. Basically, it's the User data coming from your application's persisting backend, like a database.
|
94
|
+
|
95
|
+
``` ruby
|
96
|
+
class CustomUser
|
97
|
+
attr_reader :id
|
98
|
+
|
99
|
+
def initialize(user)
|
100
|
+
@id = user.id
|
101
|
+
end
|
102
|
+
end
|
103
|
+
```
|
104
|
+
|
105
|
+
It is possible to have attribute accessors in your custom Class, but beware that **AuthLane** will *not* save changes back to your backend.
|
data/lib/authlane/helper.rb
CHANGED
@@ -8,7 +8,8 @@ module Sinatra
|
|
8
8
|
#
|
9
9
|
module Helpers
|
10
10
|
##
|
11
|
-
# @note This method uses {#authorized?} to decide, whether to redirect users to `failed_route`.
|
11
|
+
# @note This method uses {#authorized?} to decide, whether to redirect users to your app's `failed_route`.
|
12
|
+
#
|
12
13
|
# Check if a user is authorized to view a route.
|
13
14
|
#
|
14
15
|
# It utilizes the *Role* and *Remember Strategy* to see if a user can access the route this
|
@@ -33,17 +34,16 @@ module Sinatra
|
|
33
34
|
# mustache :admin
|
34
35
|
# end
|
35
36
|
#
|
36
|
-
# @param [
|
37
|
-
#
|
37
|
+
# @param [Hash] roles A Hash specifying the **Role Strategy** to be used with its key and optional arguments as the value.
|
38
|
+
# **Example:** `protect! :rolename => arguments`
|
39
|
+
#
|
40
|
+
# @return [void]
|
38
41
|
#
|
39
42
|
# @see Sinatra::AuthLane.create_role_strategy create_role_strategy
|
40
43
|
# @see Sinatra::AuthLane.create_remember_strategy create_remember_strategy
|
41
44
|
#
|
42
|
-
def protect!(roles
|
43
|
-
|
44
|
-
failed_route ||= settings.authlane[:failed_route]
|
45
|
-
|
46
|
-
redirect failed_route unless authorized?(roles: roles)
|
45
|
+
def protect!(*roles)
|
46
|
+
redirect settings.authlane[:failed_route] unless authorized?(*roles)
|
47
47
|
end
|
48
48
|
|
49
49
|
alias_method :protected, :protect!
|
@@ -64,22 +64,23 @@ module Sinatra
|
|
64
64
|
# end
|
65
65
|
# end
|
66
66
|
#
|
67
|
-
# @param [
|
67
|
+
# @param [Hash] roles A Hash specifying the **Role Strategy** to be used with its key and optional arguments as the value.
|
68
|
+
# **Example:** `protect! :rolename => arguments`
|
68
69
|
#
|
69
70
|
# @return [Boolean] `true` if the user is authorized to view a route, `false` otherwise.
|
70
71
|
#
|
71
72
|
# @see Sinatra::AuthLane::Helpers#protect! protect!
|
72
73
|
#
|
73
|
-
def authorized?(roles
|
74
|
+
def authorized?(*roles)
|
74
75
|
# So, if session[settings.authlane[:session_key]] is available
|
75
76
|
# we're home, otherwise, see if the 'Remember Me' strategy
|
76
77
|
# can come up with some User credentials.
|
77
78
|
if session[settings.authlane[:session_key]].nil?
|
78
79
|
remember_token = cookies[settings.authlane[:remember_cookie]]
|
79
|
-
remember_strat = self.instance_exec(remember_token, &settings.authlane[:remember_strategy])
|
80
|
+
remember_strat = (remember_token.nil?) ? false : self.instance_exec(remember_token, &settings.authlane[:remember_strategy])
|
80
81
|
|
81
82
|
if remember_strat
|
82
|
-
user =
|
83
|
+
user = serialize_user(remember_strat)
|
83
84
|
|
84
85
|
# The strategy doesn't log in a User,
|
85
86
|
# it just comes up with the credentials to do that.
|
@@ -95,11 +96,19 @@ module Sinatra
|
|
95
96
|
return false
|
96
97
|
else
|
97
98
|
# User is logged in ...
|
98
|
-
|
99
|
+
if roles.size == 1
|
99
100
|
# ... but hold up, he might not have the necessary
|
100
101
|
# privileges to access this particular route.
|
101
102
|
# Let's ask the 'Role' strategy.
|
102
|
-
|
103
|
+
if roles.first.is_a? Hash
|
104
|
+
role_name = roles.first.keys.first
|
105
|
+
role_args = roles.first[role_name]
|
106
|
+
else
|
107
|
+
role_name = roles.first
|
108
|
+
role_args = nil
|
109
|
+
end
|
110
|
+
|
111
|
+
strat = self.instance_exec role_args, &settings.authlane[:role_strategy][role_name]
|
103
112
|
return false unless strat
|
104
113
|
end
|
105
114
|
end
|
@@ -139,7 +148,7 @@ module Sinatra
|
|
139
148
|
redirect settings.authlane[:failed_route], 303
|
140
149
|
end
|
141
150
|
|
142
|
-
session[settings.authlane[:session_key]] =
|
151
|
+
session[settings.authlane[:session_key]] = serialize_user(strat)
|
143
152
|
end
|
144
153
|
|
145
154
|
##
|
@@ -182,11 +191,24 @@ module Sinatra
|
|
182
191
|
# mustache :account
|
183
192
|
# end
|
184
193
|
#
|
185
|
-
# @return [SerializedUser] the user data serialized into the Session
|
194
|
+
# @return [SerializedUser, Object] the user data serialized into the Session, either as `SerializedUser`
|
195
|
+
# or a custom class set by the developer.
|
186
196
|
#
|
187
197
|
def current_user
|
188
198
|
session[settings.authlane[:session_key]]
|
189
199
|
end
|
200
|
+
|
201
|
+
private
|
202
|
+
|
203
|
+
##
|
204
|
+
#
|
205
|
+
def serialize_user(obj)
|
206
|
+
if settings.authlane[:serialize_user].is_a? Array
|
207
|
+
Sinatra::AuthLane::SerializedUser.new(obj, settings.authlane[:serialize_user])
|
208
|
+
elsif settings.authlane[:serialize_user].is_a? Class
|
209
|
+
settings.authlane[:serialize_user].new(obj)
|
210
|
+
end
|
211
|
+
end
|
190
212
|
end
|
191
213
|
end
|
192
214
|
end
|
@@ -45,6 +45,14 @@ module Sinatra
|
|
45
45
|
(@user.is_a? Hash) ? @user[a] : @user.__send__(a.to_sym)
|
46
46
|
end
|
47
47
|
|
48
|
+
##
|
49
|
+
#
|
50
|
+
#
|
51
|
+
def []=(key, value)
|
52
|
+
return if key.to_s == 'id'
|
53
|
+
(@user.is_a? Hash) ? @user[key] = value : @user.__send__(key.to_sym, value)
|
54
|
+
end
|
55
|
+
|
48
56
|
##
|
49
57
|
# Enables Object-like access to the
|
50
58
|
# stored attributes.
|
@@ -58,9 +66,13 @@ module Sinatra
|
|
58
66
|
#
|
59
67
|
def method_missing(m, *args, &block)
|
60
68
|
if @user.is_a? Hash
|
61
|
-
|
69
|
+
if m.to_s.index('=').nil?
|
70
|
+
@user[m]
|
71
|
+
elsif m.to_s.index('id').nil?
|
72
|
+
@user[m] = args[1]
|
73
|
+
end
|
62
74
|
else
|
63
|
-
@user.__send__(m
|
75
|
+
@user.__send__(m, args)
|
64
76
|
end
|
65
77
|
end
|
66
78
|
|
data/lib/authlane/version.rb
CHANGED
data/lib/sinatra/authlane.rb
CHANGED
@@ -86,10 +86,11 @@ module Sinatra
|
|
86
86
|
:session_key => :authlane, # name of the Session key to store the login data
|
87
87
|
:remember_cookie => :'authlane.token', # Cookie name to store 'Remember Me' token
|
88
88
|
:auth_strategy => Proc.new { false }, # strategy to be executed to log in users
|
89
|
-
:role_strategy => Proc.new { true }, # strategy to be executed to check permissions and roles
|
89
|
+
:role_strategy => { roles: Proc.new { true } }, # strategy to be executed to check permissions and roles
|
90
90
|
:remember_strategy => Proc.new { false }, # strategy to be executed to log in users via 'Remember Me' token
|
91
91
|
:forget_strategy => Proc.new { false }, # strategy to be executed when logging out and 'forgetting' the user
|
92
92
|
:serialize_user => [:id] # specify User model fields to be serialized into the login session
|
93
|
+
# or define a custom class which receives the whole User model to handle by itself
|
93
94
|
end
|
94
95
|
|
95
96
|
class << self
|
@@ -100,14 +101,12 @@ module Sinatra
|
|
100
101
|
# to be used by passing the implementation as a Code block. It is then
|
101
102
|
# stored as a `Proc` object and will be called by AuthLane when needed.
|
102
103
|
#
|
103
|
-
#
|
104
|
-
# required by the implemented strategy to follow these to be usable by AuthLane.
|
104
|
+
# To see the code block's objects API requirements, refer to the {https://github.com/zidizei/authlane/wiki Wiki}.
|
105
105
|
#
|
106
106
|
# @note While the **Auth** Strategy is primarily responsible for logging in users,
|
107
107
|
# it usually needs to implement some *Remember Me* logic as well.
|
108
108
|
#
|
109
|
-
# @return [
|
110
|
-
# the user that successfully logged in or - in case of failure - `false`.
|
109
|
+
# @return [Proc] the `Proc` object of the strategy.
|
111
110
|
#
|
112
111
|
# @example
|
113
112
|
# Sinatra::AuthLane.create_auth_strategy do
|
@@ -121,7 +120,10 @@ module Sinatra
|
|
121
120
|
# @api AuthLane
|
122
121
|
#
|
123
122
|
def create_auth_strategy
|
124
|
-
|
123
|
+
strat = Proc.new
|
124
|
+
|
125
|
+
@app.set :authlane, :auth_strategy => strat
|
126
|
+
strat
|
125
127
|
end
|
126
128
|
|
127
129
|
##
|
@@ -131,8 +133,7 @@ module Sinatra
|
|
131
133
|
# to be used by passing the implementation as a Code block. It is then
|
132
134
|
# stored as a `Proc` object and will be called by AuthLane when needed.
|
133
135
|
#
|
134
|
-
#
|
135
|
-
# required by the implemented strategy to follow these to be usable by AuthLane.
|
136
|
+
# To see the code block's API requirements, refer to the {https://github.com/zidizei/authlane/wiki Wiki}.
|
136
137
|
#
|
137
138
|
# @example
|
138
139
|
# Sinatra::AuthLane.create_role_strategy do |roles|
|
@@ -141,18 +142,19 @@ module Sinatra
|
|
141
142
|
# roles.include? user.role # See if the list of role names in `roles` contains the user's role
|
142
143
|
# end
|
143
144
|
#
|
144
|
-
# @param [
|
145
|
-
# to be allowed to see the route. The list is passed by the {Sinatra::AuthLane::Helpers#authorized? authorized?}
|
146
|
-
# helper.
|
145
|
+
# @param [Symbol] name The name of the role strategy.
|
147
146
|
#
|
148
|
-
# @return [
|
147
|
+
# @return [Proc] the `Proc` object of the strategy.
|
149
148
|
#
|
150
149
|
# @see Sinatra::AuthLane::Helpers#authorized? authorized?
|
151
150
|
#
|
152
151
|
# @api AuthLane
|
153
152
|
#
|
154
|
-
def create_role_strategy
|
155
|
-
|
153
|
+
def create_role_strategy(name = :roles)
|
154
|
+
strat = Proc.new
|
155
|
+
|
156
|
+
@app.settings.authlane[:role_strategy][name] = strat
|
157
|
+
strat
|
156
158
|
end
|
157
159
|
|
158
160
|
##
|
@@ -162,8 +164,7 @@ module Sinatra
|
|
162
164
|
# to be used by passing the implementation as a Code block. It is then
|
163
165
|
# stored as a `Proc` object and will be called by AuthLane when needed.
|
164
166
|
#
|
165
|
-
#
|
166
|
-
# required by the implemented strategy to follow these to be usable by AuthLane.
|
167
|
+
# To see the code block's API requirements, refer to the {https://github.com/zidizei/authlane/wiki Wiki}.
|
167
168
|
#
|
168
169
|
# @note The **Remember** Strategy is only responsible for automatically logging in a user.
|
169
170
|
# The necessary Cookie token (plus any additional logic) is usually set in the **Auth** Strategy.
|
@@ -175,15 +176,17 @@ module Sinatra
|
|
175
176
|
# (remembered_user.nil?) ? false : remembered_user
|
176
177
|
# end
|
177
178
|
#
|
178
|
-
# @return [
|
179
|
-
# the user that successfully logged in or - in case of failure - `false`.
|
179
|
+
# @return [Proc] the `Proc` object of the strategy.
|
180
180
|
#
|
181
181
|
# @see Sinatra::AuthLane::Helpers#authorized? authorized?
|
182
182
|
#
|
183
183
|
# @api AuthLane
|
184
184
|
#
|
185
185
|
def create_remember_strategy
|
186
|
-
|
186
|
+
strat = Proc.new
|
187
|
+
|
188
|
+
@app.set :authlane, :remember_strategy => strat
|
189
|
+
strat
|
187
190
|
end
|
188
191
|
|
189
192
|
##
|
@@ -193,13 +196,12 @@ module Sinatra
|
|
193
196
|
# to be used by passing the implementation as a Code block. It is then
|
194
197
|
# stored as a `Proc` object and will be called by AuthLane when needed.
|
195
198
|
#
|
196
|
-
#
|
197
|
-
# required by the implemented strategy to follow these to be usable by AuthLane.
|
199
|
+
# To see the code block's API requirements, refer to the {https://github.com/zidizei/authlane/wiki Wiki}.
|
198
200
|
#
|
199
201
|
# @note The **Forget** Strategy is the counter-part to the **Remember** Strategy.
|
200
202
|
# It's responsible for disabling the auto login technique and is called when logging out.
|
201
203
|
#
|
202
|
-
# @note While the *Auth
|
204
|
+
# @note While the *Auth Strategy* needs to interact with the Cookie token directly,
|
203
205
|
# the *Forget Strategy* does not need to implement the deletion of the Cookie.
|
204
206
|
# This is done automatically by AuthLane behind the scenes.
|
205
207
|
#
|
@@ -209,16 +211,17 @@ module Sinatra
|
|
209
211
|
# user.token = nil if user.token == token
|
210
212
|
# end
|
211
213
|
#
|
212
|
-
# @param [Object] token The `Proc` object receives the *Remember Me* token of the current user.
|
213
|
-
#
|
214
214
|
# @see Sinatra::AuthLane::Helpers#unauthorize! unauthorize!
|
215
215
|
#
|
216
|
-
# @return [
|
216
|
+
# @return [Proc] the `Proc` object of the strategy.
|
217
217
|
#
|
218
218
|
# @api AuthLane
|
219
219
|
#
|
220
220
|
def create_forget_strategy
|
221
|
-
|
221
|
+
strat = Proc.new
|
222
|
+
|
223
|
+
@app.set :authlane, :forget_strategy => strat
|
224
|
+
strat
|
222
225
|
end
|
223
226
|
end
|
224
227
|
end
|
@@ -10,9 +10,19 @@ describe Sinatra::AuthLane::Helpers do
|
|
10
10
|
|
11
11
|
use Rack::Session::Cookie, :secret => 'rspec'
|
12
12
|
|
13
|
+
set :authlane, :serialize_user => [:id, :rank]
|
14
|
+
|
13
15
|
Sinatra::AuthLane.create_auth_strategy do
|
14
16
|
cookies[:'authlane.token'] = 'rspec'
|
15
|
-
{ id: '1' }
|
17
|
+
{ id: '1', rank: 1 }
|
18
|
+
end
|
19
|
+
|
20
|
+
Sinatra::AuthLane.create_role_strategy do |ranks|
|
21
|
+
current_user[:rank] == ((ranks.nil?) ? 1 : ranks)
|
22
|
+
end
|
23
|
+
|
24
|
+
Sinatra::AuthLane.create_role_strategy(:roles2) do |ranks|
|
25
|
+
current_user[:rank] == ((ranks.nil?) ? 2 : ranks)
|
16
26
|
end
|
17
27
|
|
18
28
|
get '/protected' do
|
@@ -32,6 +42,22 @@ describe Sinatra::AuthLane::Helpers do
|
|
32
42
|
protect!
|
33
43
|
end
|
34
44
|
|
45
|
+
get '/role1' do
|
46
|
+
protect! :roles
|
47
|
+
end
|
48
|
+
|
49
|
+
get '/role1a' do
|
50
|
+
protect! :roles => 2
|
51
|
+
end
|
52
|
+
|
53
|
+
get '/role2' do
|
54
|
+
protect! :roles2
|
55
|
+
end
|
56
|
+
|
57
|
+
get '/role2a' do
|
58
|
+
protect! :roles2 => 1
|
59
|
+
end
|
60
|
+
|
35
61
|
get '/unauthorize' do
|
36
62
|
unauthorize!
|
37
63
|
protect!
|
@@ -106,4 +132,28 @@ describe Sinatra::AuthLane::Helpers do
|
|
106
132
|
get '/user'#, {}, { 'rack.session' => { authlane: '1' } }
|
107
133
|
expect(last_response.body).to eq('1')
|
108
134
|
end
|
135
|
+
|
136
|
+
it "should be able to use role strategy" do
|
137
|
+
get '/authorize'
|
138
|
+
get '/role1'
|
139
|
+
last_response.should be_ok
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should be able to use role strategy with arguments" do
|
143
|
+
get '/authorize'
|
144
|
+
get '/role1a'
|
145
|
+
expect(last_response.headers['location']).to eq('http://example.org/user/unauthorized')
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should be able to use named role strategy" do
|
149
|
+
get '/authorize'
|
150
|
+
get '/role2'
|
151
|
+
expect(last_response.headers['location']).to eq('http://example.org/user/unauthorized')
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should be able to use named role strategy with arguments" do
|
155
|
+
get '/authorize'
|
156
|
+
get '/role2a'
|
157
|
+
last_response.should be_ok
|
158
|
+
end
|
109
159
|
end
|
@@ -53,4 +53,27 @@ describe Sinatra::AuthLane::SerializedUser do
|
|
53
53
|
user[:id].should eql(1)
|
54
54
|
user[:name].should be(nil)
|
55
55
|
end
|
56
|
+
|
57
|
+
it 'can change specific attributes after initialization from an Object' do
|
58
|
+
user = Sinatra::AuthLane::SerializedUser.new(MockUser.new, [:id])
|
59
|
+
user[:id].should eql(1)
|
60
|
+
user[:name].should be(nil)
|
61
|
+
user[:name] = 'Rspec'
|
62
|
+
user[:name].should eql('Rspec')
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'can change specific attributes after initialization from a Hash' do
|
66
|
+
user = Sinatra::AuthLane::SerializedUser.new({ id: 1, name: nil }, [:id])
|
67
|
+
user[:id].should eql(1)
|
68
|
+
user[:name].should be(nil)
|
69
|
+
user[:name] = 'Rspec'
|
70
|
+
user[:name].should eql('Rspec')
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'can not change id attribute after initialization' do
|
74
|
+
user = Sinatra::AuthLane::SerializedUser.new(MockUser.new, [:id])
|
75
|
+
user[:id].should eql(1)
|
76
|
+
user[:id] = 2
|
77
|
+
user[:id].should eql(1)
|
78
|
+
end
|
56
79
|
end
|
@@ -1,16 +1,41 @@
|
|
1
1
|
require File.expand_path '../spec_helper.rb', __FILE__
|
2
2
|
|
3
3
|
describe Sinatra::AuthLane do
|
4
|
-
def
|
4
|
+
def create_auth_strategy(&block)
|
5
5
|
mock_app do
|
6
6
|
register Sinatra::AuthLane
|
7
7
|
|
8
|
-
Sinatra::AuthLane.
|
8
|
+
Sinatra::AuthLane.create_auth_strategy &block
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
+
def create_role_strategy(name = :roles, &block)
|
13
|
+
mock_app do
|
14
|
+
register Sinatra::AuthLane
|
15
|
+
|
16
|
+
Sinatra::AuthLane.create_role_strategy(name, &block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_remember_strategy(&block)
|
21
|
+
mock_app do
|
22
|
+
register Sinatra::AuthLane
|
23
|
+
|
24
|
+
Sinatra::AuthLane.create_remember_strategy &block
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_forget_strategy(&block)
|
29
|
+
mock_app do
|
30
|
+
register Sinatra::AuthLane
|
31
|
+
|
32
|
+
Sinatra::AuthLane.create_forget_strategy &block
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
12
37
|
it "should allow definition of auth strategy" do
|
13
|
-
|
38
|
+
create_auth_strategy do
|
14
39
|
'rspec'
|
15
40
|
end
|
16
41
|
|
@@ -18,15 +43,23 @@ describe Sinatra::AuthLane do
|
|
18
43
|
end
|
19
44
|
|
20
45
|
it "should allow definition of role strategy" do
|
21
|
-
|
46
|
+
create_role_strategy do
|
22
47
|
'rspec'
|
23
48
|
end
|
24
49
|
|
25
|
-
settings.authlane[:role_strategy].yield.should == 'rspec'
|
50
|
+
settings.authlane[:role_strategy][:roles].yield.should == 'rspec'
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should allow definition of named role strategies" do
|
54
|
+
create_role_strategy(:rspec1) do
|
55
|
+
'rspec1'
|
56
|
+
end
|
57
|
+
|
58
|
+
settings.authlane[:role_strategy][:rspec1].yield.should == 'rspec1'
|
26
59
|
end
|
27
60
|
|
28
61
|
it "should allow definition of remember strategy" do
|
29
|
-
|
62
|
+
create_remember_strategy do
|
30
63
|
'rspec'
|
31
64
|
end
|
32
65
|
|
@@ -34,7 +67,7 @@ describe Sinatra::AuthLane do
|
|
34
67
|
end
|
35
68
|
|
36
69
|
it "should allow definition of forget strategy" do
|
37
|
-
|
70
|
+
create_forget_strategy do
|
38
71
|
'rspec'
|
39
72
|
end
|
40
73
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.expand_path '../spec_helper.rb', __FILE__
|
2
|
+
|
3
|
+
describe Sinatra::AuthLane do
|
4
|
+
class Serialized
|
5
|
+
attr_reader :id
|
6
|
+
|
7
|
+
def initialize(user)
|
8
|
+
serialize(user)
|
9
|
+
end
|
10
|
+
|
11
|
+
def serialize(user)
|
12
|
+
@id = user[:id]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
before :all do
|
17
|
+
build_rack_test_session 'rspec'
|
18
|
+
|
19
|
+
mock_app do
|
20
|
+
helpers Sinatra::Cookies
|
21
|
+
register Sinatra::AuthLane
|
22
|
+
|
23
|
+
use Rack::Session::Cookie, :secret => 'rspec'
|
24
|
+
|
25
|
+
set :authlane, serialize_user: Serialized
|
26
|
+
|
27
|
+
Sinatra::AuthLane.create_auth_strategy do
|
28
|
+
cookies[:'authlane.token'] = 'rspec'
|
29
|
+
{ id: '1', name: 'rspec' }
|
30
|
+
end
|
31
|
+
|
32
|
+
get '/authorize' do
|
33
|
+
authorize!
|
34
|
+
protect!
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
before :each do
|
40
|
+
clear_cookies
|
41
|
+
end
|
42
|
+
|
43
|
+
def current_user
|
44
|
+
Marshal.load(rack_mock_session.cookie_jar['rack.session'].unpack('m*').first)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'uses custom SerializedUser class instead of the built-in one when specified' do
|
48
|
+
get '/authorize'
|
49
|
+
last_response.should be_ok
|
50
|
+
expect(current_user['authlane']).to be_a Serialized
|
51
|
+
end
|
52
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: authlane
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Patrick Lam
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01
|
11
|
+
date: 2015-04-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sinatra
|
@@ -117,6 +117,7 @@ files:
|
|
117
117
|
- spec/authlane_helper_spec.rb
|
118
118
|
- spec/authlane_serializeduser_spec.rb
|
119
119
|
- spec/sinatra_authlane_spec.rb
|
120
|
+
- spec/sinatra_custom_serializeduser_spec.rb
|
120
121
|
- spec/spec_helper.rb
|
121
122
|
homepage:
|
122
123
|
licenses:
|
@@ -138,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
139
|
version: '0'
|
139
140
|
requirements: []
|
140
141
|
rubyforge_project:
|
141
|
-
rubygems_version: 2.4.
|
142
|
+
rubygems_version: 2.4.1
|
142
143
|
signing_key:
|
143
144
|
specification_version: 4
|
144
145
|
summary: Simple User authentication and roles for Sinatra.
|
@@ -146,5 +147,6 @@ test_files:
|
|
146
147
|
- spec/authlane_helper_spec.rb
|
147
148
|
- spec/authlane_serializeduser_spec.rb
|
148
149
|
- spec/sinatra_authlane_spec.rb
|
150
|
+
- spec/sinatra_custom_serializeduser_spec.rb
|
149
151
|
- spec/spec_helper.rb
|
150
152
|
has_rdoc:
|