##// END OF EJS Templates
Make the sudo timeout configurable (#19851)....
Jean-Philippe Lang -
r13971:b895f6434ddd
parent child
Show More
@@ -1,220 +1,221
1 # = Redmine configuration file
1 # = Redmine configuration file
2 #
2 #
3 # Each environment has it's own configuration options. If you are only
3 # Each environment has it's own configuration options. If you are only
4 # running in production, only the production block needs to be configured.
4 # running in production, only the production block needs to be configured.
5 # Environment specific configuration options override the default ones.
5 # Environment specific configuration options override the default ones.
6 #
6 #
7 # Note that this file needs to be a valid YAML file.
7 # Note that this file needs to be a valid YAML file.
8 # DO NOT USE TABS! Use 2 spaces instead of tabs for identation.
8 # DO NOT USE TABS! Use 2 spaces instead of tabs for identation.
9
9
10 # default configuration options for all environments
10 # default configuration options for all environments
11 default:
11 default:
12 # Outgoing emails configuration
12 # Outgoing emails configuration
13 # See the examples below and the Rails guide for more configuration options:
13 # See the examples below and the Rails guide for more configuration options:
14 # http://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration
14 # http://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration
15 email_delivery:
15 email_delivery:
16
16
17 # ==== Simple SMTP server at localhost
17 # ==== Simple SMTP server at localhost
18 #
18 #
19 # email_delivery:
19 # email_delivery:
20 # delivery_method: :smtp
20 # delivery_method: :smtp
21 # smtp_settings:
21 # smtp_settings:
22 # address: "localhost"
22 # address: "localhost"
23 # port: 25
23 # port: 25
24 #
24 #
25 # ==== SMTP server at example.com using LOGIN authentication and checking HELO for foo.com
25 # ==== SMTP server at example.com using LOGIN authentication and checking HELO for foo.com
26 #
26 #
27 # email_delivery:
27 # email_delivery:
28 # delivery_method: :smtp
28 # delivery_method: :smtp
29 # smtp_settings:
29 # smtp_settings:
30 # address: "example.com"
30 # address: "example.com"
31 # port: 25
31 # port: 25
32 # authentication: :login
32 # authentication: :login
33 # domain: 'foo.com'
33 # domain: 'foo.com'
34 # user_name: 'myaccount'
34 # user_name: 'myaccount'
35 # password: 'password'
35 # password: 'password'
36 #
36 #
37 # ==== SMTP server at example.com using PLAIN authentication
37 # ==== SMTP server at example.com using PLAIN authentication
38 #
38 #
39 # email_delivery:
39 # email_delivery:
40 # delivery_method: :smtp
40 # delivery_method: :smtp
41 # smtp_settings:
41 # smtp_settings:
42 # address: "example.com"
42 # address: "example.com"
43 # port: 25
43 # port: 25
44 # authentication: :plain
44 # authentication: :plain
45 # domain: 'example.com'
45 # domain: 'example.com'
46 # user_name: 'myaccount'
46 # user_name: 'myaccount'
47 # password: 'password'
47 # password: 'password'
48 #
48 #
49 # ==== SMTP server at using TLS (GMail)
49 # ==== SMTP server at using TLS (GMail)
50 # This might require some additional configuration. See the guides at:
50 # This might require some additional configuration. See the guides at:
51 # http://www.redmine.org/projects/redmine/wiki/EmailConfiguration
51 # http://www.redmine.org/projects/redmine/wiki/EmailConfiguration
52 #
52 #
53 # email_delivery:
53 # email_delivery:
54 # delivery_method: :smtp
54 # delivery_method: :smtp
55 # smtp_settings:
55 # smtp_settings:
56 # enable_starttls_auto: true
56 # enable_starttls_auto: true
57 # address: "smtp.gmail.com"
57 # address: "smtp.gmail.com"
58 # port: 587
58 # port: 587
59 # domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps
59 # domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps
60 # authentication: :plain
60 # authentication: :plain
61 # user_name: "your_email@gmail.com"
61 # user_name: "your_email@gmail.com"
62 # password: "your_password"
62 # password: "your_password"
63 #
63 #
64 # ==== Sendmail command
64 # ==== Sendmail command
65 #
65 #
66 # email_delivery:
66 # email_delivery:
67 # delivery_method: :sendmail
67 # delivery_method: :sendmail
68
68
69 # Absolute path to the directory where attachments are stored.
69 # Absolute path to the directory where attachments are stored.
70 # The default is the 'files' directory in your Redmine instance.
70 # The default is the 'files' directory in your Redmine instance.
71 # Your Redmine instance needs to have write permission on this
71 # Your Redmine instance needs to have write permission on this
72 # directory.
72 # directory.
73 # Examples:
73 # Examples:
74 # attachments_storage_path: /var/redmine/files
74 # attachments_storage_path: /var/redmine/files
75 # attachments_storage_path: D:/redmine/files
75 # attachments_storage_path: D:/redmine/files
76 attachments_storage_path:
76 attachments_storage_path:
77
77
78 # Configuration of the autologin cookie.
78 # Configuration of the autologin cookie.
79 # autologin_cookie_name: the name of the cookie (default: autologin)
79 # autologin_cookie_name: the name of the cookie (default: autologin)
80 # autologin_cookie_path: the cookie path (default: /)
80 # autologin_cookie_path: the cookie path (default: /)
81 # autologin_cookie_secure: true sets the cookie secure flag (default: false)
81 # autologin_cookie_secure: true sets the cookie secure flag (default: false)
82 autologin_cookie_name:
82 autologin_cookie_name:
83 autologin_cookie_path:
83 autologin_cookie_path:
84 autologin_cookie_secure:
84 autologin_cookie_secure:
85
85
86 # Configuration of SCM executable command.
86 # Configuration of SCM executable command.
87 #
87 #
88 # Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe)
88 # Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe)
89 # On Windows + CRuby, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work.
89 # On Windows + CRuby, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work.
90 #
90 #
91 # On Windows + JRuby 1.6.2, path which contains spaces does not work.
91 # On Windows + JRuby 1.6.2, path which contains spaces does not work.
92 # For example, "C:\Program Files\TortoiseHg\hg.exe".
92 # For example, "C:\Program Files\TortoiseHg\hg.exe".
93 # If you want to this feature, you need to install to the path which does not contains spaces.
93 # If you want to this feature, you need to install to the path which does not contains spaces.
94 # For example, "C:\TortoiseHg\hg.exe".
94 # For example, "C:\TortoiseHg\hg.exe".
95 #
95 #
96 # Examples:
96 # Examples:
97 # scm_subversion_command: svn # (default: svn)
97 # scm_subversion_command: svn # (default: svn)
98 # scm_mercurial_command: C:\Program Files\TortoiseHg\hg.exe # (default: hg)
98 # scm_mercurial_command: C:\Program Files\TortoiseHg\hg.exe # (default: hg)
99 # scm_git_command: /usr/local/bin/git # (default: git)
99 # scm_git_command: /usr/local/bin/git # (default: git)
100 # scm_cvs_command: cvs # (default: cvs)
100 # scm_cvs_command: cvs # (default: cvs)
101 # scm_bazaar_command: bzr.exe # (default: bzr)
101 # scm_bazaar_command: bzr.exe # (default: bzr)
102 # scm_darcs_command: darcs-1.0.9-i386-linux # (default: darcs)
102 # scm_darcs_command: darcs-1.0.9-i386-linux # (default: darcs)
103 #
103 #
104 scm_subversion_command:
104 scm_subversion_command:
105 scm_mercurial_command:
105 scm_mercurial_command:
106 scm_git_command:
106 scm_git_command:
107 scm_cvs_command:
107 scm_cvs_command:
108 scm_bazaar_command:
108 scm_bazaar_command:
109 scm_darcs_command:
109 scm_darcs_command:
110
110
111 # SCM paths validation.
111 # SCM paths validation.
112 #
112 #
113 # You can configure a regular expression for each SCM that will be used to
113 # You can configure a regular expression for each SCM that will be used to
114 # validate the path of new repositories (eg. path entered by users with the
114 # validate the path of new repositories (eg. path entered by users with the
115 # "Manage repositories" permission and path returned by reposman.rb).
115 # "Manage repositories" permission and path returned by reposman.rb).
116 # The regexp will be wrapped with \A \z, so it must match the whole path.
116 # The regexp will be wrapped with \A \z, so it must match the whole path.
117 # And the regexp is case sensitive.
117 # And the regexp is case sensitive.
118 #
118 #
119 # You can match the project identifier by using %project% in the regexp.
119 # You can match the project identifier by using %project% in the regexp.
120 #
120 #
121 # You can also set a custom hint message for each SCM that will be displayed
121 # You can also set a custom hint message for each SCM that will be displayed
122 # on the repository form instead of the default one.
122 # on the repository form instead of the default one.
123 #
123 #
124 # Examples:
124 # Examples:
125 # scm_subversion_path_regexp: file:///svnpath/[a-z0-9_]+
125 # scm_subversion_path_regexp: file:///svnpath/[a-z0-9_]+
126 # scm_subversion_path_info: SVN URL (eg. file:///svnpath/foo)
126 # scm_subversion_path_info: SVN URL (eg. file:///svnpath/foo)
127 #
127 #
128 # scm_git_path_regexp: /gitpath/%project%(\.[a-z0-9_])?/
128 # scm_git_path_regexp: /gitpath/%project%(\.[a-z0-9_])?/
129 #
129 #
130 scm_subversion_path_regexp:
130 scm_subversion_path_regexp:
131 scm_mercurial_path_regexp:
131 scm_mercurial_path_regexp:
132 scm_git_path_regexp:
132 scm_git_path_regexp:
133 scm_cvs_path_regexp:
133 scm_cvs_path_regexp:
134 scm_bazaar_path_regexp:
134 scm_bazaar_path_regexp:
135 scm_darcs_path_regexp:
135 scm_darcs_path_regexp:
136 scm_filesystem_path_regexp:
136 scm_filesystem_path_regexp:
137
137
138 # Absolute path to the SCM commands errors (stderr) log file.
138 # Absolute path to the SCM commands errors (stderr) log file.
139 # The default is to log in the 'log' directory of your Redmine instance.
139 # The default is to log in the 'log' directory of your Redmine instance.
140 # Example:
140 # Example:
141 # scm_stderr_log_file: /var/log/redmine_scm_stderr.log
141 # scm_stderr_log_file: /var/log/redmine_scm_stderr.log
142 scm_stderr_log_file:
142 scm_stderr_log_file:
143
143
144 # Key used to encrypt sensitive data in the database (SCM and LDAP passwords).
144 # Key used to encrypt sensitive data in the database (SCM and LDAP passwords).
145 # If you don't want to enable data encryption, just leave it blank.
145 # If you don't want to enable data encryption, just leave it blank.
146 # WARNING: losing/changing this key will make encrypted data unreadable.
146 # WARNING: losing/changing this key will make encrypted data unreadable.
147 #
147 #
148 # If you want to encrypt existing passwords in your database:
148 # If you want to encrypt existing passwords in your database:
149 # * set the cipher key here in your configuration file
149 # * set the cipher key here in your configuration file
150 # * encrypt data using 'rake db:encrypt RAILS_ENV=production'
150 # * encrypt data using 'rake db:encrypt RAILS_ENV=production'
151 #
151 #
152 # If you have encrypted data and want to change this key, you have to:
152 # If you have encrypted data and want to change this key, you have to:
153 # * decrypt data using 'rake db:decrypt RAILS_ENV=production' first
153 # * decrypt data using 'rake db:decrypt RAILS_ENV=production' first
154 # * change the cipher key here in your configuration file
154 # * change the cipher key here in your configuration file
155 # * encrypt data using 'rake db:encrypt RAILS_ENV=production'
155 # * encrypt data using 'rake db:encrypt RAILS_ENV=production'
156 database_cipher_key:
156 database_cipher_key:
157
157
158 # Set this to false to disable plugins' assets mirroring on startup.
158 # Set this to false to disable plugins' assets mirroring on startup.
159 # You can use `rake redmine:plugins:assets` to manually mirror assets
159 # You can use `rake redmine:plugins:assets` to manually mirror assets
160 # to public/plugin_assets when you install/upgrade a Redmine plugin.
160 # to public/plugin_assets when you install/upgrade a Redmine plugin.
161 #
161 #
162 #mirror_plugins_assets_on_startup: false
162 #mirror_plugins_assets_on_startup: false
163
163
164 # Your secret key for verifying cookie session data integrity. If you
164 # Your secret key for verifying cookie session data integrity. If you
165 # change this key, all old sessions will become invalid! Make sure the
165 # change this key, all old sessions will become invalid! Make sure the
166 # secret is at least 30 characters and all random, no regular words or
166 # secret is at least 30 characters and all random, no regular words or
167 # you'll be exposed to dictionary attacks.
167 # you'll be exposed to dictionary attacks.
168 #
168 #
169 # If you have a load-balancing Redmine cluster, you have to use the
169 # If you have a load-balancing Redmine cluster, you have to use the
170 # same secret token on each machine.
170 # same secret token on each machine.
171 #secret_token: 'change it to a long random string'
171 #secret_token: 'change it to a long random string'
172
172
173 # Requires users to re-enter their password for sensitive actions (editing
173 # Requires users to re-enter their password for sensitive actions (editing
174 # of account data, project memberships, application settings, user, group,
174 # of account data, project memberships, application settings, user, group,
175 # role, auth source management and project deletion).
175 # role, auth source management and project deletion). Disabled by default.
176 # Disabled by default.
176 # Timeout is set in minutes.
177 #
177 #
178 #sudo_mode: true
178 #sudo_mode: true
179 #sudo_mode_timeout: 15
179
180
180 # Absolute path (e.g. /usr/bin/convert, c:/im/convert.exe) to
181 # Absolute path (e.g. /usr/bin/convert, c:/im/convert.exe) to
181 # the ImageMagick's `convert` binary. Used to generate attachment thumbnails.
182 # the ImageMagick's `convert` binary. Used to generate attachment thumbnails.
182 #imagemagick_convert_command:
183 #imagemagick_convert_command:
183
184
184 # Configuration of RMagcik font.
185 # Configuration of RMagcik font.
185 #
186 #
186 # Redmine uses RMagcik in order to export gantt png.
187 # Redmine uses RMagcik in order to export gantt png.
187 # You don't need this setting if you don't install RMagcik.
188 # You don't need this setting if you don't install RMagcik.
188 #
189 #
189 # In CJK (Chinese, Japanese and Korean),
190 # In CJK (Chinese, Japanese and Korean),
190 # in order to show CJK characters correctly,
191 # in order to show CJK characters correctly,
191 # you need to set this configuration.
192 # you need to set this configuration.
192 #
193 #
193 # Because there is no standard font across platforms in CJK,
194 # Because there is no standard font across platforms in CJK,
194 # you need to set a font installed in your server.
195 # you need to set a font installed in your server.
195 #
196 #
196 # This setting is not necessary in non CJK.
197 # This setting is not necessary in non CJK.
197 #
198 #
198 # Examples for Japanese:
199 # Examples for Japanese:
199 # Windows:
200 # Windows:
200 # rmagick_font_path: C:\windows\fonts\msgothic.ttc
201 # rmagick_font_path: C:\windows\fonts\msgothic.ttc
201 # Linux:
202 # Linux:
202 # rmagick_font_path: /usr/share/fonts/ipa-mincho/ipam.ttf
203 # rmagick_font_path: /usr/share/fonts/ipa-mincho/ipam.ttf
203 #
204 #
204 rmagick_font_path:
205 rmagick_font_path:
205
206
206 # Maximum number of simultaneous AJAX uploads
207 # Maximum number of simultaneous AJAX uploads
207 #max_concurrent_ajax_uploads: 2
208 #max_concurrent_ajax_uploads: 2
208
209
209 # Configure OpenIdAuthentication.store
210 # Configure OpenIdAuthentication.store
210 #
211 #
211 # allowed values: :memory, :file, :memcache
212 # allowed values: :memory, :file, :memcache
212 #openid_authentication_store: :memory
213 #openid_authentication_store: :memory
213
214
214 # specific configuration options for production environment
215 # specific configuration options for production environment
215 # that overrides the default ones
216 # that overrides the default ones
216 production:
217 production:
217
218
218 # specific configuration options for development environment
219 # specific configuration options for development environment
219 # that overrides the default ones
220 # that overrides the default ones
220 development:
221 development:
@@ -1,223 +1,223
1 require 'active_support/core_ext/object/to_query'
1 require 'active_support/core_ext/object/to_query'
2 require 'rack/utils'
2 require 'rack/utils'
3
3
4 module Redmine
4 module Redmine
5 module SudoMode
5 module SudoMode
6
6
7 # timespan after which sudo mode expires when unused.
8 MAX_INACTIVITY = 15.minutes
9
10
11 class SudoRequired < StandardError
7 class SudoRequired < StandardError
12 end
8 end
13
9
14
10
15 class Form
11 class Form
16 include ActiveModel::Validations
12 include ActiveModel::Validations
17
13
18 attr_accessor :password, :original_fields
14 attr_accessor :password, :original_fields
19 validate :check_password
15 validate :check_password
20
16
21 def initialize(password = nil)
17 def initialize(password = nil)
22 self.password = password
18 self.password = password
23 end
19 end
24
20
25 def check_password
21 def check_password
26 unless password.present? && User.current.check_password?(password)
22 unless password.present? && User.current.check_password?(password)
27 errors[:password] << :invalid
23 errors[:password] << :invalid
28 end
24 end
29 end
25 end
30 end
26 end
31
27
32
28
33 module Helper
29 module Helper
34 # Represents params data from hash as hidden fields
30 # Represents params data from hash as hidden fields
35 #
31 #
36 # taken from https://github.com/brianhempel/hash_to_hidden_fields
32 # taken from https://github.com/brianhempel/hash_to_hidden_fields
37 def hash_to_hidden_fields(hash)
33 def hash_to_hidden_fields(hash)
38 cleaned_hash = hash.reject { |k, v| v.nil? }
34 cleaned_hash = hash.reject { |k, v| v.nil? }
39 pairs = cleaned_hash.to_query.split(Rack::Utils::DEFAULT_SEP)
35 pairs = cleaned_hash.to_query.split(Rack::Utils::DEFAULT_SEP)
40 tags = pairs.map do |pair|
36 tags = pairs.map do |pair|
41 key, value = pair.split('=', 2).map { |str| Rack::Utils.unescape(str) }
37 key, value = pair.split('=', 2).map { |str| Rack::Utils.unescape(str) }
42 hidden_field_tag(key, value)
38 hidden_field_tag(key, value)
43 end
39 end
44 tags.join("\n").html_safe
40 tags.join("\n").html_safe
45 end
41 end
46 end
42 end
47
43
48
44
49 module Controller
45 module Controller
50 extend ActiveSupport::Concern
46 extend ActiveSupport::Concern
51
47
52 included do
48 included do
53 around_filter :sudo_mode
49 around_filter :sudo_mode
54 end
50 end
55
51
56 # Sudo mode Around Filter
52 # Sudo mode Around Filter
57 #
53 #
58 # Checks the 'last used' timestamp from session and sets the
54 # Checks the 'last used' timestamp from session and sets the
59 # SudoMode::active? flag accordingly.
55 # SudoMode::active? flag accordingly.
60 #
56 #
61 # After the request refreshes the timestamp if sudo mode was used during
57 # After the request refreshes the timestamp if sudo mode was used during
62 # this request.
58 # this request.
63 def sudo_mode
59 def sudo_mode
64 if sudo_timestamp_valid?
60 if sudo_timestamp_valid?
65 SudoMode.active!
61 SudoMode.active!
66 end
62 end
67 yield
63 yield
68 update_sudo_timestamp! if SudoMode.was_used?
64 update_sudo_timestamp! if SudoMode.was_used?
69 end
65 end
70
66
71 # This renders the sudo mode form / handles sudo form submission.
67 # This renders the sudo mode form / handles sudo form submission.
72 #
68 #
73 # Call this method in controller actions if sudo permissions are required
69 # Call this method in controller actions if sudo permissions are required
74 # for processing this request. This approach is good in cases where the
70 # for processing this request. This approach is good in cases where the
75 # action needs to be protected in any case or where the check is simple.
71 # action needs to be protected in any case or where the check is simple.
76 #
72 #
77 # In cases where this decision depends on complex conditions in the model,
73 # In cases where this decision depends on complex conditions in the model,
78 # consider the declarative approach using the require_sudo_mode class
74 # consider the declarative approach using the require_sudo_mode class
79 # method and a corresponding declaration in the model that causes it to throw
75 # method and a corresponding declaration in the model that causes it to throw
80 # a SudoRequired Error when necessary.
76 # a SudoRequired Error when necessary.
81 #
77 #
82 # All parameter names given are included as hidden fields to be resubmitted
78 # All parameter names given are included as hidden fields to be resubmitted
83 # along with the password.
79 # along with the password.
84 #
80 #
85 # Returns true when processing the action should continue, false otherwise.
81 # Returns true when processing the action should continue, false otherwise.
86 # If false is returned, render has already been called for display of the
82 # If false is returned, render has already been called for display of the
87 # password form.
83 # password form.
88 #
84 #
89 # if @user.mail_changed?
85 # if @user.mail_changed?
90 # require_sudo_mode :user or return
86 # require_sudo_mode :user or return
91 # end
87 # end
92 #
88 #
93 def require_sudo_mode(*param_names)
89 def require_sudo_mode(*param_names)
94 return true if SudoMode.active?
90 return true if SudoMode.active?
95
91
96 if param_names.blank?
92 if param_names.blank?
97 param_names = params.keys - %w(id action controller sudo_password)
93 param_names = params.keys - %w(id action controller sudo_password)
98 end
94 end
99
95
100 process_sudo_form
96 process_sudo_form
101
97
102 if SudoMode.active?
98 if SudoMode.active?
103 true
99 true
104 else
100 else
105 render_sudo_form param_names
101 render_sudo_form param_names
106 false
102 false
107 end
103 end
108 end
104 end
109
105
110 # display the sudo password form
106 # display the sudo password form
111 def render_sudo_form(param_names)
107 def render_sudo_form(param_names)
112 @sudo_form ||= SudoMode::Form.new
108 @sudo_form ||= SudoMode::Form.new
113 @sudo_form.original_fields = params.slice( *param_names )
109 @sudo_form.original_fields = params.slice( *param_names )
114 # a simple 'render "sudo_mode/new"' works when used directly inside an
110 # a simple 'render "sudo_mode/new"' works when used directly inside an
115 # action, but not when called from a before_filter:
111 # action, but not when called from a before_filter:
116 respond_to do |format|
112 respond_to do |format|
117 format.html { render 'sudo_mode/new' }
113 format.html { render 'sudo_mode/new' }
118 format.js { render 'sudo_mode/new' }
114 format.js { render 'sudo_mode/new' }
119 end
115 end
120 end
116 end
121
117
122 # handle sudo password form submit
118 # handle sudo password form submit
123 def process_sudo_form
119 def process_sudo_form
124 if params[:sudo_password]
120 if params[:sudo_password]
125 @sudo_form = SudoMode::Form.new(params[:sudo_password])
121 @sudo_form = SudoMode::Form.new(params[:sudo_password])
126 if @sudo_form.valid?
122 if @sudo_form.valid?
127 SudoMode.active!
123 SudoMode.active!
128 else
124 else
129 flash.now[:error] = l(:notice_account_wrong_password)
125 flash.now[:error] = l(:notice_account_wrong_password)
130 end
126 end
131 end
127 end
132 end
128 end
133
129
134 def sudo_timestamp_valid?
130 def sudo_timestamp_valid?
135 session[:sudo_timestamp].to_i > MAX_INACTIVITY.ago.to_i
131 session[:sudo_timestamp].to_i > SudoMode.timeout.ago.to_i
136 end
132 end
137
133
138 def update_sudo_timestamp!(new_value = Time.now.to_i)
134 def update_sudo_timestamp!(new_value = Time.now.to_i)
139 session[:sudo_timestamp] = new_value
135 session[:sudo_timestamp] = new_value
140 end
136 end
141
137
142 # Before Filter which is used by the require_sudo_mode class method.
138 # Before Filter which is used by the require_sudo_mode class method.
143 class SudoRequestFilter < Struct.new(:parameters, :request_methods)
139 class SudoRequestFilter < Struct.new(:parameters, :request_methods)
144 def before(controller)
140 def before(controller)
145 method_matches = request_methods.blank? || request_methods.include?(controller.request.method_symbol)
141 method_matches = request_methods.blank? || request_methods.include?(controller.request.method_symbol)
146 if controller.api_request?
142 if controller.api_request?
147 true
143 true
148 elsif SudoMode.possible? && method_matches
144 elsif SudoMode.possible? && method_matches
149 controller.require_sudo_mode( *parameters )
145 controller.require_sudo_mode( *parameters )
150 else
146 else
151 true
147 true
152 end
148 end
153 end
149 end
154 end
150 end
155
151
156 module ClassMethods
152 module ClassMethods
157
153
158 # Handles sudo requirements for the given actions, preserving the named
154 # Handles sudo requirements for the given actions, preserving the named
159 # parameters, or any parameters if you omit the :parameters option.
155 # parameters, or any parameters if you omit the :parameters option.
160 #
156 #
161 # Sudo enforcement by default is active for all requests to an action
157 # Sudo enforcement by default is active for all requests to an action
162 # but may be limited to a certain subset of request methods via the
158 # but may be limited to a certain subset of request methods via the
163 # :only option.
159 # :only option.
164 #
160 #
165 # Examples:
161 # Examples:
166 #
162 #
167 # require_sudo_mode :account, only: :post
163 # require_sudo_mode :account, only: :post
168 # require_sudo_mode :update, :create, parameters: %w(role)
164 # require_sudo_mode :update, :create, parameters: %w(role)
169 # require_sudo_mode :destroy
165 # require_sudo_mode :destroy
170 #
166 #
171 def require_sudo_mode(*args)
167 def require_sudo_mode(*args)
172 actions = args.dup
168 actions = args.dup
173 options = actions.extract_options!
169 options = actions.extract_options!
174 filter = SudoRequestFilter.new Array(options[:parameters]), Array(options[:only])
170 filter = SudoRequestFilter.new Array(options[:parameters]), Array(options[:only])
175 before_filter filter, only: actions
171 before_filter filter, only: actions
176 end
172 end
177 end
173 end
178 end
174 end
179
175
180
176
181 # true if the sudo mode state was queried during this request
177 # true if the sudo mode state was queried during this request
182 def self.was_used?
178 def self.was_used?
183 !!RequestStore.store[:sudo_mode_was_used]
179 !!RequestStore.store[:sudo_mode_was_used]
184 end
180 end
185
181
186 # true if sudo mode is currently active.
182 # true if sudo mode is currently active.
187 #
183 #
188 # Calling this method also turns was_used? to true, therefore
184 # Calling this method also turns was_used? to true, therefore
189 # it is important to only call this when sudo is actually needed, as the last
185 # it is important to only call this when sudo is actually needed, as the last
190 # condition to determine wether a change can be done or not.
186 # condition to determine wether a change can be done or not.
191 #
187 #
192 # If you do it wrong, timeout of the sudo mode will happen too late or not at
188 # If you do it wrong, timeout of the sudo mode will happen too late or not at
193 # all.
189 # all.
194 def self.active?
190 def self.active?
195 if !!RequestStore.store[:sudo_mode]
191 if !!RequestStore.store[:sudo_mode]
196 RequestStore.store[:sudo_mode_was_used] = true
192 RequestStore.store[:sudo_mode_was_used] = true
197 end
193 end
198 end
194 end
199
195
200 def self.active!
196 def self.active!
201 RequestStore.store[:sudo_mode] = true
197 RequestStore.store[:sudo_mode] = true
202 end
198 end
203
199
204 def self.possible?
200 def self.possible?
205 enabled? && User.current.logged?
201 enabled? && User.current.logged?
206 end
202 end
207
203
208 # Turn off sudo mode (never require password entry).
204 # Turn off sudo mode (never require password entry).
209 def self.disable!
205 def self.disable!
210 RequestStore.store[:sudo_mode_disabled] = true
206 RequestStore.store[:sudo_mode_disabled] = true
211 end
207 end
212
208
213 # Turn sudo mode back on
209 # Turn sudo mode back on
214 def self.enable!
210 def self.enable!
215 RequestStore.store[:sudo_mode_disabled] = nil
211 RequestStore.store[:sudo_mode_disabled] = nil
216 end
212 end
217
213
218 def self.enabled?
214 def self.enabled?
219 Redmine::Configuration['sudo_mode'] && !RequestStore.store[:sudo_mode_disabled]
215 Redmine::Configuration['sudo_mode'] && !RequestStore.store[:sudo_mode_disabled]
220 end
216 end
217
218 # Timespan after which sudo mode expires when unused.
219 def self.timeout
220 Redmine::Configuration['sudo_mode_timeout'].to_i.minutes
221 end
221 end
222 end
222 end
223 end
223
General Comments 0
You need to be logged in to leave comments. Login now