authlane 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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:
|