rack_warden 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +35 -23
- data/lib/rack_warden.rb +9 -2
- data/lib/rack_warden/app.rb +26 -225
- data/lib/rack_warden/frameworks.rb +0 -6
- data/lib/rack_warden/frameworks/rails.rb +7 -11
- data/lib/rack_warden/frameworks/sinatra.rb +6 -10
- data/lib/rack_warden/helpers.rb +96 -0
- data/lib/rack_warden/models/user.rb +11 -0
- data/lib/rack_warden/routes.rb +101 -0
- data/lib/rack_warden/version.rb +1 -1
- data/lib/rack_warden/views/rw_admin.html.erb +3 -1
- data/lib/rack_warden/views/rw_dbinfo.html.erb +1 -1
- data/lib/rack_warden/views/rw_index.html.erb +1 -1
- data/lib/rack_warden/views/rw_layout.html.erb +1 -2
- data/lib/rack_warden/views/rw_layout_admin.html.erb +16 -0
- data/lib/rack_warden/warden.rb +60 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OGI4OGQxNWNhZTkwNWNlODQ3ZTkwNWFmZTZiODFkM2MwNTMzNWZkZg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YWFiYWY3NmRjNzZmNjJhMzIzM2Y2YjFmY2I5OGVjMmI5OGFmMDQ4Mg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NWVlZDdkMzczOTIwMjYzY2I4NjZiZmExNzlmYWQyZmU5OGJjYTg1YWUyZDA3
|
10
|
+
YzcwNDYzOGZiMzBlNDg2NjQ2ZmI1YTBkNjU3MTc0YTFiM2Y3NTgzZTQyNzNk
|
11
|
+
MjUyMGI2NzVlMTkwOWQ0ODdiZWRhYzVkMTI5ZDFjMWNhMzhjZGE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YzQ3ZTIzMjMyNWQ4YTRmMmQxMTRiNjMwNDliOTkwN2IyZTVjOGY3MjQ3MGIz
|
14
|
+
ODg0ZTBhMTk3ZmE4MzE3YTNiNzhjN2ExMGJmYTZhNGViZDJhYjNlOGNiZTky
|
15
|
+
MjhhMzE4MWFkMzAyZDUyZGMwZmYwYjQ0ZDQ5Mjk2NmE1ZDA4MWI=
|
data/README.md
CHANGED
@@ -4,17 +4,17 @@ RackWarden is a rack middleware mini-app that provides user authentication and m
|
|
4
4
|
|
5
5
|
RackWarden uses Sinatra for the mini-app, Warden for authentication, and DataMapper for database connections. It is based on the sinatra-warden-example at https://github.com/sklise/sinatra-warden-example. If you are new to Warden or Sinatra, I highly recommend downloading and experimenting with that example.
|
6
6
|
|
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.
|
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.
|
8
8
|
|
9
9
|
Please note that RackWarden is a work-in-progress. The gemspec, the files, the code, and the documentation can and will change over time. Follow on github for the latest fixes, changes, and developments.
|
10
10
|
|
11
11
|
## What Does it Do?
|
12
12
|
|
13
|
-
RackWarden
|
13
|
+
RackWarden is a modular 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 database & table structure to store user data. Views, layouts, databases, and tables are easily customized and/or overridden, however.
|
14
14
|
|
15
15
|
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.
|
16
16
|
|
17
|
-
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 templates and code. The easiest (and possibly the most dramatic) customization is to provide RackWarden with your own layout template, giving RackWarden the
|
17
|
+
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 templates and code. The easiest (and possibly the most dramatic) customization is to provide RackWarden with your own layout template, giving RackWarden the appearane of the application you're integrating it with.
|
18
18
|
|
19
19
|
|
20
20
|
## Installation
|
@@ -39,7 +39,7 @@ A few simple steps will have your entire app protected.
|
|
39
39
|
### Sinatra
|
40
40
|
|
41
41
|
class MySinatraApp < Sinatra::Base
|
42
|
-
use RackWarden
|
42
|
+
use RackWarden
|
43
43
|
|
44
44
|
get "/" do
|
45
45
|
erb "All routes are now protected"
|
@@ -50,7 +50,7 @@ A few simple steps will have your entire app protected.
|
|
50
50
|
|
51
51
|
application.rb or environment.rb
|
52
52
|
|
53
|
-
config.middleware.use RackWarden
|
53
|
+
config.middleware.use RackWarden
|
54
54
|
|
55
55
|
# All routes are now protected
|
56
56
|
|
@@ -60,19 +60,19 @@ application.rb or environment.rb
|
|
60
60
|
|
61
61
|
RackWarden will look for a configuration file named rack\_warden.yml in your project root or in your project/config/ directory.
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
---
|
64
|
+
database: sqlite3:///usr/local/some_other_database.sqlite3.db
|
65
|
+
layout: :'my_custom_layout.html.erb'
|
66
66
|
|
67
67
|
|
68
68
|
You an also 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 standard Sinatra settings.
|
69
69
|
|
70
|
-
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
|
70
|
+
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.
|
71
71
|
|
72
|
-
use RackWarden::App do |rack_warden_app_instance
|
72
|
+
use RackWarden::App do |rack_warden_app_instance|
|
73
73
|
set :somesetting, 'some_value'
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
|
77
77
|
## Configuration Options
|
78
78
|
|
@@ -154,15 +154,22 @@ Settings for Google's recaptcha service
|
|
154
154
|
|
155
155
|
### :log\_path
|
156
156
|
|
157
|
-
|
157
|
+
File.join(Dir.pwd, 'log', 'rack_warden.log')
|
158
|
+
|
159
|
+
### :user\_table\_name
|
160
|
+
|
161
|
+
nil
|
162
|
+
|
163
|
+
### :views
|
164
|
+
|
165
|
+
File.expand_path("../views/", __FILE__)
|
166
|
+
|
158
167
|
|
159
168
|
## Customization
|
160
169
|
|
161
170
|
### Views
|
162
171
|
|
163
|
-
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
|
164
|
-
|
165
|
-
Update: also looks in views/rack\_warden/ for view templates.
|
172
|
+
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 and in views/rack\_warden (if it exists) as a default. You can change or add to this with the ```:views``` setting.
|
166
173
|
|
167
174
|
use RackWarden::App, :views => File.join(Dir.pwd, 'app/views/another_directory')
|
168
175
|
|
@@ -175,15 +182,20 @@ Just remember that RackWarden is Sinatra, and any templates you pass must use Si
|
|
175
182
|
|
176
183
|
### Database
|
177
184
|
|
178
|
-
As a default, RackWarden will use the database specified in your project.
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
+
As a default, RackWarden will use a sqlite3 in-memory database (that starts fresh each time you boot your app). To use the database specified in your project, just pass ```:auto``` to the ```:database_config``` setting. Pass ```:file``` to set up a sqlite3 database in your app's working directory. Or pass your own custom database specification (a url or hash). If you use a database other than sqlite3, you will need to include the respective DataMapper extension gems in your Gemfile or in your manually installed gem list. For MySQL, use dm-mysql-adapter, for Postgres use dm-postgres-adapter. See the DataMapper site for more info on database adapters.
|
186
|
+
|
187
|
+
# Database specification as a url
|
188
|
+
database_config: 'sqlite3:///path/to/my/database.sqlite3.db'
|
189
|
+
|
190
|
+
# Database specification as a hash
|
191
|
+
database_config: {adapter: 'sqlite3', database: '/path/to/my/database.sqlite3.db'}
|
192
|
+
|
193
|
+
# Use a remote MySQL database
|
194
|
+
database_config: {adapter: 'mysql', username: 'will', password: 'mypass',
|
195
|
+
host: 'somehost', database: 'my_database'}
|
185
196
|
|
186
|
-
|
197
|
+
# Format for database urls
|
198
|
+
#<adapter>://<username>:<password>@<host>:<port>/<database_name>
|
187
199
|
|
188
200
|
|
189
201
|
|
data/lib/rack_warden.rb
CHANGED
@@ -17,7 +17,10 @@ module RackWarden
|
|
17
17
|
autoload :App, 'rack_warden/app'
|
18
18
|
autoload :User, "rack_warden/models"
|
19
19
|
autoload :Pref, "rack_warden/models"
|
20
|
+
autoload :Routes, "rack_warden/routes"
|
20
21
|
autoload :VERSION, "rack_warden/version"
|
22
|
+
autoload :WardenConfig, "rack_warden/warden"
|
23
|
+
autoload :RackWardenHelpers, "rack_warden/helpers"
|
21
24
|
module Frameworks
|
22
25
|
autoload :Base, 'rack_warden/frameworks'
|
23
26
|
autoload :Sinatra, 'rack_warden/frameworks/sinatra'
|
@@ -33,18 +36,22 @@ module RackWarden
|
|
33
36
|
# Utility to get middleware stack. Maybe temporary.
|
34
37
|
def self.middleware_classes(app=nil)
|
35
38
|
r = [app || Rack::Builder.parse_file(File.join(Dir.pwd, 'config.ru')).first]
|
36
|
-
|
37
39
|
while ((next_app = r.last.instance_variable_get(:@app)) != nil)
|
38
40
|
r << next_app
|
39
41
|
end
|
40
|
-
|
41
42
|
r.map{|e| e.instance_variable_defined?(:@app) ? e.class : e }
|
42
43
|
end
|
43
44
|
#app = Rack::Builder.parse_file('config.ru').first
|
44
45
|
#puts middleware_classes(app).inspect
|
45
46
|
|
47
|
+
# Shortcut/sugar to app
|
46
48
|
def self.settings
|
47
49
|
App.settings
|
48
50
|
end
|
51
|
+
|
52
|
+
def self.included(base)
|
53
|
+
puts "RW self.included into BASE #{base}, ID #{base.object_id}"
|
54
|
+
App.new base
|
55
|
+
end
|
49
56
|
|
50
57
|
end
|
data/lib/rack_warden/app.rb
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
|
4
4
|
module RackWarden
|
5
5
|
class App < Sinatra::Base
|
6
|
-
enable :sessions
|
7
|
-
register Sinatra::Flash
|
8
6
|
|
9
7
|
set :config_files, [ENV['RACK_WARDEN_CONFIG_FILE'], 'rack_warden.yml', 'config/rack_warden.yml'].compact.uniq
|
10
8
|
set :layout, :'rw_layout.html'
|
@@ -21,10 +19,15 @@ module RackWarden
|
|
21
19
|
|
22
20
|
# Load config from file, if any exist.
|
23
21
|
Hash.new.tap do |hash|
|
24
|
-
config_files.each {|c|
|
22
|
+
config_files.each {|c| hash.merge!(YAML.load_file(File.join(Dir.pwd, c))) rescue nil}
|
25
23
|
set hash
|
26
24
|
end
|
27
25
|
|
26
|
+
|
27
|
+
|
28
|
+
enable :sessions
|
29
|
+
register Sinatra::Flash
|
30
|
+
|
28
31
|
begin
|
29
32
|
enable :logging
|
30
33
|
set :log_file, File.new(settings.log_path, 'a+')
|
@@ -32,27 +35,31 @@ module RackWarden
|
|
32
35
|
use Rack::CommonLogger, settings.log_file
|
33
36
|
rescue
|
34
37
|
end
|
38
|
+
|
39
|
+
include RackWarden::WardenConfig
|
40
|
+
include RackWarden::Routes
|
41
|
+
|
42
|
+
helpers RackWardenHelpers
|
43
|
+
helpers UniversalHelpers
|
44
|
+
|
35
45
|
|
36
46
|
|
37
47
|
# WBR - This will receive params and a block from the parent "use" statement.
|
38
48
|
# This middleware app has been modified to process the parent use-block in
|
39
49
|
# the context of the RackWarden class. So you can set settings on RackWarden,
|
40
|
-
# when you call "use RackWarden
|
50
|
+
# when you call "use RackWarden"
|
41
51
|
# Example:
|
42
52
|
#
|
43
|
-
# use RackWarden
|
53
|
+
# use RackWarden :layout=>:'my_layout' do |rack_warden_instance, app|
|
44
54
|
# set :myvar, 'something'
|
45
55
|
# end
|
46
56
|
#
|
47
57
|
def initialize(parent_app_instance=nil, *args, &block)
|
48
|
-
|
49
|
-
super(parent_app_instance, &Proc.new{})
|
58
|
+
super(parent_app_instance, &Proc.new{}) # Must send empty proc, not original proc, since we're calling original block here.
|
50
59
|
initialization_args = args.dup
|
51
|
-
#puts "RW INITIALIZE middleware instance [app, self, args, block]: #{[app, self, args, block]}"
|
52
60
|
puts "RW new instance with parent: #{@app}"
|
53
61
|
# extract options.
|
54
62
|
opts = args.last.is_a?(Hash) ? args.pop : {}
|
55
|
-
#settings = self.class
|
56
63
|
if app && !settings.initialized
|
57
64
|
puts "RW initializing settings"
|
58
65
|
|
@@ -64,7 +71,7 @@ module RackWarden
|
|
64
71
|
settings.set opts if opts.any?
|
65
72
|
|
66
73
|
# Eval the use-block from the parent app, in context of this app.
|
67
|
-
settings.instance_exec(self,
|
74
|
+
settings.instance_exec(self, &block) if block_given?
|
68
75
|
|
69
76
|
# Do framework setup.
|
70
77
|
framework_module = Frameworks::Base.select_framework(binding)
|
@@ -74,13 +81,6 @@ module RackWarden
|
|
74
81
|
|
75
82
|
# Manipulate views
|
76
83
|
new_views = []
|
77
|
-
#original_views = self.class.original_views
|
78
|
-
# append parent rails views folder unless opts.has_key?(:views)
|
79
|
-
#new_views << framework_module.views_path unless opts[:views]==false #opts.has_key?(:views)
|
80
|
-
# append original_views, if original_views
|
81
|
-
#new_views << original_views if original_views
|
82
|
-
#self.class.set(:views => [new_views, Array(self.class.views)].flatten.compact.uniq) if new_views.any?
|
83
|
-
|
84
84
|
new_views.unshift settings.original_views
|
85
85
|
new_views.unshift framework_module.views_path unless settings.views==false
|
86
86
|
new_views.unshift settings.views
|
@@ -90,216 +90,17 @@ module RackWarden
|
|
90
90
|
end
|
91
91
|
settings.set :initialized, true
|
92
92
|
end
|
93
|
-
# finally, send parent app to super, but don't send the use-block (thus the empty proc)
|
94
|
-
#super(app, &Proc.new{})
|
95
|
-
end
|
96
|
-
|
97
|
-
# For testing interception of request.
|
98
|
-
# This might be breaking older rails installations
|
99
|
-
# if development?
|
100
|
-
# def call(env={})
|
101
|
-
# puts "RW instance.app #{app}"
|
102
|
-
# puts "RW instance.call(env) #{env.to_yaml}"
|
103
|
-
# super(env)
|
104
|
-
# end
|
105
|
-
# end
|
106
|
-
|
107
|
-
use Warden::Manager do |config|
|
108
|
-
# Tell Warden how to save our User info into a session.
|
109
|
-
# Sessions can only take strings, not Ruby code, we'll store
|
110
|
-
# the User's `id`
|
111
|
-
config.serialize_into_session{|user| user.id }
|
112
|
-
# Now tell Warden how to take what we've stored in the session
|
113
|
-
# and get a User from that information.
|
114
|
-
config.serialize_from_session{|id| User.get(id) }
|
115
|
-
|
116
|
-
config.scope_defaults :default,
|
117
|
-
# "strategies" is an array of named methods with which to
|
118
|
-
# attempt authentication. We have to define this later.
|
119
|
-
:strategies => [:password],
|
120
|
-
# The action is a route to send the user to when
|
121
|
-
# warden.authenticate! returns a false answer. We'll show
|
122
|
-
# this route below.
|
123
|
-
:action => 'auth/unauthenticated'
|
124
|
-
# When a user tries to log in and cannot, this specifies the
|
125
|
-
# app to send the user to.
|
126
|
-
config.failure_app = self
|
127
|
-
end
|
128
93
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
def authenticate!
|
139
|
-
user = User.first(['username = ? or email = ?', params['user']['username'], params['user']['username']]) #(username: params['user']['username'])
|
140
|
-
|
141
|
-
if user.nil?
|
142
|
-
fail!("The username you entered does not exist.")
|
143
|
-
elsif user.authenticate(params['user']['password'])
|
144
|
-
success!(user)
|
145
|
-
else
|
146
|
-
fail!("Could not log in")
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
end
|
151
|
-
|
152
|
-
# Also bring these into your main app helpers.
|
153
|
-
module RackWardenHelpers
|
154
|
-
# WBR - override. This passes block to be rendered to first template that matches.
|
155
|
-
def find_template(views, name, engine, &block)
|
156
|
-
# puts "THE VIEWS: #{views}"
|
157
|
-
# puts "THE NAME: #{name}"
|
158
|
-
# puts "THE ENGINE: #{engine}"
|
159
|
-
# puts "THE BLOCK: #{block}"
|
160
|
-
Array(views).each { |v| super(v, name, engine, &block) }
|
161
|
-
end
|
162
|
-
|
163
|
-
def require_login
|
164
|
-
warden.authenticate!
|
165
|
-
end
|
166
|
-
|
167
|
-
def warden
|
168
|
-
request.env['warden']
|
169
|
-
end
|
170
|
-
|
171
|
-
def current_user
|
172
|
-
warden.user
|
173
|
-
end
|
174
|
-
|
175
|
-
def logged_in?
|
176
|
-
warden.authenticated?
|
177
|
-
end
|
178
|
-
|
179
|
-
|
180
|
-
# TODO: Shouldn't these be in warden block above? But they don't work there for some reason.
|
181
|
-
|
182
|
-
def valid_user_input?
|
183
|
-
params['user'] && params['user']['email'] && params['user']['password']
|
184
|
-
end
|
185
|
-
|
186
|
-
# def create_user
|
187
|
-
#
|
188
|
-
# verify_recaptcha if settings.recaptcha[:secret]
|
189
|
-
#
|
190
|
-
# #return unless valid_user_input?
|
191
|
-
#
|
192
|
-
# @user = User.new(params['user'])
|
193
|
-
# @user.save #&& warden.set_user(@user)
|
194
|
-
# end
|
195
|
-
|
196
|
-
def verify_recaptcha(skip_redirect=false, ip=request.ip, response=params['g-recaptcha-response'])
|
197
|
-
secret = settings.recaptcha[:secret]
|
198
|
-
_recaptcha = ActiveSupport::JSON.decode(open("https://www.google.com/recaptcha/api/siteverify?secret=#{secret}&response=#{response}&remoteip=#{ip}").read)
|
199
|
-
puts "RECAPTCHA", _recaptcha
|
200
|
-
unless _recaptcha['success']
|
201
|
-
flash(:rwarden)[:error] = "Please confirm you are human"
|
202
|
-
redirect back unless skip_redirect
|
203
|
-
Halt "You appear to be a robot."
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
def default_page
|
208
|
-
erb :'rw_index.html', :layout=>settings.layout
|
209
|
-
end
|
210
|
-
|
211
|
-
end # RackWardenHelpers
|
212
|
-
helpers RackWardenHelpers
|
213
|
-
|
214
|
-
if defined? ::RACK_WARDEN_STANDALONE
|
215
|
-
get '/?' do
|
216
|
-
default_page
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
get '/auth/?' do
|
221
|
-
default_page
|
222
|
-
end
|
223
|
-
|
224
|
-
get '/auth/login' do
|
225
|
-
if User.count > 0
|
226
|
-
erb :'rw_login.html', :layout=>settings.layout
|
227
|
-
else
|
228
|
-
flash(:rwarden)[:error] = warden.message || "Please create an admin account"
|
229
|
-
redirect url('/auth/new', false)
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
post '/auth/login' do
|
234
|
-
warden.authenticate!
|
235
|
-
|
236
|
-
flash(:rwarden)[:success] = warden.message || "Successful login"
|
237
|
-
|
238
|
-
if session[:return_to].nil?
|
239
|
-
redirect url(settings.default_route, false)
|
240
|
-
else
|
241
|
-
redirect session[:return_to]
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
get '/auth/logout' do
|
246
|
-
warden.raw_session.inspect
|
247
|
-
warden.logout
|
248
|
-
flash(:rwarden)[:success] = 'You have been logged out'
|
249
|
-
redirect url(settings.default_route, false)
|
250
|
-
end
|
251
|
-
|
252
|
-
get '/auth/new' do
|
253
|
-
halt 403 unless settings.allow_public_signup or !(User.count > 0)
|
254
|
-
erb :'rw_new_user.html', :layout=>settings.layout, :locals=>{:recaptcha_sitekey=>settings.recaptcha['sitekey']}
|
255
|
-
end
|
256
|
-
|
257
|
-
post '/auth/create' do
|
258
|
-
verify_recaptcha if settings.recaptcha[:secret]
|
259
|
-
Halt "Could not create account", :layout=>settings.layout unless params[:user]
|
260
|
-
params[:user].delete_if {|k,v| v.nil? || v==''}
|
261
|
-
@user = User.new(params['user'])
|
262
|
-
if @user.save
|
263
|
-
warden.set_user(@user)
|
264
|
-
flash(:rwarden)[:success] = warden.message || "Account created"
|
265
|
-
redirect session[:return_to] || url(settings.default_route, false)
|
266
|
-
else
|
267
|
-
flash(:rwarden)[:error] = "#{warden.message} => #{@user.errors.entries.join('. ')}"
|
268
|
-
puts "RW /auth/create #{@user.errors.entries}"
|
269
|
-
redirect back #url('/auth/new', false)
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
post '/auth/unauthenticated' do
|
274
|
-
# I had to remove the condition, since it was not updating return path when it should have.
|
275
|
-
session[:return_to] = env['warden.options'][:attempted_path] if !request.xhr? && !env['warden.options'][:attempted_path][/login|new|create/]
|
276
|
-
puts "RW attempted path: #{env['warden.options'][:attempted_path]}"
|
277
|
-
puts "RW will return-to #{session[:return_to]}"
|
278
|
-
puts warden
|
279
|
-
# if User.count > 0
|
280
|
-
flash(:rwarden)[:error] = warden.message || "Please login to continue"
|
281
|
-
redirect url('/auth/login', false)
|
282
|
-
# else
|
283
|
-
# flash(:rwarden)[:error] = warden.message || "Please create an admin account"
|
284
|
-
# redirect url('/auth/new', false)
|
285
|
-
# end
|
286
|
-
end
|
287
|
-
|
288
|
-
get '/auth/protected' do
|
289
|
-
warden.authenticate!
|
94
|
+
end # initialize
|
95
|
+
|
96
|
+
# Store this app instance in the env.
|
97
|
+
def call(env)
|
98
|
+
#puts "RW instance.app #{app}"
|
99
|
+
#puts "RW instance.call(env) #{env.to_yaml}"
|
100
|
+
env['rack_warden_instance'] = self
|
101
|
+
super(env)
|
102
|
+
end
|
290
103
|
|
291
|
-
erb :'rw_protected.html', :layout=>settings.layout
|
292
|
-
end
|
293
|
-
|
294
|
-
get "/auth/dbinfo" do
|
295
|
-
warden.authenticate!
|
296
|
-
erb :'rw_dbinfo.html', :layout=>settings.layout
|
297
|
-
end
|
298
|
-
|
299
|
-
get '/auth/admin' do
|
300
|
-
warden.authenticate!
|
301
|
-
erb :'rw_admin.html', :layout=>settings.layout
|
302
|
-
end
|
303
104
|
|
304
105
|
end # App
|
305
106
|
end # RackWarden
|
@@ -39,12 +39,6 @@ module RackWarden
|
|
39
39
|
@rack_warden_app_class = @rack_warden_app_instance.class
|
40
40
|
selector && self
|
41
41
|
end
|
42
|
-
|
43
|
-
# # Best guess at framework database settings.
|
44
|
-
# def get_database_config
|
45
|
-
# ActiveRecord::Base.connection_config rescue nil ||
|
46
|
-
# DataMapper.repository(:default).adapter[:options] rescue nil
|
47
|
-
# end
|
48
42
|
|
49
43
|
### End methods extended into framework module ###
|
50
44
|
|
@@ -15,19 +15,15 @@ module RackWarden
|
|
15
15
|
|
16
16
|
def setup_framework
|
17
17
|
#puts "RW setup_framework for rails"
|
18
|
-
|
18
|
+
ActionController::Base.send(:include, RackWarden::UniversalHelpers)
|
19
19
|
|
20
20
|
# Define class method 'require_login' on framework controller.
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
(ApplicationController.before_filter :require_login, *Array(rack_warden_app_class.require_login).flatten) if rack_warden_app_class.require_login != false
|
21
|
+
ActionController::Base.define_singleton_method :require_login do |conditions_hash={}|
|
22
|
+
before_filter(:require_login, conditions_hash)
|
23
|
+
end
|
24
|
+
|
25
|
+
# The way you pass arguments here is fragile. If it's not correct, it will bomb with "undefined method 'before'...".
|
26
|
+
(ActionController::Base.require_login (rack_warden_app_class.require_login || {})) if rack_warden_app_class.require_login != false
|
31
27
|
end
|
32
28
|
|
33
29
|
end
|
@@ -15,18 +15,14 @@ module RackWarden
|
|
15
15
|
|
16
16
|
def setup_framework
|
17
17
|
#puts "RW setup_framework for sinatra"
|
18
|
-
parent_app.helpers(RackWarden::
|
18
|
+
parent_app.helpers(RackWarden::UniversalHelpers)
|
19
19
|
|
20
20
|
# Define class method 'require_login' on framework controller.
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
require_login
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
21
|
+
parent_app.define_singleton_method :require_login do |accept_conditions=/.*/, reject_conditions=false|
|
22
|
+
before(accept_conditions){require_login unless reject_conditions}
|
23
|
+
end
|
24
|
+
|
25
|
+
# Add require_login to before filter of sinatra app.
|
30
26
|
parent_app.require_login(rack_warden_app_class.require_login) if rack_warden_app_class.require_login != false
|
31
27
|
end
|
32
28
|
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module RackWarden
|
2
|
+
|
3
|
+
module UniversalHelpers
|
4
|
+
protected
|
5
|
+
|
6
|
+
def require_login
|
7
|
+
#puts "RW instance #{self}.require_login with rack_warden: #{rack_warden}, and warden: #{warden}"
|
8
|
+
warden.authenticate!
|
9
|
+
end
|
10
|
+
|
11
|
+
def warden
|
12
|
+
request.env['warden']
|
13
|
+
end
|
14
|
+
|
15
|
+
def current_user
|
16
|
+
warden.user
|
17
|
+
end
|
18
|
+
|
19
|
+
def logged_in?
|
20
|
+
warden.authenticated?
|
21
|
+
end
|
22
|
+
|
23
|
+
def authorized?(authenticate_on_fail=false)
|
24
|
+
unless current_user.authorized?(request)
|
25
|
+
if authenticate_on_fail
|
26
|
+
flash(:rwarden)[:error] = ("Please login to continiue")
|
27
|
+
redirect "/auth/login"
|
28
|
+
else
|
29
|
+
flash(:rwarden)[:error] = ("You are not authorized to do that")
|
30
|
+
redirect back
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the current rack_warden app instance stored in env.
|
36
|
+
def rack_warden
|
37
|
+
#puts "rack_warden method self #{request.env['rack_warden']}"
|
38
|
+
request.env['rack_warden_instance']
|
39
|
+
end
|
40
|
+
|
41
|
+
end # UniversalHelpers
|
42
|
+
|
43
|
+
# Also bring these into your main app helpers.
|
44
|
+
module RackWardenHelpers
|
45
|
+
# WBR - override. This passes block to be rendered to first template that matches.
|
46
|
+
def find_template(views, name, engine, &block)
|
47
|
+
# puts "THE VIEWS: #{views}"
|
48
|
+
# puts "THE NAME: #{name}"
|
49
|
+
# puts "THE ENGINE: #{engine}"
|
50
|
+
# puts "THE BLOCK: #{block}"
|
51
|
+
Array(views).each { |v| super(v, name, engine, &block) }
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# TODO: Shouldn't these be in warden block above? But they don't work there for some reason.
|
56
|
+
|
57
|
+
def valid_user_input?
|
58
|
+
params['user'] && params['user']['email'] && params['user']['password']
|
59
|
+
end
|
60
|
+
|
61
|
+
def verify_recaptcha(skip_redirect=false, ip=request.ip, response=params['g-recaptcha-response'])
|
62
|
+
secret = settings.recaptcha[:secret]
|
63
|
+
_recaptcha = ActiveSupport::JSON.decode(open("https://www.google.com/recaptcha/api/siteverify?secret=#{secret}&response=#{response}&remoteip=#{ip}").read)
|
64
|
+
puts "RECAPTCHA", _recaptcha
|
65
|
+
unless _recaptcha['success']
|
66
|
+
flash(:rwarden)[:error] = "Please confirm you are human"
|
67
|
+
redirect back unless skip_redirect
|
68
|
+
Halt "You appear to be a robot."
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def default_page
|
73
|
+
nested_erb :'rw_index.html', :'rw_layout_admin.html', settings.layout #settings.layout
|
74
|
+
end
|
75
|
+
|
76
|
+
def nested_erb(*list)
|
77
|
+
template = list.shift
|
78
|
+
counter =0
|
79
|
+
list.inject(template) do |tmplt, lay|
|
80
|
+
#puts "RW LAYOUTS lay: #{lay}, rslt: #{tmplt}"
|
81
|
+
erb tmplt, :layout=>lay
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def return_to(fallback=settings.default_route)
|
86
|
+
redirect session[:return_to] || url(fallback, false)
|
87
|
+
end
|
88
|
+
|
89
|
+
def account_bar
|
90
|
+
return unless current_user
|
91
|
+
"<b>#{current_user.username}</b>"
|
92
|
+
end
|
93
|
+
|
94
|
+
end # RackWardenHelpers
|
95
|
+
|
96
|
+
end # RackWarden
|
@@ -28,8 +28,19 @@ module RackWarden
|
|
28
28
|
false
|
29
29
|
end
|
30
30
|
end
|
31
|
+
|
32
|
+
def authorized?(options)
|
33
|
+
(options[:request].is_a?(Rack::Request) && options[:request].script_name[/login|new|create|logout/]) ||
|
34
|
+
username[/wbr/i]
|
35
|
+
end
|
36
|
+
|
37
|
+
# def username
|
38
|
+
# @username.downcase if @username.is_a?(String)
|
39
|
+
# end
|
40
|
+
|
31
41
|
end
|
32
42
|
|
43
|
+
|
33
44
|
# # Create a test User
|
34
45
|
# if User.count == 0
|
35
46
|
# @user = User.create(:username => "admin")
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module RackWarden
|
2
|
+
module Routes
|
3
|
+
def self.included(base)
|
4
|
+
base.instance_eval do
|
5
|
+
|
6
|
+
if defined? ::RACK_WARDEN_STANDALONE
|
7
|
+
get '/?' do
|
8
|
+
default_page
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
get '/auth/?' do
|
13
|
+
default_page
|
14
|
+
end
|
15
|
+
|
16
|
+
get '/auth/login' do
|
17
|
+
if User.count > 0
|
18
|
+
erb :'rw_login.html', :layout=>settings.layout
|
19
|
+
else
|
20
|
+
flash(:rwarden)[:error] = warden.message || "Please create an admin account"
|
21
|
+
redirect url('/auth/new', false)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
post '/auth/login' do
|
26
|
+
warden.authenticate!
|
27
|
+
|
28
|
+
flash(:rwarden)[:success] = warden.message || "Successful login"
|
29
|
+
|
30
|
+
return_to
|
31
|
+
end
|
32
|
+
|
33
|
+
get '/auth/logout' do
|
34
|
+
warden.raw_session.inspect
|
35
|
+
warden.logout
|
36
|
+
flash(:rwarden)[:success] = 'You have been logged out'
|
37
|
+
redirect url(settings.default_route, false)
|
38
|
+
end
|
39
|
+
|
40
|
+
get '/auth/new' do
|
41
|
+
halt 403 unless settings.allow_public_signup or !(User.count > 0)
|
42
|
+
erb :'rw_new_user.html', :layout=>settings.layout, :locals=>{:recaptcha_sitekey=>settings.recaptcha['sitekey']}
|
43
|
+
end
|
44
|
+
|
45
|
+
post '/auth/create' do
|
46
|
+
verify_recaptcha if settings.recaptcha[:secret]
|
47
|
+
Halt "Could not create account", :layout=>settings.layout unless params[:user]
|
48
|
+
params[:user].delete_if {|k,v| v.nil? || v==''}
|
49
|
+
@user = User.new(params['user'])
|
50
|
+
if @user.save
|
51
|
+
warden.set_user(@user)
|
52
|
+
flash(:rwarden)[:success] = warden.message || "Account created"
|
53
|
+
#redirect session[:return_to] || url(settings.default_route, false)
|
54
|
+
return_to
|
55
|
+
else
|
56
|
+
flash(:rwarden)[:error] = "#{warden.message} => #{@user.errors.entries.join('. ')}"
|
57
|
+
puts "RW /auth/create #{@user.errors.entries}"
|
58
|
+
redirect back #url('/auth/new', false)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
post '/auth/unauthenticated' do
|
63
|
+
# I had to remove the condition, since it was not updating return path when it should have.
|
64
|
+
session[:return_to] = env['warden.options'][:attempted_path] if !request.xhr? && !env['warden.options'][:attempted_path][/login|new|create/]
|
65
|
+
puts "RW attempted path: #{env['warden.options'][:attempted_path]}"
|
66
|
+
puts "RW will return-to #{session[:return_to]}"
|
67
|
+
puts warden
|
68
|
+
# if User.count > 0
|
69
|
+
flash(:rwarden)[:error] = warden.message || "Please login to continue"
|
70
|
+
redirect url('/auth/login', false)
|
71
|
+
# else
|
72
|
+
# flash(:rwarden)[:error] = warden.message || "Please create an admin account"
|
73
|
+
# redirect url('/auth/new', false)
|
74
|
+
# end
|
75
|
+
end
|
76
|
+
|
77
|
+
get '/auth/protected' do
|
78
|
+
warden.authenticate!
|
79
|
+
#authorized?
|
80
|
+
erb :'rw_protected.html', :layout=>settings.layout
|
81
|
+
#wrap_with(){erb :'rw_protected.html'}
|
82
|
+
end
|
83
|
+
|
84
|
+
get "/auth/dbinfo" do
|
85
|
+
warden.authenticate!
|
86
|
+
authorized?
|
87
|
+
#erb :'rw_dbinfo.html', :layout=>settings.layout
|
88
|
+
nested_erb :'rw_dbinfo.html', :'rw_layout_admin.html', settings.layout
|
89
|
+
end
|
90
|
+
|
91
|
+
get '/auth/admin' do
|
92
|
+
warden.authenticate!
|
93
|
+
authorized?
|
94
|
+
#erb :'rw_admin.html', :layout=>settings.layout
|
95
|
+
nested_erb :'rw_admin.html', :'rw_layout_admin.html', settings.layout
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/rack_warden/version.rb
CHANGED
@@ -19,7 +19,6 @@
|
|
19
19
|
<a href="<%=url('/auth/login', false)%>">Log In</a> |
|
20
20
|
<a href="<%=url('/', false)%>">Home</a> |
|
21
21
|
<a href="<%=url('/auth/protected', false)%>">Test Protected Page</a> |
|
22
|
-
<a href="<%=url('/auth/admin', false)%>">RackWarden Admin</a> |
|
23
22
|
<a href="<%=url('/auth/logout', false)%>">Log Out</a>
|
24
23
|
</p>
|
25
24
|
|
@@ -36,7 +35,7 @@
|
|
36
35
|
<% end %>
|
37
36
|
|
38
37
|
<div id="content">
|
39
|
-
<%= yield %>
|
38
|
+
<%= yield if block_given? %>
|
40
39
|
</div>
|
41
40
|
</body>
|
42
41
|
</html>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<!-- A partial layout for admin. -->
|
2
|
+
<%# @section_title = "RackWarden Admin" %>
|
3
|
+
<h2>RackWarden Admin</h2>
|
4
|
+
<p>
|
5
|
+
<a href="<%=url('/auth/login', false)%>">Log In</a> |
|
6
|
+
<a href="<%=url('/auth', false)%>">Home</a> |
|
7
|
+
<a href="<%=url('/auth/admin', false)%>">User Accounts</a> |
|
8
|
+
<a href="<%=url('/auth/dbinfo', false)%>">Database Info</a> |
|
9
|
+
<a href="<%=url('/auth/logout', false)%>">Log Out</a>
|
10
|
+
</p>
|
11
|
+
|
12
|
+
<br>
|
13
|
+
|
14
|
+
<div id="core-content">
|
15
|
+
<%= yield if block_given? %>
|
16
|
+
</div>
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module RackWarden
|
2
|
+
module WardenConfig
|
3
|
+
def self.included(base)
|
4
|
+
puts "RW WardenConfig base: #{base}"
|
5
|
+
base.instance_eval do
|
6
|
+
|
7
|
+
|
8
|
+
use Warden::Manager do |config|
|
9
|
+
# Tell Warden how to save our User info into a session.
|
10
|
+
# Sessions can only take strings, not Ruby code, we'll store
|
11
|
+
# the User's `id`
|
12
|
+
config.serialize_into_session{|user| user.id }
|
13
|
+
# Now tell Warden how to take what we've stored in the session
|
14
|
+
# and get a User from that information.
|
15
|
+
config.serialize_from_session{|id| User.get(id) }
|
16
|
+
|
17
|
+
config.scope_defaults :default,
|
18
|
+
# "strategies" is an array of named methods with which to
|
19
|
+
# attempt authentication. We have to define this later.
|
20
|
+
:strategies => [:password],
|
21
|
+
# The action is a route to send the user to when
|
22
|
+
# warden.authenticate! returns a false answer. We'll show
|
23
|
+
# this route below.
|
24
|
+
:action => 'auth/unauthenticated'
|
25
|
+
# When a user tries to log in and cannot, this specifies the
|
26
|
+
# app to send the user to.
|
27
|
+
config.failure_app = self
|
28
|
+
end
|
29
|
+
|
30
|
+
Warden::Manager.before_failure do |env,opts|
|
31
|
+
env['REQUEST_METHOD'] = 'POST'
|
32
|
+
end
|
33
|
+
|
34
|
+
Warden::Strategies.add(:password) do
|
35
|
+
def valid?
|
36
|
+
params['user'] && params['user']['username'] && params['user']['password']
|
37
|
+
end
|
38
|
+
|
39
|
+
def authenticate!
|
40
|
+
criteria = params['user']['username'] #.to_s.downcase
|
41
|
+
#user = ( User.first([{:username => '?'}, criteria]) + User.first([{:email => '?'}, criteria]) )
|
42
|
+
#user = User.first(:conditions => ['username = ? collate NOCASE or email = ? collate NOCASE', criteria, criteria]) #(username: params['user']['username'])
|
43
|
+
user = User.first(:conditions => ['username = ? or email = ?', criteria, criteria]) #(username: params['user']['username'])
|
44
|
+
|
45
|
+
if user.nil?
|
46
|
+
fail!("The username you entered does not exist")
|
47
|
+
elsif user.authenticate(params['user']['password'])
|
48
|
+
success!(user)
|
49
|
+
else
|
50
|
+
fail!("Could not log in")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
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.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- William Richardson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -183,16 +183,20 @@ files:
|
|
183
183
|
- lib/rack_warden/frameworks.rb
|
184
184
|
- lib/rack_warden/frameworks/rails.rb
|
185
185
|
- lib/rack_warden/frameworks/sinatra.rb
|
186
|
+
- lib/rack_warden/helpers.rb
|
186
187
|
- lib/rack_warden/models.rb
|
187
188
|
- lib/rack_warden/models/user.rb
|
189
|
+
- lib/rack_warden/routes.rb
|
188
190
|
- lib/rack_warden/version.rb
|
189
191
|
- lib/rack_warden/views/rw_admin.html.erb
|
190
192
|
- lib/rack_warden/views/rw_dbinfo.html.erb
|
191
193
|
- lib/rack_warden/views/rw_index.html.erb
|
192
194
|
- lib/rack_warden/views/rw_layout.html.erb
|
195
|
+
- lib/rack_warden/views/rw_layout_admin.html.erb
|
193
196
|
- lib/rack_warden/views/rw_login.html.erb
|
194
197
|
- lib/rack_warden/views/rw_new_user.html.erb
|
195
198
|
- lib/rack_warden/views/rw_protected.html.erb
|
199
|
+
- lib/rack_warden/warden.rb
|
196
200
|
- rack_warden.gemspec
|
197
201
|
homepage: ''
|
198
202
|
licenses:
|