Froze rails gems
[depot.git] / vendor / rails / actionpack / lib / action_controller / verification.rb
1 module ActionController #:nodoc:
2 module Verification #:nodoc:
3 def self.included(base) #:nodoc:
4 base.extend(ClassMethods)
5 end
6
7 # This module provides a class-level method for specifying that certain
8 # actions are guarded against being called without certain prerequisites
9 # being met. This is essentially a special kind of before_filter.
10 #
11 # An action may be guarded against being invoked without certain request
12 # parameters being set, or without certain session values existing.
13 #
14 # When a verification is violated, values may be inserted into the flash, and
15 # a specified redirection is triggered. If no specific action is configured,
16 # verification failures will by default result in a 400 Bad Request response.
17 #
18 # Usage:
19 #
20 # class GlobalController < ActionController::Base
21 # # Prevent the #update_settings action from being invoked unless
22 # # the 'admin_privileges' request parameter exists. The
23 # # settings action will be redirected to in current controller
24 # # if verification fails.
25 # verify :params => "admin_privileges", :only => :update_post,
26 # :redirect_to => { :action => "settings" }
27 #
28 # # Disallow a post from being updated if there was no information
29 # # submitted with the post, and if there is no active post in the
30 # # session, and if there is no "note" key in the flash. The route
31 # # named category_url will be redirected to if verification fails.
32 #
33 # verify :params => "post", :session => "post", "flash" => "note",
34 # :only => :update_post,
35 # :add_flash => { "alert" => "Failed to create your message" },
36 # :redirect_to => :category_url
37 #
38 # Note that these prerequisites are not business rules. They do not examine
39 # the content of the session or the parameters. That level of validation should
40 # be encapsulated by your domain model or helper methods in the controller.
41 module ClassMethods
42 # Verify the given actions so that if certain prerequisites are not met,
43 # the user is redirected to a different action. The +options+ parameter
44 # is a hash consisting of the following key/value pairs:
45 #
46 # <tt>:params</tt>::
47 # a single key or an array of keys that must be in the <tt>params</tt>
48 # hash in order for the action(s) to be safely called.
49 # <tt>:session</tt>::
50 # a single key or an array of keys that must be in the <tt>session</tt>
51 # in order for the action(s) to be safely called.
52 # <tt>:flash</tt>::
53 # a single key or an array of keys that must be in the flash in order
54 # for the action(s) to be safely called.
55 # <tt>:method</tt>::
56 # a single key or an array of keys--any one of which must match the
57 # current request method in order for the action(s) to be safely called.
58 # (The key should be a symbol: <tt>:get</tt> or <tt>:post</tt>, for
59 # example.)
60 # <tt>:xhr</tt>::
61 # true/false option to ensure that the request is coming from an Ajax
62 # call or not.
63 # <tt>:add_flash</tt>::
64 # a hash of name/value pairs that should be merged into the session's
65 # flash if the prerequisites cannot be satisfied.
66 # <tt>:add_headers</tt>::
67 # a hash of name/value pairs that should be merged into the response's
68 # headers hash if the prerequisites cannot be satisfied.
69 # <tt>:redirect_to</tt>::
70 # the redirection parameters to be used when redirecting if the
71 # prerequisites cannot be satisfied. You can redirect either to named
72 # route or to the action in some controller.
73 # <tt>:render</tt>::
74 # the render parameters to be used when the prerequisites cannot be satisfied.
75 # <tt>:only</tt>::
76 # only apply this verification to the actions specified in the associated
77 # array (may also be a single value).
78 # <tt>:except</tt>::
79 # do not apply this verification to the actions specified in the associated
80 # array (may also be a single value).
81 def verify(options={})
82 before_filter :only => options[:only], :except => options[:except] do |c|
83 c.__send__ :verify_action, options
84 end
85 end
86 end
87
88 private
89
90 def verify_action(options) #:nodoc:
91 if prereqs_invalid?(options)
92 flash.update(options[:add_flash]) if options[:add_flash]
93 response.headers.update(options[:add_headers]) if options[:add_headers]
94 apply_remaining_actions(options) unless performed?
95 end
96 end
97
98 def prereqs_invalid?(options) # :nodoc:
99 verify_presence_of_keys_in_hash_flash_or_params(options) ||
100 verify_method(options) ||
101 verify_request_xhr_status(options)
102 end
103
104 def verify_presence_of_keys_in_hash_flash_or_params(options) # :nodoc:
105 [*options[:params] ].find { |v| params[v].nil? } ||
106 [*options[:session]].find { |v| session[v].nil? } ||
107 [*options[:flash] ].find { |v| flash[v].nil? }
108 end
109
110 def verify_method(options) # :nodoc:
111 [*options[:method]].all? { |v| request.method != v.to_sym } if options[:method]
112 end
113
114 def verify_request_xhr_status(options) # :nodoc:
115 request.xhr? != options[:xhr] unless options[:xhr].nil?
116 end
117
118 def apply_redirect_to(redirect_to_option) # :nodoc:
119 (redirect_to_option.is_a?(Symbol) && redirect_to_option != :back) ? self.__send__(redirect_to_option) : redirect_to_option
120 end
121
122 def apply_remaining_actions(options) # :nodoc:
123 case
124 when options[:render] ; render(options[:render])
125 when options[:redirect_to] ; redirect_to(apply_redirect_to(options[:redirect_to]))
126 else head(:bad_request)
127 end
128 end
129 end
130 end