rack_warden 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +2 -0
  3. data/Gemfile +13 -10
  4. data/README.md +115 -53
  5. data/config.ru +1 -0
  6. data/lib/rack_warden.rb +33 -5
  7. data/lib/rack_warden/app.rb +73 -58
  8. data/lib/rack_warden/core_patches.rb +20 -0
  9. data/lib/rack_warden/env.rb +27 -0
  10. data/lib/rack_warden/frameworks.rb +34 -36
  11. data/lib/rack_warden/frameworks/rack.rb +36 -0
  12. data/lib/rack_warden/frameworks/rails.rb +29 -9
  13. data/lib/rack_warden/frameworks/sinatra.rb +15 -11
  14. data/lib/rack_warden/helpers.rb +197 -29
  15. data/lib/rack_warden/mail.rb +26 -0
  16. data/lib/rack_warden/models.rb +79 -40
  17. data/lib/rack_warden/models/user.rb +180 -22
  18. data/lib/rack_warden/routes.rb +159 -83
  19. data/lib/rack_warden/sinatra/decompile.rb +127 -0
  20. data/lib/rack_warden/sinatra/json.rb +131 -0
  21. data/lib/rack_warden/sinatra/namespace.rb +285 -0
  22. data/lib/rack_warden/sinatra/respond_with.rb +277 -0
  23. data/lib/rack_warden/version.rb +1 -1
  24. data/lib/rack_warden/views/rw_account_widget.html.erb +8 -0
  25. data/lib/rack_warden/views/rw_activation.email.erb +3 -0
  26. data/lib/rack_warden/views/rw_admin.html.erb +7 -5
  27. data/lib/rack_warden/views/rw_dbinfo.html.erb +5 -4
  28. data/lib/rack_warden/views/rw_error.html.erb +1 -0
  29. data/lib/rack_warden/views/rw_flash_widget.html.erb +12 -0
  30. data/lib/rack_warden/views/rw_index.html.erb +1 -1
  31. data/lib/rack_warden/views/rw_layout.html.erb +13 -19
  32. data/lib/rack_warden/views/rw_layout_admin.html.erb +6 -6
  33. data/lib/rack_warden/views/rw_login.html.erb +18 -5
  34. data/lib/rack_warden/views/rw_new_user.html.erb +22 -6
  35. data/lib/rack_warden/views/rw_protected.xml.erb +10 -0
  36. data/lib/rack_warden/views/rw_session.html.erb +34 -0
  37. data/lib/rack_warden/warden.rb +161 -30
  38. data/rack_warden.gemspec +16 -13
  39. metadata +84 -29
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OGI4OGQxNWNhZTkwNWNlODQ3ZTkwNWFmZTZiODFkM2MwNTMzNWZkZg==
4
+ Yzg2NzVkNGE1Yzc3NWIwYmNhZDkxMGNkMDE3MzZiZGU3MTNkMDQwOQ==
5
5
  data.tar.gz: !binary |-
6
- YWFiYWY3NmRjNzZmNjJhMzIzM2Y2YjFmY2I5OGVjMmI5OGFmMDQ4Mg==
6
+ M2UzZTNiM2UxOGFhYjBhN2VmNzI4OGM1N2UyMDk1NDBmNWI5MjI1OQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NWVlZDdkMzczOTIwMjYzY2I4NjZiZmExNzlmYWQyZmU5OGJjYTg1YWUyZDA3
10
- YzcwNDYzOGZiMzBlNDg2NjQ2ZmI1YTBkNjU3MTc0YTFiM2Y3NTgzZTQyNzNk
11
- MjUyMGI2NzVlMTkwOWQ0ODdiZWRhYzVkMTI5ZDFjMWNhMzhjZGE=
9
+ ZTk4MmI2YmU5YTg1OTM3MWFkMjc3YjExOTQwYjY5ZTI5N2U4NWI3YmE2ZWU2
10
+ YjAwMGE1NDBjODU5NGE4OWVmYjIzM2FhYzUyY2VlYTJhYjEyNTk3YTk1M2E5
11
+ NmJkNDA0NDI0N2JlZmM2ZjcyZTVmY2RiNzM3Zjg1M2RiZTM5NzU=
12
12
  data.tar.gz: !binary |-
13
- YzQ3ZTIzMjMyNWQ4YTRmMmQxMTRiNjMwNDliOTkwN2IyZTVjOGY3MjQ3MGIz
14
- ODg0ZTBhMTk3ZmE4MzE3YTNiNzhjN2ExMGJmYTZhNGViZDJhYjNlOGNiZTky
15
- MjhhMzE4MWFkMzAyZDUyZGMwZmYwYjQ0ZDQ5Mjk2NmE1ZDA4MWI=
13
+ MmYxYWIzOWQ5YWNhZDE1ZTNlYTAwNTYwMzRlZWVhM2QxMTkzNWVlYTcyNGNm
14
+ ZDNmNDAyNjFlMzBlMTYzNzMwNWFhY2Y2Zjg1MGIxMjQyY2ExNTQ4MmJjMTY3
15
+ M2VjZmFiMzU1NDNiNDc5ODc4YTI3OTM1MWUyNzM0OWY1Yzk1MzU=
data/.gitignore CHANGED
@@ -22,4 +22,6 @@ rack_warden.y*ml
22
22
  .DS_Store
23
23
  log/**
24
24
  scratch.rb
25
+ /*.diff
25
26
 
27
+ rack_warden_local_testing
data/Gemfile CHANGED
@@ -3,15 +3,18 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in rack_warden.gemspec
4
4
  gemspec
5
5
 
6
+ # To use edge sinatra, which should fix "NoMethodError: undefined method `join' for #<String:0x000001016a7c58>",
7
+ # put this in your gemfile:
8
+ #gem 'sinatra', git: 'git@github.com:sinatra/sinatra.git'
6
9
 
7
- # gem 'sinatra'
8
- # gem 'sinatra-flash', require: 'sinatra/flash'
9
- # gem 'bcrypt'
10
- # gem 'data_mapper'
11
- # gem 'dm-sqlite-adapter'
12
- # gem 'warden'
13
- #
14
- # #gem 'shotgun'
15
- # #gem 'tux'
16
- # #gem 'thin'
10
+ # Extra utilities that you might want.
11
+ #gem 'shotgun'
12
+ #gem 'tux'
13
+ #gem 'thin'
17
14
 
15
+ # If you have trouble with failing dependencies or templating errors in rails 2.3,
16
+ # you may need to activate any or all of these.
17
+ #gem "i18n", "0.6.11"
18
+ #gem "mime-types", "~> 1.25"
19
+ #gem "nokogiri", "1.5.11"
20
+ #gem "erubis"
data/README.md CHANGED
@@ -1,45 +1,50 @@
1
1
  # RackWarden
2
2
 
3
- RackWarden is a rack middleware mini-app that provides user authentication and management to any rack-based app (currently supports Sinatra and Rails, with more on the way). This project is in its infancy. It is currently a great starter to get you going with plug-in authentication for your ruby app. Over time it will grow into a more fully featured package while maintaining a focus on simplicity, modularity, and transparency.
3
+ RackWarden is a ruby gatekeeper mini-app providing authentication and user management for rack based apps. Protecting your entire application with only a few lines of code, RackWarden uses its own controllers, views, models, and database. You can also drop in your own views and layouts, specify your own database, and use your existing users table for seamless custom integration.
4
4
 
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.
5
+ RackWarden is Rack middleware that uses Sinatra for UI, Warden for authentication, and DataMapper for database connections. It is based on the sinatra-warden-example at <https://github.com/sklise/sinatra-warden-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.
8
-
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
-
11
- ## What Does it Do?
12
-
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
-
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
-
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.
7
+ RackWarden is a work-in-progress. The gemspec, the files, the code, and the documentation are likely to change over time. Follow on [rubygems.org](https://rubygems.org/gems/rack_warden) or [github](https://github.com/ginjo/rack_warden) for the latest updates.
18
8
 
19
9
 
20
10
  ## Installation
21
11
 
22
- In your Gemfile:
12
+ In your Gemfile.
23
13
 
24
14
  gem 'rack_warden'
25
15
 
26
- Then:
16
+ Then.
27
17
 
28
18
  $ bundle
29
19
 
30
- Or install manually:
20
+ Or install manually.
31
21
 
32
22
  $ gem install rack_warden
33
23
 
24
+ If you are using a database other than sqlite, and you want RackWarden to use that database as well, install the corresponding DataMapper database adapter. For sqlite, the dm-sqlite-adapter is already included in the RackWarden gemspec.
25
+
26
+ gem 'dm-mysql-adapter'
27
+ gem 'dm-postgres-adapter'
28
+
29
+ See the [DataMapper](https://github.com/datamapper/dm-core/wiki/Adapters) site for more info on adapters.
34
30
 
35
31
  ## Usage
36
32
 
37
33
  A few simple steps will have your entire app protected.
34
+ If not using bundler, don't forget to ```require 'rack_warden'```.
38
35
 
39
36
  ### Sinatra
40
37
 
38
+ # classic
39
+ register RackWarden
40
+
41
+ get "/" do
42
+ erb "All routes are now protected"
43
+ end
44
+
45
+ # modular
41
46
  class MySinatraApp < Sinatra::Base
42
- use RackWarden
47
+ register RackWarden
43
48
 
44
49
  get "/" do
45
50
  erb "All routes are now protected"
@@ -54,53 +59,96 @@ application.rb or environment.rb
54
59
 
55
60
  # All routes are now protected
56
61
 
62
+ ### Rack
63
+
64
+ You can also use RackWarden with bare Rack applications. A ruby application framework is not necessary.
65
+
66
+ config.ru
67
+
68
+ map "/" do
69
+ use RackWarden
70
+ run MyApp
71
+ end
57
72
 
58
73
 
59
74
  ## Configuration
60
75
 
61
- RackWarden will look for a configuration file named rack\_warden.yml in your project root or in your project/config/ directory.
76
+ RackWarden will look for a yaml configuration file named rack_warden.yml in your project root or in your project-root/config/ directory. You can specify any of RackWarden's settings here.
62
77
 
63
78
  ---
64
79
  database: sqlite3:///usr/local/some_other_database.sqlite3.db
65
80
  layout: :'my_custom_layout.html.erb'
66
81
 
67
82
 
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.
83
+ 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 standard Sinatra settings.
69
84
 
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.
85
+ 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 RackWarden::App class itself. While in the block, you also have access to the current _instance_ of RackWarden::App.
71
86
 
72
87
  use RackWarden::App do |rack_warden_app_instance|
73
- set :somesetting, 'some_value'
88
+ set :some_setting, 'some_value'
74
89
  end
90
+
91
+ You can also set RackWarden settings directly from inside your application.
92
+
93
+ RackWarden::App.set({:setting1 => val1, :setting2 => val2})
75
94
 
95
+ Note that with some frameworks, the RackWarden middleware instance will be lazy-loaded only when it is needed (usually with the first request). This is a function of the ruby framework you are using and is not under control of RackWarden. This means that some settings you pass with the ```use``` method (or block) may have 'missed the boat'. RackWarden tries to integrate these settings in lazy-loaded situations as best as it can. However, if you suspect your settings might not be taking, put your settings in the rack\_warden.yml config file. The config file will always be loaded with the RackWarden module. If you are using Sinatra, load up RackWarden with ```register RackWarden```, as that will initialize RackWarden as soon as your Sinatra project loads.
96
+
76
97
 
77
98
  ## Configuration Options
78
99
 
79
100
  Current list of settings specific to rack\_warden, with defaults.
80
101
 
102
+ set :config_files, [ENV['RACK_WARDEN_CONFIG_FILE'], 'rack_warden.yml', 'config/rack_warden.yml'].compact.uniq
103
+ set :layout, :'rw_layout.html'
104
+ set :default_route, '/'
105
+ set :exclude_from_return_to, 'login|logout|new|create'
106
+ set :repository_name, :default
107
+ set :database_config => nil
108
+ set :database_default => "sqlite3:///#{Dir.pwd}/rack_warden.sqlite3.db"
109
+ set :recaptcha, Hash.new
110
+ set :require_login, nil
111
+ set :rack_authentication, nil
112
+ set :allow_public_signup, false
113
+ set :logging, true
114
+ set :log_path, "#{Dir.pwd}/log/rack_warden.#{settings.environment}.log"
115
+ set :use_common_logger, false
116
+ set :sessions, true
117
+ set :remember_token_cookie_name, 'rack_warden_remember_token'
118
+ set :user_table_name, 'rack_warden_users'
119
+ set :views, File.expand_path("../views/", __FILE__) unless views
120
+ set :login_on_create, true
121
+ set :login_on_activate, false
122
+ set :rw_prefix, '/auth'
123
+ set :mail_options,
124
+ :delivery_method => :test,
125
+ :delivery_options => {:from => 'my@email.com'}
126
+
127
+
128
+ Some of the configuration settings in more detail.
129
+
81
130
  ### :layout
82
131
 
83
- A symbol representing a layout file in any of the view paths.
132
+ A symbol representing a (Sinatra) layout file in any of the view paths.
84
133
 
85
134
  layout: :'rack_warden_layout.html'
86
135
 
87
136
  ### :default\_route
88
137
 
89
- A Sinatra route to fall back on after logout, errors, or any action that has no specified route.
138
+ A Sinatra route to fall back on after logout, errors, or any redirect that has no specified route.
90
139
 
91
140
  default_route: '/'
92
141
 
93
142
  ### :database\_config
94
143
 
95
- A database specification hash or or url string.
144
+ A database specification hash or url string.
96
145
 
97
146
  database_config: "sqlite:///Absolute/path/to/your/rack_warden.sqlite3.db"
98
147
 
99
148
  # or
100
149
 
101
150
  database_config:
102
- adapter: mysql2
103
- encoding: utf8
151
+ adapter: mysql
104
152
  database: my_db_name
105
153
  username: root
106
154
  password: my_password
@@ -110,31 +158,30 @@ A database specification hash or or url string.
110
158
  ### :require\_login
111
159
 
112
160
  Parameters to pass to the before/before\_filter for require\_login.
113
- So if you're main app is Sinatra,
161
+ So if your main app is Sinatra,
114
162
 
115
- require_login: /^\/.+/
163
+ require_login: '/admin*'
116
164
 
117
165
  is the same as
118
166
 
119
167
  class MySinatraApp
120
- require_login /^\/.+/
168
+ require_login '/admin*'
121
169
  end
122
170
 
123
171
  which is the same as
124
172
 
125
173
  class MySinatraApp
126
- before /^\/.+/ do
174
+ before '/admin*' do
127
175
  require_login
128
176
  end
129
177
  end
130
178
 
131
179
  For Rails, you would be passing a hash of :only or :except keys.
132
180
 
133
- require_login:
134
- except: :index
181
+ require_login: {:except => [:index, :show]}
135
182
 
136
183
  The default for :require\_login is nil, which means require login on every route or action.
137
- To disable automatic activation of require\_login, pass it ```false```.
184
+ To disable automatic activation of require\_login, set it to ```false```.
138
185
 
139
186
  ### :allow\_public\_signup
140
187
 
@@ -145,44 +192,54 @@ Allows public access to the account creation view & action.
145
192
 
146
193
  ### :recaptcha
147
194
 
148
- Settings for Google's recaptcha service
195
+ Settings for Google's recaptcha service. If these settings exist, recaptcha will be required on account creation and password reset/recover actions.
149
196
 
150
197
  :recaptcha => {
151
198
  :sitekey => '',
152
199
  :secret => ''
153
200
  }
154
201
 
155
- ### :log\_path
156
202
 
157
- File.join(Dir.pwd, 'log', 'rack_warden.log')
158
-
159
- ### :user\_table\_name
160
203
 
161
- nil
162
-
163
- ### :views
204
+ ## Customization
164
205
 
165
- File.expand_path("../views/", __FILE__)
206
+ ### Actions
166
207
 
208
+ RackWarden adds a handful of helpers to your base controller class, giving you finer control over what actions (or routes) are protected. One of these helpers is ```require_login```. Run this helper in any action that you want protected behind a login session. If the user is not logged in, they will be redirected to the login action provided by RackWarden. Once they have successfully completed the login, the user will be redirected back to the protected page they were originally trying to access.
209
+
210
+ The default for RackWarden is to enable the ```require_login``` helper on every action in your project. To disable this default, set ```:require_login``` (in your RackWarden configuration) to anything other than nil. Setting ```:require_login => false``` will disable automatic activation of the ```require_login``` helper entirely.
211
+
212
+ To control authentication inclusion/exclusion of routes & actions on a per-controller or per-application basis, use the class method ```require_login```. This creates a before filter in the context where you declare it. You can pass any options to ```require_login``` that are allowed by your framework's before filter.
213
+
214
+ # Rails
215
+ class Products < ActionController::Base
216
+ require_login :only=>[:new, :create, :edit, :update]
217
+ ...
218
+ end
219
+
220
+ # Sinatra
221
+ class MyApp < Sinatra::Base
222
+ require_login '/admin*', :agent => /Songbird/
223
+ ...
224
+ end
167
225
 
168
- ## Customization
169
226
 
170
227
  ### Views
171
228
 
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.
229
+ 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.
173
230
 
174
231
  use RackWarden::App, :views => File.join(Dir.pwd, 'app/views/another_directory')
175
232
 
176
- Or if you simply want RackWarden to use your own custom layout, pass it a file path in the :layout parameter.
233
+ Or if you simply want RackWarden to wrap all of its views in your own custom layout, pass it a file path in the :layout parameter.
177
234
 
178
235
  use RackWarden::App, :layout => :'layouts/rack_warden_layout.html'
179
236
 
180
- 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.
237
+ 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.
181
238
 
182
239
 
183
240
  ### Database
184
241
 
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.
242
+ As a default, RackWarden will use a sqlite3 database created in your app's root. 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 gem 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
243
 
187
244
  # Database specification as a url
188
245
  database_config: 'sqlite3:///path/to/my/database.sqlite3.db'
@@ -190,12 +247,17 @@ As a default, RackWarden will use a sqlite3 in-memory database (that starts fres
190
247
  # Database specification as a hash
191
248
  database_config: {adapter: 'sqlite3', database: '/path/to/my/database.sqlite3.db'}
192
249
 
193
- # Use a remote MySQL database
194
- database_config: {adapter: 'mysql', username: 'will', password: 'mypass',
195
- host: 'somehost', database: 'my_database'}
196
-
197
- # Format for database urls
198
- #<adapter>://<username>:<password>@<host>:<port>/<database_name>
250
+ # Use a remote MySQL database
251
+ database_config: {adapter: 'mysql', username: 'will', password: 'mypass',
252
+ host: 'somehost', database: 'my_database'}
253
+
254
+ # Format for database urls
255
+ #<adapter>://<username>:<password>@<host>:<port>/<database_name>
256
+
257
+ #### A note about DataMapper and ActiveRecord
258
+
259
+ ActiveRecord and DataMapper should be able to coexist in the same ruby process. Note that the database adapters for ActiveRecord are not the same as those for DataMapper. So for example, if you are using mysql, you will need the activerecord-mysql2-adapter for ActiveRecord (or mysql2 or mysql, if you're on older rails versions) and the dm-mysql-adapter for DataMapper.
260
+
199
261
 
200
262
 
201
263
 
data/config.ru CHANGED
@@ -7,5 +7,6 @@ Bundler.require
7
7
  require File.expand_path('../lib/rack_warden', __FILE__)
8
8
 
9
9
  map ENV['BASE_URI'] || '/' do
10
+ RackWarden::App.set :sessions, :key=>'_rack_warden'
10
11
  run RackWarden::App
11
12
  end
@@ -6,25 +6,42 @@ module RackWarden
6
6
  end
7
7
 
8
8
  require "sinatra/base"
9
- require "sinatra/flash"
9
+ #require "sinatra/contrib" # not compatible with rails 2.3 because of rack dependency conflict.
10
+ require "rack/flash" # this somehow loads rack/flash3
11
+ require "rack/contrib/cookies" # This is needed to set cookies in warden callbacks.
10
12
  require 'bcrypt'
11
13
  require 'data_mapper'
12
14
  require 'warden'
13
- require 'open-uri'
14
15
  require 'yaml'
16
+ require 'tilt/erb' # An error somwhere suggested this be explicity required.
17
+ require 'rack_warden/core_patches'
18
+
19
+ autoload :Mail, 'mail'
20
+ autoload :URI, 'open-uri'
21
+ autoload :Base64, 'base64'
15
22
 
16
23
  module RackWarden
17
24
  autoload :App, 'rack_warden/app'
25
+ autoload :Env, 'rack_warden/env'
18
26
  autoload :User, "rack_warden/models"
19
27
  autoload :Pref, "rack_warden/models"
28
+ autoload :Mail, "rack_warden/mail"
20
29
  autoload :Routes, "rack_warden/routes"
21
30
  autoload :VERSION, "rack_warden/version"
22
31
  autoload :WardenConfig, "rack_warden/warden"
32
+ autoload :AppClassMethods, "rack_warden/helpers"
33
+ autoload :UniversalHelpers, "rack_warden/helpers"
23
34
  autoload :RackWardenHelpers, "rack_warden/helpers"
35
+ # Autload patched versions of respond_with & namespace.
36
+ # respond_with handles uri dot-format extension,
37
+ # and namespace handles require_login.
38
+ autoload :RespondWith, "rack_warden/sinatra/respond_with"
39
+ autoload :Namespace, "rack_warden/sinatra/namespace"
40
+ autoload :Frameworks, "rack_warden/frameworks"
24
41
  module Frameworks
25
- autoload :Base, 'rack_warden/frameworks'
26
42
  autoload :Sinatra, 'rack_warden/frameworks/sinatra'
27
43
  autoload :Rails, 'rack_warden/frameworks/rails'
44
+ autoload :Rack, 'rack_warden/frameworks/rack'
28
45
  end
29
46
 
30
47
  # Make this module a pseudo-class appropriate for middlware stack. Use RackWarden for older rails apps (rather than 'RackWarden::App')
@@ -50,8 +67,19 @@ module RackWarden
50
67
  end
51
68
 
52
69
  def self.included(base)
53
- puts "RW self.included into BASE #{base}, ID #{base.object_id}"
54
- App.new base
70
+ App.logger.warn "RW self.included into BASE #{base}, ID #{base.object_id}"
71
+ # Force initialize rack_warden, even if not all the settings are known yet.
72
+ #App.new base
73
+ end
74
+
75
+ def self.registered(app)
76
+ App.setup_framework app
77
+ # TODO: Do we need to check installed middleware to make sure we only have one instance of RW,
78
+ # in case someone registers RW with multiple sinatra apps in the same ruby process (which seems to be a common practice)?
79
+ app.use self
55
80
  end
81
+
82
+ # Enable this for automatic sinatra top-level registration.
83
+ #Sinatra.register self
56
84
 
57
85
  end
@@ -1,49 +1,47 @@
1
1
  # require 'bundler'
2
2
  # Bundler.require
3
3
 
4
+ require 'logger'
5
+
4
6
  module RackWarden
5
7
  class App < Sinatra::Base
6
-
8
+
7
9
  set :config_files, [ENV['RACK_WARDEN_CONFIG_FILE'], 'rack_warden.yml', 'config/rack_warden.yml'].compact.uniq
8
10
  set :layout, :'rw_layout.html'
9
11
  set :default_route, '/'
10
- set :database_config => nil #, "sqlite3:///#{Dir.pwd}/rack_warden.sqlite3.db"
11
- set :database_default => "sqlite3::memory:" #"sqlite3:///#{Dir.pwd}/rack_warden.sqlite3.db"
12
+ set :exclude_from_return_to, 'login|logout|new|create'
13
+ set :repository_name, :default
14
+ set :database_config => nil
15
+ set :database_default => "sqlite3:///#{Dir.pwd}/rack_warden.sqlite3.db"
12
16
  set :recaptcha, Hash.new
13
17
  set :require_login, nil
18
+ set :rack_authentication, nil
14
19
  set :allow_public_signup, false
20
+ set :logging, true
15
21
  set :log_path, "#{Dir.pwd}/log/rack_warden.#{settings.environment}.log"
16
- set :user_table_name, nil
22
+ set :log_file, ($0[/rails|irb|ruby|rack|server/i] && development? ? $stdout : nil)
23
+ set :log_level => ENV['RACK_WARDEN_LOG_LEVEL'] || (development? ? 'INFO' : 'WARN')
24
+ set :logger, nil
25
+ set :use_common_logger, false
26
+ set :reset_logger, false
27
+ set :sessions, true # Will use parent app sessions. Pass in :key=>'something' to enable RW-specific sessions (maybe).
28
+ set :remember_token_cookie_name, 'rack_warden_remember_token'
29
+ set :user_table_name, 'rack_warden_users'
17
30
  set :views, File.expand_path("../views/", __FILE__) unless views
18
31
  set :initialized, false
32
+ set :login_on_create, true
33
+ set :login_on_activate, false
34
+ set :rw_prefix, '/auth'
35
+ set :mail_options,
36
+ :delivery_method => :test,
37
+ :delivery_options => {:from => 'my@email.com'} #, :openssl_verify_mode => OpenSSL::SSL::VERIFY_NONE
38
+
19
39
 
20
- # Load config from file, if any exist.
21
- Hash.new.tap do |hash|
22
- config_files.each {|c| hash.merge!(YAML.load_file(File.join(Dir.pwd, c))) rescue nil}
23
- set hash
24
- end
25
-
26
-
27
-
28
- enable :sessions
29
- register Sinatra::Flash
30
-
31
- begin
32
- enable :logging
33
- set :log_file, File.new(settings.log_path, 'a+')
34
- settings.log_file.sync = true
35
- use Rack::CommonLogger, settings.log_file
36
- rescue
37
- end
38
40
 
39
- include RackWarden::WardenConfig
40
- include RackWarden::Routes
41
+ register AppClassMethods
41
42
 
42
- helpers RackWardenHelpers
43
- helpers UniversalHelpers
44
-
45
-
46
43
 
44
+
47
45
  # WBR - This will receive params and a block from the parent "use" statement.
48
46
  # This middleware app has been modified to process the parent use-block in
49
47
  # the context of the RackWarden class. So you can set settings on RackWarden,
@@ -54,40 +52,30 @@ module RackWarden
54
52
  # set :myvar, 'something'
55
53
  # end
56
54
  #
55
+ # TODO: Move most of this functionality to a class method, so it can be called from self.registered(app)
57
56
  def initialize(parent_app_instance=nil, *args, &block)
58
57
  super(parent_app_instance, &Proc.new{}) # Must send empty proc, not original proc, since we're calling original block here.
59
58
  initialization_args = args.dup
60
- puts "RW new instance with parent: #{@app}"
61
- # extract options.
59
+ logger.info "RW new app instance with parent: #{@app}"
62
60
  opts = args.last.is_a?(Hash) ? args.pop : {}
61
+
62
+
63
+
63
64
  if app && !settings.initialized
64
- puts "RW initializing settings"
65
+ logger.warn "RW initializing settings from app instance"
65
66
 
66
- # Save original views from opts.
67
- #settings.set(:original_views, opts.has_key?(:views) ? settings.views : nil)
68
- settings.set(:original_views, settings.views)
69
-
70
- # Set app settings with remainder of opts.
71
- settings.set opts if opts.any?
72
-
67
+ self.class.setup_framework(parent_app_instance, *initialization_args) #unless Frameworks.selected_framework
68
+
73
69
  # Eval the use-block from the parent app, in context of this app.
74
70
  settings.instance_exec(self, &block) if block_given?
75
71
 
76
- # Do framework setup.
77
- framework_module = Frameworks::Base.select_framework(binding)
78
- puts "RW selected framework module #{framework_module}"
79
- if framework_module
80
- framework_module.setup_framework
81
-
82
- # Manipulate views
83
- new_views = []
84
- new_views.unshift settings.original_views
85
- new_views.unshift framework_module.views_path unless settings.views==false
86
- new_views.unshift settings.views
87
- settings.set :views, new_views.flatten.compact.uniq
88
-
89
- puts "RW compiled views: #{settings.views.inspect}"
90
- end
72
+ # Set global layout (remember to use :layout=>false in your calls to partials).
73
+ settings.set :erb, :layout=>settings.layout
74
+
75
+ settings.initialize_logging
76
+
77
+ logger.info "RW compiled views: #{settings.views.inspect}"
78
+
91
79
  settings.set :initialized, true
92
80
  end
93
81
 
@@ -95,14 +83,41 @@ module RackWarden
95
83
 
96
84
  # Store this app instance in the env.
97
85
  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)
86
+ logger.debug "RW app.call extending env with Env."
87
+ env.extend Env
88
+ logger.debug "RW app.call next app: #{@app}"
89
+
90
+ # Set this now, so you can access the rw app instance from the endpoint app.
91
+ logger.debug "RW app.call storing app instance in env['rack_warden_instance'] #{self}"
92
+ self.request= Rack::Request.new(env)
93
+ env.rack_warden = self
94
+
95
+ # Authenticate here-and-now.
96
+ if !request.path_info.to_s.match(/^\/auth/) && settings.rack_authentication
97
+ logger.debug "RW rack_authentication for path_info: #{request.path_info}"
98
+ Array(settings.rack_authentication).each do |rule|
99
+ logger.debug "RW rack_authentication rule #{rule}"
100
+ (require_login) if rule && request.path_info.to_s.match(Regexp.new rule.to_s)
101
+ end
102
+ end
103
+
104
+ # Send to super, then build & process response.
105
+ # resp = Rack::Response.new *super(env).tap{|e| e.unshift e.pop}
106
+ # #resp.set_cookie :wbr_cookie, :value=>"Yay!", :expires=>Time.now+60*10
107
+ # logger.debug "App.call: #{resp.finish}"
108
+ # resp.finish
109
+ super(env)
102
110
  end
111
+
112
+ # Only initialize app after all above have loaded.
113
+ #initialize_app_class
103
114
 
104
115
 
105
- end # App
116
+ end # App
117
+
118
+ # TODO: This is not working:
119
+ #Sinatra::Application.register self
106
120
  end # RackWarden
107
121
 
108
122
 
123
+