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.
- checksums.yaml +8 -8
- data/.gitignore +2 -0
- data/Gemfile +13 -10
- data/README.md +115 -53
- data/config.ru +1 -0
- data/lib/rack_warden.rb +33 -5
- data/lib/rack_warden/app.rb +73 -58
- data/lib/rack_warden/core_patches.rb +20 -0
- data/lib/rack_warden/env.rb +27 -0
- data/lib/rack_warden/frameworks.rb +34 -36
- data/lib/rack_warden/frameworks/rack.rb +36 -0
- data/lib/rack_warden/frameworks/rails.rb +29 -9
- data/lib/rack_warden/frameworks/sinatra.rb +15 -11
- data/lib/rack_warden/helpers.rb +197 -29
- data/lib/rack_warden/mail.rb +26 -0
- data/lib/rack_warden/models.rb +79 -40
- data/lib/rack_warden/models/user.rb +180 -22
- data/lib/rack_warden/routes.rb +159 -83
- data/lib/rack_warden/sinatra/decompile.rb +127 -0
- data/lib/rack_warden/sinatra/json.rb +131 -0
- data/lib/rack_warden/sinatra/namespace.rb +285 -0
- data/lib/rack_warden/sinatra/respond_with.rb +277 -0
- data/lib/rack_warden/version.rb +1 -1
- data/lib/rack_warden/views/rw_account_widget.html.erb +8 -0
- data/lib/rack_warden/views/rw_activation.email.erb +3 -0
- data/lib/rack_warden/views/rw_admin.html.erb +7 -5
- data/lib/rack_warden/views/rw_dbinfo.html.erb +5 -4
- data/lib/rack_warden/views/rw_error.html.erb +1 -0
- data/lib/rack_warden/views/rw_flash_widget.html.erb +12 -0
- data/lib/rack_warden/views/rw_index.html.erb +1 -1
- data/lib/rack_warden/views/rw_layout.html.erb +13 -19
- data/lib/rack_warden/views/rw_layout_admin.html.erb +6 -6
- data/lib/rack_warden/views/rw_login.html.erb +18 -5
- data/lib/rack_warden/views/rw_new_user.html.erb +22 -6
- data/lib/rack_warden/views/rw_protected.xml.erb +10 -0
- data/lib/rack_warden/views/rw_session.html.erb +34 -0
- data/lib/rack_warden/warden.rb +161 -30
- data/rack_warden.gemspec +16 -13
- metadata +84 -29
@@ -0,0 +1,277 @@
|
|
1
|
+
require 'rack_warden/sinatra/json'
|
2
|
+
require 'sinatra/base'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module RackWarden
|
6
|
+
App.logger.debug "RW loading RespondWith"
|
7
|
+
|
8
|
+
#
|
9
|
+
# = Sinatra::RespondWith
|
10
|
+
#
|
11
|
+
# These extensions let Sinatra automatically choose what template to render or
|
12
|
+
# action to perform depending on the request's Accept header.
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
#
|
16
|
+
# # Without Sinatra::RespondWith
|
17
|
+
# get '/' do
|
18
|
+
# data = { :name => 'example' }
|
19
|
+
# request.accept.each do |type|
|
20
|
+
# case type.to_s
|
21
|
+
# when 'text/html'
|
22
|
+
# halt haml(:index, :locals => data)
|
23
|
+
# when 'text/json'
|
24
|
+
# halt data.to_json
|
25
|
+
# when 'application/atom+xml'
|
26
|
+
# halt nokogiri(:'index.atom', :locals => data)
|
27
|
+
# when 'application/xml', 'text/xml'
|
28
|
+
# halt nokogiri(:'index.xml', :locals => data)
|
29
|
+
# when 'text/plain'
|
30
|
+
# halt 'just an example'
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
# error 406
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# # With Sinatra::RespondWith
|
37
|
+
# get '/' do
|
38
|
+
# respond_with :index, :name => 'example' do |f|
|
39
|
+
# f.txt { 'just an example' }
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# Both helper methods +respond_to+ and +respond_with+ let you define custom
|
44
|
+
# handlers like the one above for +text/plain+. +respond_with+ additionally
|
45
|
+
# takes a template name and/or an object to offer the following default
|
46
|
+
# behavior:
|
47
|
+
#
|
48
|
+
# * If a template name is given, search for a template called
|
49
|
+
# +name.format.engine+ (+index.xml.nokogiri+ in the above example).
|
50
|
+
# * If a template name is given, search for a templated called +name.engine+
|
51
|
+
# for engines known to result in the requested format (+index.haml+).
|
52
|
+
# * If a file extension associated with the mime type is known to Sinatra, and
|
53
|
+
# the object responds to +to_extension+, call that method and use the result
|
54
|
+
# (+data.to_json+).
|
55
|
+
#
|
56
|
+
# == Security
|
57
|
+
#
|
58
|
+
# Since methods are triggered based on client input, this can lead to security
|
59
|
+
# issues (but not as severe as those might appear in the first place: keep in
|
60
|
+
# mind that only known file extensions are used). You should limit
|
61
|
+
# the possible formats you serve.
|
62
|
+
#
|
63
|
+
# This is possible with the +provides+ condition:
|
64
|
+
#
|
65
|
+
# get '/', :provides => [:html, :json, :xml, :atom] do
|
66
|
+
# respond_with :index, :name => 'example'
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# However, since you have to set +provides+ for every route, this extension
|
70
|
+
# adds an app global (class method) `respond_to`, that lets you define content
|
71
|
+
# types for all routes:
|
72
|
+
#
|
73
|
+
# respond_to :html, :json, :xml, :atom
|
74
|
+
# get('/a') { respond_with :index, :name => 'a' }
|
75
|
+
# get('/b') { respond_with :index, :name => 'b' }
|
76
|
+
#
|
77
|
+
# == Custom Types
|
78
|
+
#
|
79
|
+
# Use the +on+ method for defining actions for custom types:
|
80
|
+
#
|
81
|
+
# get '/' do
|
82
|
+
# respond_to do |f|
|
83
|
+
# f.xml { nokogiri :index }
|
84
|
+
# f.on('application/custom') { custom_action }
|
85
|
+
# f.on('text/*') { data.to_s }
|
86
|
+
# f.on('*/*') { "matches everything" }
|
87
|
+
# end
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
# Definition order does not matter.
|
91
|
+
module RespondWith
|
92
|
+
class Format
|
93
|
+
def initialize(app)
|
94
|
+
@app, @map, @generic, @default = app, {}, {}, nil
|
95
|
+
end
|
96
|
+
|
97
|
+
def on(type, &block)
|
98
|
+
# WBR
|
99
|
+
@app.logger.debug "RW respond_with.on type: #{type}"
|
100
|
+
@app.logger.debug "RW respond_with.on block: #{block}"
|
101
|
+
@app.logger.debug "RW respond_with.on @app.params: #{@app.params}"
|
102
|
+
@app.logger.debug "RW respond_with.on @app.settings.mime_types(type): #{@app.settings.mime_types(type)}"
|
103
|
+
|
104
|
+
@app.settings.mime_types(type).each do |mime|
|
105
|
+
case mime
|
106
|
+
when '*/*' then @default = block
|
107
|
+
when /^([^\/]+)\/\*$/ then @generic[$1] = block
|
108
|
+
else @map[mime] = block
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def finish
|
114
|
+
yield self if block_given?
|
115
|
+
# WBR - adds format/extension of uri to front of mime-types.
|
116
|
+
# You must capture the format string in the params with your route declaration.
|
117
|
+
format_type = @app.settings.mime_types(@app.params['format'])[0]
|
118
|
+
@app.logger.debug "RW respond_with.finish format_type (WBR): #{format_type}, #{format_type.class}"
|
119
|
+
mime_type = format_type ||
|
120
|
+
@app.content_type ||
|
121
|
+
@app.request.preferred_type(@map.keys) ||
|
122
|
+
@app.request.preferred_type ||
|
123
|
+
'text/html'
|
124
|
+
type = mime_type.split(/\s*;\s*/, 2).first
|
125
|
+
@app.logger.debug "RW respond_with.finish type: #{type}"
|
126
|
+
@app.logger.debug "RW respond_with.finish @map: #{@map}"
|
127
|
+
@app.logger.debug "RW respond_with.finish @default: #{@default}"
|
128
|
+
@app.logger.debug "RW respond_with.finish @generic: #{@generic}"
|
129
|
+
handlers = [@map[type], @generic[type[/^[^\/]+/]], @default].compact
|
130
|
+
handlers.each do |block|
|
131
|
+
if result = block.call(type)
|
132
|
+
@app.content_type mime_type
|
133
|
+
@app.halt result
|
134
|
+
end
|
135
|
+
end
|
136
|
+
@app.halt 406
|
137
|
+
end
|
138
|
+
|
139
|
+
def method_missing(method, *args, &block)
|
140
|
+
return super if args.any? or block.nil? or not @app.mime_type(method)
|
141
|
+
on(method, &block)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
module Helpers
|
146
|
+
include Sinatra::JSON
|
147
|
+
|
148
|
+
def respond_with(template, object = nil, &block)
|
149
|
+
object, template = template, nil unless Symbol === template
|
150
|
+
format = Format.new(self)
|
151
|
+
format.on "*/*" do |type|
|
152
|
+
exts = settings.ext_map[type]
|
153
|
+
exts << :xml if type.end_with? '+xml'
|
154
|
+
# WBR - not necessary, since the hack of #finish method above.
|
155
|
+
#exts.unshift params[:format].to_sym if params[:format]
|
156
|
+
logger.debug "RW respond_with format: #{params[:format]}"
|
157
|
+
|
158
|
+
logger.debug "RW respond_with exts: #{exts.inspect}"
|
159
|
+
if template
|
160
|
+
args = template_cache.fetch(type, template) { template_for(template, exts) }
|
161
|
+
if args.any?
|
162
|
+
locals = { :object => object }
|
163
|
+
locals.merge! object.to_hash if object.respond_to? :to_hash
|
164
|
+
|
165
|
+
renderer = args.first
|
166
|
+
options = args[1..-1] + [{:locals => locals}]
|
167
|
+
|
168
|
+
halt send(renderer, *options)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
if object
|
172
|
+
exts.each do |ext|
|
173
|
+
halt json(object) if ext == :json
|
174
|
+
next unless object.respond_to? method = "to_#{ext}"
|
175
|
+
halt(*object.send(method))
|
176
|
+
end
|
177
|
+
end
|
178
|
+
false
|
179
|
+
end
|
180
|
+
format.finish(&block)
|
181
|
+
end
|
182
|
+
|
183
|
+
def respond_to(&block)
|
184
|
+
Format.new(self).finish(&block)
|
185
|
+
end
|
186
|
+
|
187
|
+
private
|
188
|
+
|
189
|
+
def template_for(name, exts)
|
190
|
+
logger.debug "RW respond_with#template_for name, exts: #{name}, #{exts}"
|
191
|
+
# in production this is cached, so don't worry too much about runtime
|
192
|
+
possible = []
|
193
|
+
settings.template_engines[:all].each do |engine|
|
194
|
+
exts.each { |ext| possible << [engine, "#{name}.#{ext}"] }
|
195
|
+
end
|
196
|
+
exts.each do |ext|
|
197
|
+
settings.template_engines[ext].each { |e| possible << [e, name] }
|
198
|
+
end
|
199
|
+
logger.debug "RW respond_with#template_for possible: #{possible.inspect}"
|
200
|
+
possible.each do |engine, template|
|
201
|
+
# not exactly like Tilt[engine], but does not trigger a require
|
202
|
+
klass = Tilt.mappings[Tilt.normalize(engine)].first
|
203
|
+
logger.debug "RW respond_with#template_for klass : #{klass}"
|
204
|
+
find_template(settings.views, template, klass) do |file|
|
205
|
+
#logger.debug "RW respond_with#template_for find_template file: #{file}"
|
206
|
+
#logger.debug "RW respond_with#template_for find_template engine: #{engine.inspect}"
|
207
|
+
#logger.debug "RW respond_with#template_for find_template template: #{template.inspect}"
|
208
|
+
next unless File.exist? file
|
209
|
+
return settings.rendering_method(engine) << template.to_sym
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
[] # nil or false would not be cached
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def remap_extensions
|
218
|
+
ext_map.clear
|
219
|
+
Rack::Mime::MIME_TYPES.each { |e,t| ext_map[t] << e[1..-1].to_sym }
|
220
|
+
ext_map['text/javascript'] << 'js'
|
221
|
+
ext_map['text/xml'] << 'xml'
|
222
|
+
end
|
223
|
+
|
224
|
+
def mime_type(*)
|
225
|
+
result = super
|
226
|
+
remap_extensions
|
227
|
+
result
|
228
|
+
end
|
229
|
+
|
230
|
+
def respond_to(*formats)
|
231
|
+
if formats.any?
|
232
|
+
@respond_to ||= []
|
233
|
+
@respond_to.concat formats
|
234
|
+
elsif @respond_to.nil? and superclass.respond_to? :respond_to
|
235
|
+
superclass.respond_to
|
236
|
+
else
|
237
|
+
@respond_to
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def rendering_method(engine)
|
242
|
+
return [engine] if Sinatra::Templates.method_defined? engine
|
243
|
+
return [:mab] if engine.to_sym == :markaby
|
244
|
+
[:render, :engine]
|
245
|
+
end
|
246
|
+
|
247
|
+
private
|
248
|
+
|
249
|
+
def compile!(verb, path, block, options = {})
|
250
|
+
options[:provides] ||= respond_to if respond_to
|
251
|
+
super
|
252
|
+
end
|
253
|
+
|
254
|
+
ENGINES = {
|
255
|
+
:css => [:less, :sass, :scss],
|
256
|
+
:xml => [:builder, :nokogiri],
|
257
|
+
:js => [:coffee],
|
258
|
+
:json => [:yajl],
|
259
|
+
:html => [:erb, :erubis, :haml, :slim, :liquid, :radius, :mab, :markdown,
|
260
|
+
:textile, :rdoc],
|
261
|
+
:all => Sinatra::Templates.instance_methods.map(&:to_sym) + [:mab] -
|
262
|
+
[:find_template, :markaby]
|
263
|
+
}
|
264
|
+
|
265
|
+
ENGINES.default = []
|
266
|
+
|
267
|
+
def self.registered(base)
|
268
|
+
base.set :ext_map, Hash.new { |h,k| h[k] = [] }
|
269
|
+
base.set :template_engines, ENGINES.dup
|
270
|
+
base.remap_extensions
|
271
|
+
base.helpers Helpers
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
#register RespondWith
|
276
|
+
#Delegator.delegate :respond_to
|
277
|
+
end
|
data/lib/rack_warden/version.rb
CHANGED
@@ -5,18 +5,20 @@
|
|
5
5
|
<table>
|
6
6
|
<thead>
|
7
7
|
<tr>
|
8
|
-
<th>Email</th>
|
9
|
-
<th>User</th>
|
10
8
|
<th>Id</th>
|
9
|
+
<th>User</th>
|
10
|
+
<th>Email</th>
|
11
|
+
<th>Activated</th>
|
11
12
|
</tr>
|
12
13
|
<tbody>
|
13
14
|
<% RackWarden::User.all(:limit=>100).each do |user| %>
|
14
15
|
<tr>
|
15
|
-
<td><%=user.email%></td>
|
16
|
-
<td><%=user.username%></td>
|
17
16
|
<td><%=user.id%></td>
|
17
|
+
<td><%=user.username%></td>
|
18
|
+
<td><%=user.email%></td>
|
19
|
+
<td><%=user.activated_at%></td>
|
18
20
|
</tr>
|
19
21
|
<% end %>
|
20
22
|
</tbody>
|
21
23
|
</table>
|
22
|
-
</p>
|
24
|
+
</p>
|
@@ -3,7 +3,8 @@
|
|
3
3
|
</p>
|
4
4
|
|
5
5
|
<p>
|
6
|
-
|
7
|
-
<br
|
8
|
-
<%= DataMapper.repository.adapter.
|
9
|
-
</p>
|
6
|
+
<%#= DataMapper.repository.adapter.select('select * from SQLITE_MASTER').to_yaml.to_html %>
|
7
|
+
<%#= DataMapper.repository.adapter.to_yaml.gsub(/\n|\r/, '<br>') %>
|
8
|
+
<%= DataMapper.repository(settings.repository_name).adapter.options.dup.tap{|o| o.delete(:password); o.delete('password')}.to_yaml.to_html %>
|
9
|
+
</p>
|
10
|
+
<br>
|
@@ -0,0 +1 @@
|
|
1
|
+
<h2>Oops! We encountered an error</h2>
|
@@ -4,38 +4,32 @@
|
|
4
4
|
<title>Rack Warden</title>
|
5
5
|
|
6
6
|
<style>
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
body {
|
8
|
+
margin: 10px auto;
|
9
|
+
width: 800px;
|
10
|
+
}
|
11
11
|
</style>
|
12
12
|
|
13
13
|
<script src='https://www.google.com/recaptcha/api.js'></script>
|
14
14
|
</head>
|
15
15
|
<body>
|
16
|
+
<br>
|
16
17
|
<h1>Rack Warden</h1>
|
17
18
|
|
18
19
|
<p>
|
19
|
-
<a href="<%=url('/
|
20
|
-
<a href="<%=
|
21
|
-
|
22
|
-
<a href="<%=url('/auth/logout', false)%>">Log Out</a>
|
20
|
+
<a href="<%=url('/', false)%>">Main Site</a> |
|
21
|
+
<a href="<%=url_for('/protected')%>">Test Protected Page</a> |
|
22
|
+
<%= erb :'rw_account_widget.html', :layout=>false %>
|
23
23
|
</p>
|
24
24
|
|
25
|
-
|
26
|
-
<div style="color:green;">
|
27
|
-
<%= flash(:rwarden)[:success] %>
|
28
|
-
</div>
|
29
|
-
<% end %>
|
30
|
-
|
31
|
-
<% if flash(:rwarden)[:error] %>
|
32
|
-
<div style="color:red;">
|
33
|
-
<%= flash(:rwarden)[:error] %>
|
34
|
-
</div>
|
35
|
-
<% end %>
|
25
|
+
<%= erb :'rw_flash_widget.html', :layout=>false %>
|
36
26
|
|
37
27
|
<div id="content">
|
28
|
+
<br>
|
29
|
+
<br>
|
38
30
|
<%= yield if block_given? %>
|
31
|
+
<br>
|
32
|
+
<br>
|
39
33
|
</div>
|
40
34
|
</body>
|
41
35
|
</html>
|
@@ -1,12 +1,12 @@
|
|
1
1
|
<!-- A partial layout for admin. -->
|
2
2
|
<%# @section_title = "RackWarden Admin" %>
|
3
|
-
<h2>
|
3
|
+
<h2>Account Management</h2>
|
4
4
|
<p>
|
5
|
-
<a href="<%=
|
6
|
-
<a href="<%=
|
7
|
-
<a href="<%=
|
8
|
-
<a href="<%=
|
9
|
-
|
5
|
+
<a href="<%=url_for('/')%>">RackWarden Home</a> |
|
6
|
+
<a href="<%=url_for('/admin')%>">User Accounts</a> |
|
7
|
+
<a href="<%=url_for('/dbinfo')%>">Database Info</a> |
|
8
|
+
<a href="<%=url_for('/sessinfo')%>">Session Info</a> |
|
9
|
+
<%=account_widget%>
|
10
10
|
</p>
|
11
11
|
|
12
12
|
<br>
|
@@ -1,9 +1,22 @@
|
|
1
|
-
|
2
|
-
<form action="<%=
|
3
|
-
|
4
|
-
|
1
|
+
<h3>Login</h3>
|
2
|
+
<form action="<%=url_for('/login')%>" method="post" class="rw">
|
3
|
+
<style scoped="scoped">
|
4
|
+
.rw label {font-size: .95em; color: grey; display: block;}
|
5
|
+
.rw input {font-size: 1.15em; margin-bottom: 20px; padding:7px;}
|
6
|
+
</style>
|
7
|
+
|
8
|
+
<label for="user_username">Username or Email</label>
|
9
|
+
<input type="text" name="user[username]" id="user_username"/>
|
10
|
+
|
11
|
+
<label for="user_password">Password</label>
|
12
|
+
<input type="password" name="user[password]" id="user_password" />
|
13
|
+
|
14
|
+
<label for="user_remember_me">Remember me
|
15
|
+
<input name="user[remember_me]" type="checkbox" value="1" id="user_remember_me" />
|
16
|
+
</label>
|
17
|
+
|
5
18
|
<input type="submit" value="Log In" />
|
6
19
|
<% if settings.allow_public_signup %>
|
7
|
-
or <a href="<%=
|
20
|
+
or <a href="<%=url_for('/new')%>">Create a new account</a>
|
8
21
|
<% end %>
|
9
22
|
</form>
|