rack_warden 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.gitignore +1 -1
- data/README.md +96 -49
- data/lib/rack_warden/app.rb +45 -11
- data/lib/rack_warden/model.rb +6 -2
- data/lib/rack_warden/version.rb +1 -1
- data/lib/rack_warden/views/create_user.html.erb +3 -1
- data/lib/rack_warden/views/login_user.html.erb +4 -1
- data/lib/rack_warden/views/rw_admin.html.erb +18 -0
- data/lib/rack_warden.rb +2 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZjdjY2YyZWIwODFiZWVhY2FiNGNiOTNjNGE3ZGRiYjI0OWFlNWExMA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZjFjZTkwOTFhNWY5NTRlOTQxODM1NmZjOTAyNDlkMGE2OTFlMTk4NA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ODRhZDRjZTMyNGNmYmRkZTdmYzIyYWM5NGU3ZjcwZjEwOTdhNzI5OWZiOTg4
|
10
|
+
ZDZmMDdhYjA4ZWJhYWYzNTE4ZDNkNWJlZDZhZjg4MzcyZmNjMzYzN2U0YzUx
|
11
|
+
N2YxNDQyZjhmMjIzOTU3NjEzOTNjZDIzYzhmYzcyYTE3Mzc0NDQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZDdlMjNiMmIzMjU3N2Q3MGU2ZGQzYWU2ODY2NDJjZjM5MmVlZDk3MGEwYjZl
|
14
|
+
Zjc1NDI4YTQ5YTEzOWY1YmQzNmM0NTdhOTZmNGZjOTUyOWE0M2YzNDFhODU5
|
15
|
+
MTFhNDM3ZGQ5YjRjZmJiMmNjZDE1MzM2YmQ0M2JlNzdiZjZjMzg=
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -6,12 +6,20 @@ RackWarden uses Sinatra for the mini-app, Warden for authentication, and DataMap
|
|
6
6
|
|
7
7
|
My goal in developing this software is to have drop-in authentication containing most of the features you see in user/account management sections of a typical web site. But I don't want to be strapped by this module in any of my projects, so it must be customizable. Or rather, overridable. The basics of this flexibility are already in place, and it will be a central theme throughout. See below for examples on overriding and customizing RackWarden.
|
8
8
|
|
9
|
+
## What Does it Do?
|
10
|
+
|
11
|
+
RackWarden acts as a self-sufficient gatekeeper for your ruby web app. Once you enable RackWarden in your rack-based project, all routes/actions in your project will require a login and will redirect browsers to an authentication page. RackWarden provides its own view & layout templates to facilitate user authentication. RackWarden also provides it's own tables to store user data.
|
12
|
+
|
13
|
+
Once RackWarden authenticates a user, it gets out of the way, and the user is returned to your application. RackWarden also provides a number of user management tools for common actions like creating, updating, and deleting users.
|
14
|
+
|
15
|
+
Most of the RackWarden features can be customized. You can override the views, the database, the actions, and even the authentication logic with your own. The easiest (and possibly the most dramatic) customization is to provide RackWarden with your own layout template, giving RackWarden the look-and-feel of your own application.
|
16
|
+
|
9
17
|
|
10
18
|
## Installation
|
11
19
|
|
12
20
|
In your Gemfile:
|
13
21
|
|
14
|
-
|
22
|
+
gem 'rack_warden'
|
15
23
|
|
16
24
|
Then:
|
17
25
|
|
@@ -28,88 +36,127 @@ A few simple steps will have your entire app protected.
|
|
28
36
|
|
29
37
|
### Sinatra
|
30
38
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
get "/" do
|
39
|
-
erb "All routes are now protected"
|
40
|
-
end
|
41
|
-
end
|
39
|
+
class MySinatraApp < Sinatra::Base
|
40
|
+
use RackWarden::App
|
41
|
+
|
42
|
+
get "/" do
|
43
|
+
erb "All routes are now protected"
|
44
|
+
end
|
45
|
+
end
|
42
46
|
|
43
47
|
### Rails
|
44
48
|
|
45
49
|
application.rb or environment.rb
|
46
50
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
before_filter :require_login
|
52
|
-
|
51
|
+
config.middleware.use RackWarden::App
|
52
|
+
|
53
|
+
# All routes are now protected
|
54
|
+
|
53
55
|
|
54
56
|
|
55
57
|
## Configuration
|
56
58
|
|
57
|
-
Pass configuration settings to RackWarden through
|
59
|
+
Pass configuration settings to RackWarden through the ``use`` method of your framework. The params hash of ``use`` will be translated directly to RackWarden's settings. In addition to RackWarden's specific configuration options, you can also pass in any settings that Sinatra recognizes.
|
58
60
|
|
59
|
-
If you pass a block with the ``use`` method, the block will be evaluated in the context of the RackWarden::App class. Anything you do in that block is just as if you were writing code in the app class itself. While in the block, you also have access to
|
61
|
+
If you pass a block with the ``use`` method, the block will be evaluated in the context of the RackWarden::App class. Anything you do in that block is just as if you were writing code in the app class itself. While in the block, you also have access to the current instance of RackWarden::App and the current instance of the parent app.
|
60
62
|
|
61
|
-
|
62
|
-
|
63
|
-
|
63
|
+
use RackWarden::App do |rack_warden_app_instance, parent_app_instance|
|
64
|
+
set :somesetting, 'some_value'
|
65
|
+
end
|
64
66
|
|
65
67
|
### Configuration Options
|
66
68
|
|
67
|
-
Current list of settings specific to
|
69
|
+
Current list of settings specific to rack\_warden, with defaults.
|
68
70
|
|
69
71
|
#### :layout
|
70
72
|
|
71
73
|
A symbol representing a layout file in any of the view paths.
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
#### :
|
74
|
+
|
75
|
+
layout: :'rack_warden_layout.html'
|
76
|
+
|
77
|
+
#### :default\_route
|
76
78
|
|
77
79
|
A Sinatra route to fall back on after logout, errors, or any action that has no specified route.
|
78
80
|
|
79
|
-
|
80
|
-
|
81
|
-
#### :database
|
82
|
-
|
83
|
-
A
|
84
|
-
|
85
|
-
|
86
|
-
|
81
|
+
default_route: '/'
|
82
|
+
|
83
|
+
#### :database\_config
|
84
|
+
|
85
|
+
A database specification hash or or url string.
|
86
|
+
|
87
|
+
database_config: "sqlite:///Absolute/path/to/your/rack_warden.sqlite3.db"
|
88
|
+
|
89
|
+
# or
|
90
|
+
|
91
|
+
database_config:
|
92
|
+
adapter: mysql2
|
93
|
+
encoding: utf8
|
94
|
+
database: my_db_name
|
95
|
+
username: root
|
96
|
+
password: my_password
|
97
|
+
host: 127.0.0.1
|
98
|
+
port: 3306
|
99
|
+
|
100
|
+
#### :require\_login
|
101
|
+
|
102
|
+
Parameters to pass to the before/before\_filter for require\_login.
|
103
|
+
So if you're main app is Sinatra,
|
104
|
+
|
105
|
+
require_login: /^\/.+/
|
106
|
+
|
107
|
+
is the same as
|
108
|
+
|
109
|
+
class MySinatraApp
|
110
|
+
require_login /^\/.+/
|
111
|
+
end
|
112
|
+
|
113
|
+
which is the same as
|
114
|
+
|
115
|
+
class MySinatraApp
|
116
|
+
before /^\/.+/ do
|
117
|
+
require_login
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
For Rails, you would be passing a hash of :only or :except keys.
|
122
|
+
|
123
|
+
require_login:
|
124
|
+
except: :index
|
125
|
+
|
126
|
+
The default for :require\_login is nil, which means require login on every route or action.
|
127
|
+
To disable automatic activation of require\_login, pass it ``false``.
|
128
|
+
|
129
|
+
#### :allow\_public\_signup
|
130
|
+
|
131
|
+
Allows public access to the account creation view & action.
|
132
|
+
|
133
|
+
allow_public_signup: false
|
134
|
+
|
135
|
+
|
87
136
|
#### :recaptcha
|
88
137
|
|
89
138
|
Settings for Google's recaptcha service
|
90
139
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
140
|
+
:recaptcha => {
|
141
|
+
:sitekey => '',
|
142
|
+
:secret => ''
|
143
|
+
}
|
95
144
|
|
96
145
|
## Customization
|
97
146
|
|
98
147
|
To customize RackWarden for your specific project, you can set :views to point to a directory within your project. Then create templates that match the names of RackWarden templates, and they will be picked up and rendered. RackWarden looks for templates at the top level of your views directory as a default. You can change or add to this when you define the middleware in your project.
|
99
148
|
|
100
|
-
|
101
|
-
|
149
|
+
use RackWarden::App, :views => File.join(Dir.pwd, 'app/views/rack_warden')
|
150
|
+
|
102
151
|
Or if you simply want RackWarden to use your own custom layout, pass it a file path in the :layout parameter.
|
103
152
|
|
104
|
-
|
105
|
-
|
106
|
-
Just remember that RackWarden is Sinatra, and any templates you pass must use Sinatra-specific code. For example, Sinatra uses ``url`` instead of Rails' ``url_for``. Also remember that template names in Sinatra must always be symbols.
|
107
|
-
|
108
|
-
Another way to customize RackWarden is to override its classes and methods, as you would with any other ruby code.
|
153
|
+
use RackWarden::App, :layout => :'layouts/rack_warden_layout.html'
|
154
|
+
|
155
|
+
Just remember that RackWarden is Sinatra, and any templates you pass must use Sinatra-specific code. For example, Sinatra uses ``url`` instead of Rails' ``url_for``. Also remember that template names in Sinatra must always be symbols. Have a look at the readme on Sinatra's web site for more details on Sinatra's DSL.
|
109
156
|
|
110
|
-
And if you want to customize RackWarden more extensively, you can always download the source from github and directly modify the app file and templates. Then point to this modified gem in your project Gemfile.
|
157
|
+
Another way to customize RackWarden is to override its classes and methods, as you would with any other ruby code. And if you want to customize RackWarden more extensively, you can always download the source from github and directly modify the app file and templates. Then point to this modified gem in your project Gemfile.
|
111
158
|
|
112
|
-
|
159
|
+
gem 'rack_warden', :path => "../RackWarden/"
|
113
160
|
|
114
161
|
|
115
162
|
|
data/lib/rack_warden/app.rb
CHANGED
@@ -8,8 +8,10 @@ module RackWarden
|
|
8
8
|
set :config_files, [ENV['RACK_WARDEN_CONFIG_FILE'], 'rack_warden.yml', 'config/rack_warden.yml'].compact.uniq
|
9
9
|
set :layout, :'rack_warden_layout.html'
|
10
10
|
set :default_route, '/'
|
11
|
-
set :
|
11
|
+
set :database_config, "sqlite3:///#{Dir.pwd}/rack_warden.sqlite3.db"
|
12
12
|
set :recaptcha, Hash.new
|
13
|
+
set :require_login, nil
|
14
|
+
set :allow_public_signup, false
|
13
15
|
|
14
16
|
# Load config from file, if any exist.
|
15
17
|
Hash.new.tap do |hash|
|
@@ -29,7 +31,7 @@ module RackWarden
|
|
29
31
|
# end
|
30
32
|
#
|
31
33
|
def initialize(parent_app=nil, *args, &block)
|
32
|
-
|
34
|
+
puts "INITIALIZE RackWarden::App INSTANCE [parent_app, self, args, block]: #{[parent_app, self, args, block]}"
|
33
35
|
# extract options.
|
34
36
|
opts = args.last.is_a?(Hash) ? args.pop : {}
|
35
37
|
klass = self.class
|
@@ -58,9 +60,29 @@ module RackWarden
|
|
58
60
|
when parent_app.class.ancestors.find{|x| x.to_s=='Sinatra::Base'}
|
59
61
|
parent_app.class.helpers(RackWardenHelpers)
|
60
62
|
default_parent_views = File.join(Dir.pwd,"views")
|
63
|
+
|
64
|
+
parent_app.class.instance_eval do
|
65
|
+
def self.require_login(*args)
|
66
|
+
#options = args.last.is_a?(Hash) ? args.pop : Hash.new
|
67
|
+
before(*args) do
|
68
|
+
require_login
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
parent_app.class.require_login(klass.require_login) if klass.require_login != false
|
61
73
|
when parent_app.class.parents.find{|x| x.to_s=='ActionDispatch'}
|
62
74
|
ApplicationController.send(:include, RackWardenHelpers)
|
63
75
|
default_parent_views = File.join(Dir.pwd, "app/views")
|
76
|
+
|
77
|
+
parent_app.class.instance_eval do
|
78
|
+
def self.require_login(*args)
|
79
|
+
#options = args.last.is_a?(Hash) ? args.pop : Hash.new
|
80
|
+
before_filter(:require_login, *args) do
|
81
|
+
require_login
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
(ApplicationController.before_filter :require_login, *Array(klass.require_login).flatten) if klass.require_login != false
|
64
86
|
end
|
65
87
|
|
66
88
|
new_views = []
|
@@ -149,7 +171,7 @@ module RackWarden
|
|
149
171
|
# TODO: Shouldn't these be in warden block above? But they don't work there for some reason.
|
150
172
|
|
151
173
|
def valid_user_input?
|
152
|
-
params['user'] && params['user']['
|
174
|
+
params['user'] && params['user']['email'] && params['user']['password']
|
153
175
|
end
|
154
176
|
|
155
177
|
def create_user
|
@@ -157,9 +179,10 @@ module RackWarden
|
|
157
179
|
verify_recaptcha if settings.recaptcha[:secret]
|
158
180
|
|
159
181
|
return unless valid_user_input?
|
160
|
-
|
161
|
-
|
162
|
-
user.
|
182
|
+
#user = User.create(username: params['user']['username'])
|
183
|
+
@user = User.new(params['user'])
|
184
|
+
#user.password = params['user']['password']
|
185
|
+
@user.save && warden.set_user(@user)
|
163
186
|
end
|
164
187
|
|
165
188
|
def verify_recaptcha(skip_redirect=false, ip=request.ip, response=params['g-recaptcha-response'])
|
@@ -214,8 +237,9 @@ module RackWarden
|
|
214
237
|
redirect url(settings.default_route, false)
|
215
238
|
end
|
216
239
|
|
217
|
-
get '/auth/
|
218
|
-
|
240
|
+
get '/auth/new' do
|
241
|
+
halt 403 unless settings.allow_public_signup or !(User.count > 0)
|
242
|
+
erb :'create_user.html', :layout=>settings.layout, :locals=>{:recaptcha_sitekey=>settings.recaptcha['sitekey']}
|
219
243
|
end
|
220
244
|
|
221
245
|
post '/auth/create' do
|
@@ -224,7 +248,7 @@ module RackWarden
|
|
224
248
|
redirect session[:return_to] || url(settings.default_route, false)
|
225
249
|
else
|
226
250
|
flash(:rwarden)[:error] = warden.message || "Could not create account"
|
227
|
-
redirect url('/auth/
|
251
|
+
redirect back #url('/auth/new', false)
|
228
252
|
end
|
229
253
|
end
|
230
254
|
|
@@ -233,8 +257,13 @@ module RackWarden
|
|
233
257
|
session[:return_to] = env['warden.options'][:attempted_path] if !request.xhr? && !env['warden.options'][:attempted_path][/login/]
|
234
258
|
puts "WARDEN ATTEMPTED PATH: #{env['warden.options'][:attempted_path]}"
|
235
259
|
puts warden
|
236
|
-
|
237
|
-
|
260
|
+
if User.count > 0
|
261
|
+
flash(:rwarden)[:error] = warden.message || "Please login to continue"
|
262
|
+
redirect url('/auth/login', false)
|
263
|
+
else
|
264
|
+
flash(:rwarden)[:error] = warden.message || "Please create an admin account"
|
265
|
+
redirect url('/auth/new', false)
|
266
|
+
end
|
238
267
|
end
|
239
268
|
|
240
269
|
get '/auth/protected' do
|
@@ -242,6 +271,11 @@ module RackWarden
|
|
242
271
|
|
243
272
|
erb :'rack_warden_protected.html', :layout=>settings.layout
|
244
273
|
end
|
274
|
+
|
275
|
+
get '/auth/admin' do
|
276
|
+
warden.authenticate!
|
277
|
+
erb :'rw_admin.html', :layout=>settings.layout
|
278
|
+
end
|
245
279
|
|
246
280
|
end # App
|
247
281
|
end # RackWarden
|
data/lib/rack_warden/model.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
#require 'bcrypt'
|
2
|
-
DataMapper.
|
2
|
+
DataMapper::Logger.new(File.join(Dir.pwd, 'log', 'rack_warden.log'))
|
3
|
+
DataMapper.setup(:default, RackWarden::App.database_config)
|
4
|
+
|
5
|
+
# Do DataMapper.repository.adapter to get connection info for this connection.
|
3
6
|
|
4
7
|
class User
|
5
8
|
include DataMapper::Resource
|
6
9
|
include BCrypt
|
7
10
|
|
8
11
|
property :id, Serial, key: true
|
9
|
-
property :username, String, length: 128
|
12
|
+
property :username, String, length: 128, required: true, unique: true, default: lambda {|r,v| r.instance_variable_get :@email}
|
13
|
+
property :email, String, length: 128, required: true, unique: true, default: 'error'
|
10
14
|
|
11
15
|
property :password, BCryptHash
|
12
16
|
|
data/lib/rack_warden/version.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
<% @section_title = "Create Account" %>
|
2
2
|
<form action="<%=url('/auth/create', false)%>" method="post">
|
3
|
+
<p>Email: <input type="text" name="user[email]" /></p>
|
3
4
|
<p>Username: <input type="text" name="user[username]" /></p>
|
4
5
|
<p>Password: <input type="password" name="user[password]" /></p>
|
5
|
-
<% if recaptcha_sitekey %>
|
6
|
+
<% if recaptcha_sitekey && User.count > 0 %>
|
6
7
|
<div class="g-recaptcha control text-control" data-sitekey="<%=recaptcha_sitekey%>"></div>
|
7
8
|
<% end %>
|
8
9
|
<input type="submit" value="Create" />
|
10
|
+
<p><%= @user.errors.to_yaml if @user && @user.errors %></p>
|
9
11
|
</form>
|
@@ -2,5 +2,8 @@
|
|
2
2
|
<form action="<%=url('/auth/login', false)%>" method="post">
|
3
3
|
<p>Username: <input type="text" name="user[username]" /></p>
|
4
4
|
<p>Password: <input type="password" name="user[password]" /></p>
|
5
|
-
<input type="submit" value="Log In" />
|
5
|
+
<input type="submit" value="Log In" />
|
6
|
+
<% if settings.allow_public_signup %>
|
7
|
+
or <a href="<%=url('/auth/new', false)%>">Create a new account</a>
|
8
|
+
<% end %>
|
6
9
|
</form>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<% @section_title = "RackWarden Admin" %>
|
2
|
+
<table>
|
3
|
+
<thead>
|
4
|
+
<tr>
|
5
|
+
<th>Email</th>
|
6
|
+
<th>User</th>
|
7
|
+
<th>Id</th>
|
8
|
+
</tr>
|
9
|
+
<tbody>
|
10
|
+
<% User.all(:limit=>100).each do |user| %>
|
11
|
+
<tr>
|
12
|
+
<td><%=user.email%></td>
|
13
|
+
<td><%=user.username%></td>
|
14
|
+
<td><%=user.id%></td>
|
15
|
+
</tr>
|
16
|
+
<% end %>
|
17
|
+
</tbody>
|
18
|
+
</table>
|
data/lib/rack_warden.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack_warden
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- William Richardson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -173,6 +173,7 @@ files:
|
|
173
173
|
- lib/rack_warden/views/rack_warden_index.html.erb
|
174
174
|
- lib/rack_warden/views/rack_warden_layout.html.erb
|
175
175
|
- lib/rack_warden/views/rack_warden_protected.html.erb
|
176
|
+
- lib/rack_warden/views/rw_admin.html.erb
|
176
177
|
- rack_warden.gemspec
|
177
178
|
homepage: ''
|
178
179
|
licenses:
|