padrino-core 0.10.7 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/lib/padrino-core.rb +58 -4
  3. data/lib/padrino-core/application.rb +38 -16
  4. data/lib/padrino-core/application/flash.rb +229 -0
  5. data/lib/padrino-core/application/rendering.rb +39 -11
  6. data/lib/padrino-core/application/rendering/extensions/erubis.rb +55 -0
  7. data/lib/padrino-core/application/rendering/extensions/haml.rb +26 -0
  8. data/lib/padrino-core/application/rendering/extensions/slim.rb +14 -0
  9. data/lib/padrino-core/application/routing.rb +106 -35
  10. data/lib/padrino-core/cli/base.rb +41 -38
  11. data/lib/padrino-core/cli/rake.rb +30 -9
  12. data/lib/padrino-core/cli/rake_tasks.rb +9 -14
  13. data/lib/padrino-core/loader.rb +23 -9
  14. data/lib/padrino-core/locale/fr.yml +1 -1
  15. data/lib/padrino-core/locale/ru.yml +1 -1
  16. data/lib/padrino-core/logger.rb +48 -32
  17. data/lib/padrino-core/module.rb +58 -0
  18. data/lib/padrino-core/mounter.rb +15 -5
  19. data/lib/padrino-core/reloader.rb +14 -12
  20. data/lib/padrino-core/server.rb +4 -4
  21. data/lib/padrino-core/support_lite.rb +43 -6
  22. data/lib/padrino-core/version.rb +1 -1
  23. data/padrino-core.gemspec +9 -4
  24. data/test/fixtures/app_gem/Gemfile +4 -0
  25. data/test/fixtures/app_gem/app/app.rb +3 -0
  26. data/test/fixtures/app_gem/app_gem.gemspec +17 -0
  27. data/test/fixtures/app_gem/lib/app_gem.rb +7 -0
  28. data/test/fixtures/app_gem/lib/app_gem/version.rb +3 -0
  29. data/test/mini_shoulda.rb +1 -1
  30. data/test/test_application.rb +38 -21
  31. data/test/test_csrf_protection.rb +80 -0
  32. data/test/test_filters.rb +70 -0
  33. data/test/test_flash.rb +168 -0
  34. data/test/test_logger.rb +27 -0
  35. data/test/test_mounter.rb +24 -2
  36. data/test/test_reloader_simple.rb +4 -4
  37. data/test/test_rendering.rb +75 -4
  38. data/test/test_routing.rb +164 -35
  39. data/test/test_support_lite.rb +56 -0
  40. metadata +52 -29
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9f915e954014b964f9d5afccd9999d80cd888c05
4
+ data.tar.gz: 0f64be604ae666519fdd77d32413f9bdf4c32986
5
+ SHA512:
6
+ metadata.gz: f5b45a55ece397aabf5c7e9d4c961a51edeaa882156962222a0b41d718e62c000fa301f954236fa1599d94e8f2e19109e538b775a2c651c94dfefabf6f187073
7
+ data.tar.gz: 7796c665daf7a323174e265e3fbc23d71cef98cc9ae1427cb0d5a3d18a3352fdd861fab8adb83308b01c6f4e2f7b1e3bd6ab372493b6032c43f41431dabbb15e
data/lib/padrino-core.rb CHANGED
@@ -1,8 +1,19 @@
1
1
  require 'sinatra/base'
2
- require 'padrino-core/support_lite' unless defined?(SupportLite)
2
+ require 'padrino-core/version'
3
+ require 'padrino-core/support_lite'
4
+ require 'padrino-core/application'
5
+
6
+ require 'padrino-core/caller'
7
+ require 'padrino-core/command'
8
+ require 'padrino-core/loader'
9
+ require 'padrino-core/logger'
10
+ require 'padrino-core/mounter'
11
+ require 'padrino-core/reloader'
12
+ require 'padrino-core/router'
13
+ require 'padrino-core/server'
14
+ require 'padrino-core/tasks'
15
+ require 'padrino-core/module'
3
16
 
4
- FileSet.glob_require('padrino-core/application/*.rb', __FILE__)
5
- FileSet.glob_require('padrino-core/*.rb', __FILE__)
6
17
 
7
18
  # The Padrino environment (falls back to the rack env or finally develop)
8
19
  PADRINO_ENV = ENV["PADRINO_ENV"] ||= ENV["RACK_ENV"] ||= "development" unless defined?(PADRINO_ENV)
@@ -80,7 +91,14 @@ module Padrino
80
91
  # end
81
92
  #
82
93
  def configure_apps(&block)
83
- @_global_configuration = block if block_given?
94
+ return unless block_given?
95
+ @@_global_configurations ||= []
96
+ @@_global_configurations << block
97
+ @_global_configuration = lambda do |app|
98
+ @@_global_configurations.each do |configuration|
99
+ app.class_eval(&configuration)
100
+ end
101
+ end
84
102
  end
85
103
 
86
104
  ##
@@ -148,5 +166,41 @@ module Padrino
148
166
  def use(m, *args, &block)
149
167
  middleware << [m, args, block]
150
168
  end
169
+
170
+ ##
171
+ # Registers a gem with padrino. This relieves the caller from setting up
172
+ # loadpaths by himself and enables Padrino to look up apps in gem folder.
173
+ #
174
+ # The name given has to be the proper gem name as given in the gemspec.
175
+ #
176
+ # @param [String] name
177
+ # The name of the gem being registered.
178
+ #
179
+ # @param [Module] main_module
180
+ # The main module of the gem.
181
+ #
182
+ # @returns The root path of the loaded gem
183
+ def gem(name, main_module)
184
+ _,spec = Gem.loaded_specs.find { |spec_name, spec| spec_name == name }
185
+ gems << spec
186
+ modules << main_module
187
+ spec.full_gem_path
188
+ end
189
+
190
+ ##
191
+ # Returns all currently known padrino gems.
192
+ #
193
+ # @returns [Gem::Specification]
194
+ def gems
195
+ @gems ||= []
196
+ end
197
+
198
+ ##
199
+ # All loaded Padrino modules.
200
+ #
201
+ # @returns [<Padrino::Module>]
202
+ def modules
203
+ @modules ||= []
204
+ end
151
205
  end # self
152
206
  end # Padrino
@@ -1,3 +1,8 @@
1
+ require 'padrino-core/application/rendering'
2
+ require 'padrino-core/application/routing'
3
+ require 'padrino-core/application/flash'
4
+ require 'padrino-core/application/showexceptions'
5
+
1
6
  module Padrino
2
7
  class ApplicationSetupError < RuntimeError # @private
3
8
  end
@@ -173,17 +178,21 @@ module Padrino
173
178
  set :method_override, true
174
179
  set :sessions, false
175
180
  set :public_folder, Proc.new { Padrino.root('public', uri_root) }
176
- set :views, Proc.new { File.join(root, "views") }
177
- set :images_path, Proc.new { File.join(public, "images") }
178
- set :protection, false
181
+ set :views, Proc.new { File.join(root, 'views') }
182
+ set :images_path, Proc.new { File.join(public_folder, 'images') }
183
+ set :protection, true
184
+ # Haml specific
185
+ set :haml, { :ugly => (Padrino.env == :production) } if defined?(Haml)
179
186
  # Padrino specific
180
187
  set :uri_root, '/'
181
188
  set :app_name, settings.to_s.underscore.to_sym
182
189
  set :default_builder, 'StandardFormBuilder'
183
- set :flash, defined?(Sinatra::Flash) || defined?(Rack::Flash)
184
190
  set :authentication, false
185
191
  # Padrino locale
186
192
  set :locale_path, Proc.new { Dir[File.join(settings.root, '/locale/**/*.{rb,yml}')] }
193
+ # Authenticity token
194
+ set :protect_from_csrf, false
195
+ set :allow_disabled_csrf, false
187
196
  # Load the Global Configurations
188
197
  class_eval(&Padrino.apps_configuration) if Padrino.apps_configuration
189
198
  end
@@ -241,27 +250,40 @@ module Padrino
241
250
  # Also initializes the application after setting up the middleware
242
251
  def setup_default_middleware(builder)
243
252
  setup_sessions builder
244
- setup_flash builder
245
253
  builder.use Padrino::ShowExceptions if show_exceptions?
246
254
  builder.use Padrino::Logger::Rack, uri_root if Padrino.logger && logging?
247
255
  builder.use Padrino::Reloader::Rack if reload?
248
256
  builder.use Rack::MethodOverride if method_override?
249
257
  builder.use Rack::Head
258
+ register Padrino::Flash
250
259
  setup_protection builder
260
+ setup_csrf_protection builder
251
261
  setup_application!
252
262
  end
253
263
 
254
- # TODO Remove this in a few versions (rack-flash deprecation)
255
- # Move register Sinatra::Flash into setup_default_middleware
256
- # Initializes flash using sinatra-flash or rack-flash
257
- def setup_flash(builder)
258
- register Sinatra::Flash if flash? && defined?(Sinatra::Flash)
259
- if defined?(Rack::Flash) && !defined?(Sinatra::Flash)
260
- logger.warn %Q{
261
- [Deprecation] In Gemfile, 'rack-flash' should be replaced with 'sinatra-flash'!
262
- Rack-Flash is not compatible with later versions of Rack and should be replaced.
263
- }
264
- builder.use Rack::Flash, :sweep => true if flash?
264
+ # sets up csrf protection for the app
265
+ def setup_csrf_protection(builder)
266
+ if protect_from_csrf? && !sessions?
267
+ raise(<<-ERROR)
268
+ `protect_from_csrf` is activated, but `sessions` are not. To enable csrf
269
+ protection, use:
270
+
271
+ enable :sessions
272
+
273
+ or deactivate protect_from_csrf:
274
+
275
+ disable :protect_from_csrf
276
+ ERROR
277
+ end
278
+
279
+ if protect_from_csrf?
280
+ if allow_disabled_csrf?
281
+ builder.use Rack::Protection::AuthenticityToken,
282
+ :reaction => :report,
283
+ :report_key => 'protection.csrf.failed'
284
+ else
285
+ builder.use Rack::Protection::AuthenticityToken
286
+ end
265
287
  end
266
288
  end
267
289
  end # self
@@ -0,0 +1,229 @@
1
+ module Padrino
2
+ module Flash
3
+
4
+ class << self
5
+ # @private
6
+ def registered(app)
7
+ app.helpers Helpers
8
+ app.after do
9
+ session[:_flash] = @_flash.next if @_flash
10
+ end
11
+ end
12
+ end # self
13
+
14
+ class Storage
15
+ include Enumerable
16
+
17
+ # @private
18
+ def initialize(session=nil)
19
+ @_now = session || {}
20
+ @_next = {}
21
+ end
22
+
23
+ def now
24
+ @_now
25
+ end
26
+
27
+ def next
28
+ @_next
29
+ end
30
+
31
+ # @since 0.10.8
32
+ # @api public
33
+ def [](type)
34
+ @_now[type]
35
+ end
36
+
37
+ # @since 0.10.8
38
+ # @api public
39
+ def []=(type, message)
40
+ @_next[type] = message
41
+ end
42
+
43
+ # @since 0.10.8
44
+ # @api public
45
+ def delete(type)
46
+ @_now.delete(type)
47
+ self
48
+ end
49
+
50
+ # @since 0.10.8
51
+ # @api public
52
+ def keys
53
+ @_now.keys
54
+ end
55
+
56
+ # @since 0.10.8
57
+ # @api public
58
+ def key?(type)
59
+ @_now.key?(type)
60
+ end
61
+
62
+ # @since 0.10.8
63
+ # @api public
64
+ def each(&block)
65
+ @_now.each(&block)
66
+ end
67
+
68
+ # @since 0.10.8
69
+ # @api public
70
+ def replace(hash)
71
+ @_now.replace(hash)
72
+ self
73
+ end
74
+
75
+ # @since 0.10.8
76
+ # @api public
77
+ def update(hash)
78
+ @_now.update(hash)
79
+ self
80
+ end
81
+ alias_method :merge!, :update
82
+
83
+ # @since 0.10.8
84
+ # @api public
85
+ def sweep
86
+ @_now.replace(@_next)
87
+ @_next = {}
88
+ self
89
+ end
90
+
91
+ # @since 0.10.8
92
+ # @api public
93
+ def keep(key = nil)
94
+ if key
95
+ @_next[key] = @_now[key]
96
+ else
97
+ @_next.merge!(@_now)
98
+ end
99
+ self
100
+ end
101
+
102
+ # @since 0.10.8
103
+ # @api public
104
+ def discard(key = nil)
105
+ if key
106
+ @_next.delete(key)
107
+ else
108
+ @_next = {}
109
+ end
110
+ self
111
+ end
112
+
113
+ # @since 0.10.8
114
+ # @api public
115
+ def clear
116
+ @_now.clear
117
+ end
118
+
119
+ # @since 0.10.8
120
+ # @api public
121
+ def empty?
122
+ @_now.empty?
123
+ end
124
+
125
+ # @since 0.10.8
126
+ # @api public
127
+ def to_hash
128
+ @_now.dup
129
+ end
130
+
131
+ def length
132
+ @_now.length
133
+ end
134
+ alias_method :size, :length
135
+
136
+ # @since 0.10.8
137
+ # @api public
138
+ def to_s
139
+ @_now.to_s
140
+ end
141
+
142
+ # @since 0.10.8
143
+ # @api public
144
+ def error=(message)
145
+ self[:error] = message
146
+ end
147
+
148
+ # @since 0.10.8
149
+ # @api public
150
+ def error
151
+ self[:error]
152
+ end
153
+
154
+ # @since 0.10.8
155
+ # @api public
156
+ def notice=(message)
157
+ self[:notice] = message
158
+ end
159
+
160
+ # @since 0.10.8
161
+ # @api public
162
+ def notice
163
+ self[:notice]
164
+ end
165
+
166
+ # @since 0.10.8
167
+ # @api public
168
+ def success=(message)
169
+ self[:success] = message
170
+ end
171
+
172
+ # @since 0.10.8
173
+ # @api public
174
+ def success
175
+ self[:success]
176
+ end
177
+ end # Storage
178
+
179
+ module Helpers
180
+ ###
181
+ # Overloads the existing redirect helper in-order to provide support for flash messages
182
+ #
183
+ # @overload redirect(url)
184
+ # @param [String] url
185
+ #
186
+ # @overload redirect(url, status_code)
187
+ # @param [String] url
188
+ # @param [Fixnum] status_code
189
+ #
190
+ # @overload redirect(url, status_code, flash_messages)
191
+ # @param [String] url
192
+ # @param [Fixnum] status_code
193
+ # @param [Hash] flash_messages
194
+ #
195
+ # @overload redirect(url, flash_messages)
196
+ # @param [String] url
197
+ # @param [Hash] flash_messages
198
+ #
199
+ # @example
200
+ # redirect(dashboard, success: :user_created)
201
+ # redirect(new_location, 301, notice: 'This page has moved. Please update your bookmarks!!')
202
+ #
203
+ # @since 0.10.8
204
+ # @api public
205
+ def redirect(url, *args)
206
+ flashes = args.extract_options!
207
+
208
+ flashes.each do |type, message|
209
+ message = I18n.translate(message) if message.is_a?(Symbol) && defined?(I18n)
210
+ flash[type] = message
211
+ end
212
+
213
+ super(url, args)
214
+ end
215
+ alias_method :redirect_to, :redirect
216
+
217
+ ###
218
+ # Returns the flash storage object
219
+ #
220
+ # @return [Storage]
221
+ #
222
+ # @since 0.10.8
223
+ # @api public
224
+ def flash
225
+ @_flash ||= Storage.new(env['rack.session'] ? session[:_flash] : {})
226
+ end
227
+ end # Helpers
228
+ end # Flash
229
+ end # Padrino
@@ -7,6 +7,16 @@ module Padrino
7
7
  # locale enabled rendering, among other features.
8
8
  #
9
9
  module Rendering
10
+ ##
11
+ # A SafeTemplate assumes that its output is safe.
12
+ #
13
+ # @api private
14
+ module SafeTemplate
15
+ def render(*)
16
+ super.html_safe
17
+ end
18
+ end
19
+
10
20
  ##
11
21
  # Exception responsible for when an expected template did not exist.
12
22
  #
@@ -25,19 +35,34 @@ module Padrino
25
35
  ] unless defined?(IGNORE_FILE_PATTERN)
26
36
 
27
37
  ##
28
- # Default rendering options used in the #render-method.
38
+ # Default options used in the #resolve_template-method.
29
39
  #
30
40
  DEFAULT_RENDERING_OPTIONS = { :strict_format => false, :raise_exceptions => true } unless defined?(DEFAULT_RENDERING_OPTIONS)
31
41
 
32
42
  class << self
43
+ ##
44
+ # Default engine configurations for Padrino::Rendering
45
+ #
46
+ # @return {Hash<Symbol,Hash>}
47
+ # The configurations, keyed by engine.
48
+ def engine_configurations
49
+ @engine_configurations ||= {}
50
+ end
51
+
33
52
  ##
34
53
  # Main class that register this extension.
35
54
  #
36
55
  def registered(app)
37
- app.send(:include, InstanceMethods)
38
- app.extend(ClassMethods)
56
+ included(app)
57
+ engine_configurations.each do |engine, configs|
58
+ app.set engine, configs
59
+ end
60
+ end
61
+
62
+ def included(base)
63
+ base.send(:include, InstanceMethods)
64
+ base.extend(ClassMethods)
39
65
  end
40
- alias :included :registered
41
66
  end
42
67
 
43
68
  ##
@@ -152,11 +177,8 @@ module Padrino
152
177
  # * Use render 'path/to/template.haml' (with explicit engine lookup)
153
178
  # * Use render 'path/to/template', :layout => false
154
179
  # * Use render 'path/to/template', :layout => false, :engine => 'haml'
155
- # * Use render { :a => 1, :b => 2, :c => 3 } # => return a json string
156
180
  #
157
181
  def render(engine, data=nil, options={}, locals={}, &block)
158
- # If engine is a hash then render data converted to json
159
- content_type(:json, :charset => 'utf-8') and return engine.to_json if engine.is_a?(Hash)
160
182
 
161
183
  # If engine is nil, ignore engine parameter and shift up all arguments
162
184
  # render nil, "index", { :layout => true }, { :localvar => "foo" }
@@ -175,10 +197,10 @@ module Padrino
175
197
  root = settings.respond_to?(:root) ? settings.root : ""
176
198
 
177
199
  # Use @layout if it exists
178
- options[:layout] = @layout if options[:layout].nil?
179
-
200
+ layout_was = options[:layout]
201
+ options[:layout] = @layout if options[:layout].nil? || options[:layout] == true
180
202
  # Resolve layouts similar to in Rails
181
- if (options[:layout].nil? || options[:layout] == true) && !settings.templates.has_key?(:layout)
203
+ if options[:layout].nil? && !settings.templates.has_key?(:layout)
182
204
  layout_path, layout_engine = *resolved_layout
183
205
  options[:layout] = layout_path || false # We need to force layout false so sinatra don't try to render it
184
206
  options[:layout] = false unless layout_engine == engine # TODO allow different layout engine
@@ -186,10 +208,12 @@ module Padrino
186
208
  elsif options[:layout].present?
187
209
  options[:layout] = settings.fetch_layout_path(options[:layout] || @layout)
188
210
  end
211
+ # Default to original layout value if none found
212
+ options[:layout] ||= layout_was
189
213
 
190
214
  # Cleanup the template
191
215
  @current_engine, engine_was = engine, @current_engine
192
- @_out_buf, _buf_was = "", @_out_buf
216
+ @_out_buf, _buf_was = ActiveSupport::SafeBuffer.new, @_out_buf
193
217
 
194
218
  # Pass arguments to Sinatra render method
195
219
  super(engine, data, options.dup, locals, &block)
@@ -290,3 +314,7 @@ module Padrino
290
314
  end # InstanceMethods
291
315
  end # Rendering
292
316
  end # Padrino
317
+
318
+ require 'padrino-core/application/rendering/extensions/haml'
319
+ require 'padrino-core/application/rendering/extensions/erubis'
320
+ require 'padrino-core/application/rendering/extensions/slim'