Changesets can be listed by changeset number.
The Git repository is here.
- Revision:
- 98
- Log:
Initial import of Hub, an account management application.
- Author:
- adh
- Date:
- Thu Oct 19 15:18:43 +0100 2006
- Size:
- 12689 Bytes
1 | class AccountController < ApplicationController |
2 | |
3 | require 'authenticated_roles' |
4 | layout 'default.rhtml' |
5 | |
6 | # Action permissions for this class. |
7 | |
8 | @@permissions = AuthorisedPermissions.new({ |
9 | :logout => [ :admin, :webmaster, :privileged, :normal ], |
10 | :expire => [ :admin, :webmaster, :privileged, :normal ], |
11 | :change_password => [ :admin, :webmaster, :privileged, :normal ], |
12 | :change_details => [ :admin, :webmaster, :privileged, :normal ], |
13 | :delete => [ :admin, :webmaster, :privileged, :normal ], |
14 | :delete_confirm => [ :admin, :webmaster, :privileged, :normal ], |
15 | :list => [ :admin, :webmaster, :privileged ], |
16 | :show => [ :admin ], |
17 | :edit_roles => [ :admin ], |
18 | :destroy => [ :admin ] |
19 | }) |
20 | |
21 | def AccountController.permissions |
22 | @@permissions |
23 | end |
24 | |
25 | # Ensure that we don't try to ask for log-in or sign up except |
26 | # for authorisation-only methods. Avoid session expiry checks# |
27 | # if the user is trying to log out. |
28 | |
29 | attr_accessor :permissions |
30 | skip_before_filter :check_session_expiry, :only => [ :logout, :expire ] |
31 | skip_before_filter :login_required, :only => [ :login, |
32 | :signup, |
33 | :activate, |
34 | :forgot_password, |
35 | :reset_password ] |
36 | |
37 | # If you want "remember me" functionality, add this before_filter and |
38 | # uncomment relevant code in some of the methods below. |
39 | # before_filter :login_from_cookie |
40 | |
41 | # Set up the notification mailer. |
42 | observer :user_observer |
43 | |
44 | def login |
45 | @title = 'Log in' |
46 | return unless request.post? |
47 | |
48 | @email = params[:email] |
49 | self.current_user = User.authenticate(@email, params[:password]) |
50 | |
51 | if current_user |
52 | |
53 | # If you reinstate (uncomment) this code, ensure you reinstate |
54 | # relevant code in the 'logout' method too. |
55 | # |
56 | # if params[:remember_me] == "1" |
57 | # self.current_user.remember_me |
58 | # cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at } |
59 | # end |
60 | |
61 | session[:last_used] = Time.now.utc |
62 | flash[:notice] = 'Logged in successfully.' |
63 | redirect_back_or_default(:controller => 'tasks', :action => nil) |
64 | else |
65 | flash[:alert] = 'Incorrect e-mail address or password.' |
66 | flash.discard # Ensure the flash message is discarded after this action, |
67 | # since it's going to be shown on the same URL so it won't |
68 | # get automatically discarded. |
69 | end |
70 | end |
71 | |
72 | # The logout method is a standard action but with an optional parameter |
73 | # which change the 'flash' message shown to the user. By default the user |
74 | # sees a normal 'you have logged out' message, but by passing 'true', the |
75 | # message changes to an indication that the session timed out. See also |
76 | # the 'expire' method below. |
77 | # |
78 | def logout(expired = false) |
79 | @title = 'Log out' |
80 | actually_log_out() |
81 | |
82 | if (expired) |
83 | flash[:attention] = 'Sorry, your session timed out; please log in again.' |
84 | redirect_to :controller => 'account', :action => 'login' |
85 | else |
86 | flash[:attention] = 'You are now logged out.' |
87 | redirect_to :controller => 'tasks', :action => nil |
88 | end |
89 | end |
90 | |
91 | # This method is called by the application controller if it sees that |
92 | # a user as been idle for longer than the idle timeout period. It redirects |
93 | # to a URL which causes this action to be run. In turn, all we do is call |
94 | # the logout method but set the 'expired' flag to get a better 'flash' |
95 | # message shown to the user. |
96 | # |
97 | def expire |
98 | self.logout(true) |
99 | end |
100 | |
101 | def signup |
102 | @title = 'Sign up' |
103 | return unless request.post? |
104 | |
105 | # Bulk assignment from the params hash is safe because the User object |
106 | # contains nothing that won't be overwritten anyway or isn't already |
107 | # protected by attr_accessible in the User model. |
108 | |
109 | @user = User.new(params[:user]) |
110 | |
111 | # Are there any users yet? If not, grant this user admin permissions. |
112 | # Administrators are for just this application; whether or not admin |
113 | # privileges affect other applications depends on the level of external |
114 | # SSO integration. |
115 | |
116 | users = User.find_all |
117 | |
118 | if (users.empty? or users.nil?) |
119 | @user.roles = AuthenticatedRoles.new(true).to_s |
120 | @user.save! |
121 | @user.activate |
122 | |
123 | self.current_user = @user |
124 | |
125 | flash[:notice] = 'Thanks for signing up. You are now the system administrator ' << |
126 | 'and your account has been automatically activated.' |
127 | else |
128 | |
129 | @user.roles = AuthenticatedRoles.new(false).to_s |
130 | @user.save! |
131 | |
132 | flash[:notice] = 'Thanks for signing up. Your site account must be activated ' << |
133 | 'before you can use it - please check your e-mail account ' << |
134 | 'for a message which tells you what you should do next.' |
135 | end |
136 | |
137 | redirect_to :controller => 'tasks', :action => nil |
138 | |
139 | rescue ActiveRecord::RecordInvalid |
140 | render :action => 'signup' |
141 | end |
142 | |
143 | def activate |
144 | activation_code = params[:activation_code] || params[:id] |
145 | |
146 | unless activation_code.nil? |
147 | @user = User.find_by_activation_code(activation_code) |
148 | |
149 | if @user and @user.activate |
150 | self.current_user = @user |
151 | session[:last_used] = Time.now.utc |
152 | |
153 | flash[:notice] = 'Your RISC OS Open web site account is now active.' |
154 | redirect_back_or_default(:controller => 'tasks', :action => nil) |
155 | else |
156 | flash[:alert] = 'Unable to activate your RISC OS Open web site account. ' << |
157 | 'Is the activation code correct, or has it already been used? ' << |
158 | 'If in doubt please try to sign up again. Contact ROOL if you ' << |
159 | 'keep having trouble.' |
160 | |
161 | redirect_to :controller => 'account', :action => 'signup' |
162 | end |
163 | else |
164 | redirect_to :controller => 'account', :action => 'signup' |
165 | end |
166 | end |
167 | |
168 | def change_password |
169 | @title = 'Change password' |
170 | return unless request.post? |
171 | |
172 | if User.authenticate(current_user.email, params[:old_password]) |
173 | if (params[:password] == params[:password_confirmation]) |
174 | current_user.password_confirmation = params[:password_confirmation] |
175 | current_user.password = params[:password] |
176 | save_password_and_set_flash(current_user) |
177 | |
178 | redirect_to :controller => 'tasks', :action => nil |
179 | else |
180 | set_password_mismatch_flash |
181 | flash.discard # Staying on same URL, so it won't be discarded automatically - |
182 | # do it manually now. |
183 | |
184 | @old_password = params[:old_password] |
185 | end |
186 | else |
187 | flash[:alert] = 'Incorrect current password.' |
188 | flash.discard # Staying on same URL again, so discard it manually |
189 | end |
190 | end |
191 | |
192 | def change_details |
193 | @title = 'Update account details' |
194 | @user = self.current_user |
195 | @real_name = @user ? @user.real_name || '' : '' |
196 | |
197 | return unless request.post? |
198 | |
199 | if (params[:real_name]) |
200 | @user.real_name = @real_name = params[:real_name] |
201 | @user.save! |
202 | |
203 | flash[:notice] = 'Account details updated successfully.' |
204 | flash.discard # The flash is going to be shown on the same URL so it won't |
205 | # be automatically discarded; discard it now so it only shows |
206 | # up once. |
207 | end |
208 | end |
209 | |
210 | def forgot_password |
211 | @title = 'Forgotten password' |
212 | return unless request.post? |
213 | |
214 | if @user = User.find_by_email(params[:email]) |
215 | @user.forgot_password |
216 | @user.save |
217 | flash[:notice] = 'An e-mail message which tells you how to reset your ' << |
218 | 'account password has been set to your e-mail address.' |
219 | |
220 | redirect_to :controller => 'tasks', :action => nil |
221 | else |
222 | flash[:alert] = 'No account was found for the given e-mail address.' |
223 | flash.discard # Saying on same URL, so manually ensure that flash is discarded after use |
224 | end |
225 | end |
226 | |
227 | def reset_password |
228 | @title = 'Reset password' |
229 | |
230 | if params[:id].nil? |
231 | redirect_back_or_default(:controller => 'tasks', :action => nil) |
232 | return |
233 | end |
234 | |
235 | @user = User.find_by_password_reset_code(params[:id]) |
236 | |
237 | if (@user.nil?) |
238 | flash[:alert] = 'Invalid reset code. Did your e-mail client break up the reset ' << |
239 | 'link so it spanned more than one line? If so, please try again, ' << |
240 | 'copying all of the link in the message however many lines it spans.' |
241 | |
242 | redirect_back_or_default(:controller => 'tasks', :action => nil) |
243 | return |
244 | end |
245 | |
246 | t = Time.now.utc |
247 | if (t >= (@user.password_reset_code_expires_at || t)) # Allows for 'nil' in expiry field |
248 | flash[:alert] = 'The reset code has expired. Please try your reset request again.' |
249 | redirect_to :controller => 'account', :action => 'forgot_password' |
250 | return |
251 | end |
252 | |
253 | unless params[:password] |
254 | flash[:alert] = 'Reset your password using the form below.' |
255 | flash.discard # Staying on same URL, so ensure the flash is discarded after use |
256 | return |
257 | end |
258 | |
259 | if (params[:password] == params[:password_confirmation]) |
260 | @user.password_confirmation = params[:password_confirmation] |
261 | @user.password = params[:password] |
262 | @user.reset_password |
263 | save_password_and_set_flash(@user) |
264 | redirect_to :controller => 'tasks', :action => nil |
265 | return |
266 | else |
267 | set_password_mismatch_flash |
268 | flash.discard # Staying on same URL, so ensure the flash is discarded after use |
269 | return |
270 | end |
271 | end |
272 | |
273 | def delete |
274 | flash[:alert] = 'Are you sure?' |
275 | flash.discard |
276 | title = 'Delete account: Are you sure?' |
277 | end |
278 | |
279 | def delete_confirm |
280 | me = self.current_user |
281 | actually_log_out() |
282 | me.destroy |
283 | |
284 | flash.clear |
285 | flash[:alert] = 'Your account has been deleted.' |
286 | redirect_to :controller => 'tasks', :action => nil |
287 | end |
288 | |
289 | def list |
290 | @title = 'List of user accounts' |
291 | @users = User.find_all |
292 | end |
293 | |
294 | def show |
295 | @title = 'User account details' |
296 | @user = User.find(params[:id]) |
297 | end |
298 | |
299 | def edit_roles |
300 | @title = 'Edit account roles' |
301 | |
302 | # We must have a valid ID |
303 | |
304 | unless (request.post?) and (params[:id]) and (@user = User.find(params[:id])) |
305 | redirect_to :controller => tasks, :action => nil |
306 | return |
307 | end |
308 | |
309 | # If 'commit' is present, the form was submitted with details rather than |
310 | # visited from a list or account details view. |
311 | |
312 | return unless (params[:commit]) |
313 | |
314 | # Validate the result |
315 | |
316 | roles = (params[:user] ? params[:user][:roles] : '').to_authenticated_roles |
317 | |
318 | unless (roles.validate) |
319 | flash[:alert] = 'Invalid roles chosen. Ensure at least one item in the list is selected.' |
320 | flash.discard # Staying on the same action, so must manually discard the flash |
321 | else |
322 | @user.roles = roles.to_s |
323 | @user.save! |
324 | |
325 | flash[:notice] = 'Account roles updated successfully.' |
326 | redirect_to :action => 'show', :id => @user.id |
327 | end |
328 | end |
329 | |
330 | def destroy |
331 | user = User.find(params[:id]) |
332 | |
333 | if (user == self.current_user) |
334 | flash[:alert] = 'Please use the normal control panel to delete your own account.' |
335 | elsif (user.roles.to_authenticated_roles.include?(:admin)) |
336 | flash[:alert] = 'You cannot destroy an administrator account! You can only do that at the control panel when logged into the account, or at the database level.' |
337 | else |
338 | user.destroy |
339 | flash[:alert] = 'The account has been deleted.' |
340 | end |
341 | |
342 | redirect_to :action => 'list' |
343 | end |
344 | |
345 | protected |
346 | |
347 | def save_password_and_set_flash(user) |
348 | user.save ? |
349 | flash[:notice] = 'Your password has been changed.' : |
350 | flash[:alert] = 'Sorry, your password could not be changed.' |
351 | end |
352 | |
353 | def set_password_mismatch_flash |
354 | flash[:alert] = 'The new password differed from the password confirmation you entered.' |
355 | end |
356 | |
357 | def actually_log_out |
358 | self.current_user.forget_me if logged_in? |
359 | # cookies.delete :auth_token |
360 | |
361 | # Calling reset_session() is more thorough, but stops the flash[...] from |
362 | # working. Clearing the user field works well enough. |
363 | session[:user] = nil |
364 | self.current_user = nil |
365 | end |
366 | end |