Redirect after processing user changes
[rails.git] / app / controllers / user_controller.rb
1 class UserController < ApplicationController
2   layout 'site', :except => :api_details
3
4   before_filter :authorize, :only => [:api_details, :api_gpx_files]
5   before_filter :authorize_web, :except => [:api_details, :api_gpx_files]
6   before_filter :set_locale, :except => [:api_details, :api_gpx_files]
7   before_filter :require_user, :only => [:account, :go_public, :make_friend, :remove_friend]
8   before_filter :check_database_readable, :except => [:api_details, :api_gpx_files]
9   before_filter :check_database_writable, :only => [:login, :new, :account, :go_public, :make_friend, :remove_friend]
10   before_filter :check_api_readable, :only => [:api_details, :api_gpx_files]
11   before_filter :require_allow_read_prefs, :only => [:api_details]
12   before_filter :require_allow_read_gpx, :only => [:api_gpx_files]
13   before_filter :require_cookies, :only => [:login, :confirm]
14   before_filter :require_administrator, :only => [:set_status, :delete, :list]
15   before_filter :lookup_this_user, :only => [:set_status, :delete]
16
17   filter_parameter_logging :password, :pass_crypt, :pass_crypt_confirmation
18
19   cache_sweeper :user_sweeper, :only => [:account, :set_status, :delete]
20
21   def save
22     @title = t 'user.new.title'
23
24     if Acl.find_by_address(request.remote_ip, :conditions => {:k => "no_account_creation"})
25       render :action => 'new'
26     else
27       @user = User.new(params[:user])
28
29       @user.status = "pending"
30       @user.data_public = true
31       @user.description = "" if @user.description.nil?
32       @user.creation_ip = request.remote_ip
33       @user.languages = request.user_preferred_languages
34
35       if @user.save
36         flash[:notice] = t 'user.new.flash create success message'
37         Notifier.deliver_signup_confirm(@user, @user.tokens.create(:referer => params[:referer]))
38         redirect_to :action => 'login'
39       else
40         render :action => 'new'
41       end
42     end
43   end
44
45   def account
46     @title = t 'user.account.title'
47     @tokens = @user.oauth_tokens.find :all, :conditions => 'oauth_tokens.invalidated_at is null and oauth_tokens.authorized_at is not null'
48
49     if params[:user] and params[:user][:display_name] and params[:user][:description]
50       @user.display_name = params[:user][:display_name]
51       @user.new_email = params[:user][:new_email]
52
53       if params[:user][:pass_crypt].length > 0 or params[:user][:pass_crypt_confirmation].length > 0
54         @user.pass_crypt = params[:user][:pass_crypt]
55         @user.pass_crypt_confirmation = params[:user][:pass_crypt_confirmation]
56       end
57
58       @user.description = params[:user][:description]
59       @user.languages = params[:user][:languages].split(",")
60
61       case params[:image_action]
62         when "new" then @user.image = params[:user][:image]
63         when "delete" then @user.image = nil
64       end
65
66       @user.home_lat = params[:user][:home_lat]
67       @user.home_lon = params[:user][:home_lon]
68
69       if @user.save
70         set_locale
71
72         if @user.new_email.nil? or @user.new_email.empty?
73           flash[:notice] = t 'user.account.flash update success'
74         else
75           flash[:notice] = t 'user.account.flash update success confirm needed'
76
77           begin
78             Notifier.deliver_email_confirm(@user, @user.tokens.create)
79           rescue
80             # Ignore errors sending email
81           end
82         end
83
84         redirect_to :action => "account", :display_name => @user.display_name
85       end
86     else
87       if flash[:errors]
88         flash[:errors].each do |attr,msg|
89           attr = "new_email" if attr == "email"
90           @user.errors.add(attr,msg)
91         end
92       end
93     end
94   end
95
96   def go_public
97     @user.data_public = true
98     @user.save
99     flash[:notice] = t 'user.go_public.flash success'
100     redirect_to :controller => 'user', :action => 'account', :display_name => @user.display_name
101   end
102
103   def lost_password
104     @title = t 'user.lost_password.title'
105
106     if params[:user] and params[:user][:email]
107       user = User.find_by_email(params[:user][:email], :conditions => {:status => ["pending", "active", "confirmed"]})
108
109       if user
110         token = user.tokens.create
111         Notifier.deliver_lost_password(user, token)
112         flash[:notice] = t 'user.lost_password.notice email on way'
113         redirect_to :action => 'login'
114       else
115         flash.now[:error] = t 'user.lost_password.notice email cannot find'
116       end
117     end
118   end
119
120   def reset_password
121     @title = t 'user.reset_password.title'
122
123     if params[:token]
124       token = UserToken.find_by_token(params[:token])
125
126       if token
127         @user = token.user
128
129         if params[:user]
130           @user.pass_crypt = params[:user][:pass_crypt]
131           @user.pass_crypt_confirmation = params[:user][:pass_crypt_confirmation]
132           @user.status = "active"
133           @user.email_valid = true
134
135           if @user.save
136             token.destroy
137             flash[:notice] = t 'user.reset_password.flash changed'
138             redirect_to :action => 'login'
139           end
140         end
141       else
142         flash[:error] = t 'user.reset_password.flash token bad'
143         redirect_to :action => 'lost_password'
144       end
145     end
146   end
147
148   def new
149     @title = t 'user.new.title'
150
151     # The user is logged in already, so don't show them the signup
152     # page, instead send them to the home page
153     redirect_to :controller => 'site', :action => 'index' if session[:user]
154   end
155
156   def login
157     @title = t 'user.login.title'
158
159     if params[:user]
160       email_or_display_name = params[:user][:email]
161       pass = params[:user][:password]
162       user = User.authenticate(:username => email_or_display_name, :password => pass)
163
164       if user
165         session[:user] = user.id
166         session_expires_after 1.month if params[:remember_me]
167
168         # The user is logged in, if the referer param exists, redirect
169         # them to that unless they've also got a block on them, in
170         # which case redirect them to the block so they can clear it.
171         if user.blocked_on_view
172           redirect_to user.blocked_on_view, :referrer => params[:referrer]
173         elsif params[:referer]
174           redirect_to params[:referer]
175         else
176           redirect_to :controller => 'site', :action => 'index'
177         end
178       elsif User.authenticate(:username => email_or_display_name, :password => pass, :pending => true)
179         flash.now[:error] = t 'user.login.account not active'
180       elsif User.authenticate(:username => email_or_display_name, :password => pass, :suspended => true)
181         flash.now[:error] = t 'user.login.account suspended'
182       else
183         flash.now[:error] = t 'user.login.auth failure'
184       end
185     end
186   end
187
188   def logout
189     @title = t 'user.logout.title'
190
191     if params[:session] == request.session_options[:id]
192       if session[:token]
193         token = UserToken.find_by_token(session[:token])
194         if token
195           token.destroy
196         end
197         session[:token] = nil
198       end
199       session[:user] = nil
200       session_expires_automatically
201       if params[:referer]
202         redirect_to params[:referer]
203       else
204         redirect_to :controller => 'site', :action => 'index'
205       end
206     end
207   end
208
209   def confirm
210     if params[:confirm_action]
211       token = UserToken.find_by_token(params[:confirm_string])
212       if token and !token.user.active?
213         @user = token.user
214         @user.status = "active"
215         @user.email_valid = true
216         @user.save!
217         referer = token.referer
218         token.destroy
219         flash[:notice] = t 'user.confirm.success'
220         session[:user] = @user.id
221         unless referer.nil?
222           redirect_to referer
223         else
224           redirect_to :action => 'account', :display_name => @user.display_name
225         end
226       else
227         flash.now[:error] = t 'user.confirm.failure'
228       end
229     end
230   end
231
232   def confirm_email
233     if params[:confirm_action]
234       token = UserToken.find_by_token(params[:confirm_string])
235       if token and token.user.new_email?
236         @user = token.user
237         @user.email = @user.new_email
238         @user.new_email = nil
239         @user.email_valid = true
240         if @user.save
241           flash[:notice] = t 'user.confirm_email.success'
242         else
243           flash[:errors] = @user.errors
244         end
245         token.destroy
246         session[:user] = @user.id
247         redirect_to :action => 'account', :display_name => @user.display_name
248       else
249         flash.now[:error] = t 'user.confirm_email.failure'
250       end
251     end
252   end
253
254   def api_gpx_files
255     doc = OSM::API.new.get_xml_doc
256     @user.traces.each do |trace|
257       doc.root << trace.to_xml_node() if trace.public? or trace.user == @user
258     end
259     render :text => doc.to_s, :content_type => "text/xml"
260   end
261
262   def view
263     @this_user = User.find_by_display_name(params[:display_name])
264
265     if @this_user and
266        (@this_user.visible? or (@user and @user.administrator?))
267       @title = @this_user.display_name
268     else
269       @title = t 'user.no_such_user.title'
270       @not_found_user = params[:display_name]
271       render :action => 'no_such_user', :status => :not_found
272     end
273   end
274
275   def make_friend
276     if params[:display_name]
277       name = params[:display_name]
278       new_friend = User.find_by_display_name(name, :conditions => {:status => ["active", "confirmed"]})
279       friend = Friend.new
280       friend.user_id = @user.id
281       friend.friend_user_id = new_friend.id
282       unless @user.is_friends_with?(new_friend)
283         if friend.save
284           flash[:notice] = t 'user.make_friend.success', :name => name
285           Notifier.deliver_friend_notification(friend)
286         else
287           friend.add_error(t('user.make_friend.failed', :name => name))
288         end
289       else
290         flash[:warning] = t 'user.make_friend.already_a_friend', :name => name
291       end
292
293       if params[:referer]
294         redirect_to params[:referer]
295       else
296         redirect_to :controller => 'user', :action => 'view'
297       end
298     end
299   end
300
301   def remove_friend
302     if params[:display_name]
303       name = params[:display_name]
304       friend = User.find_by_display_name(name, :conditions => {:status => ["active", "confirmed"]})
305       if @user.is_friends_with?(friend)
306         Friend.delete_all "user_id = #{@user.id} AND friend_user_id = #{friend.id}"
307         flash[:notice] = t 'user.remove_friend.success', :name => friend.display_name
308       else
309         flash[:error] = t 'user.remove_friend.not_a_friend', :name => friend.display_name
310       end
311
312       if params[:referer]
313         redirect_to params[:referer]
314       else
315         redirect_to :controller => 'user', :action => 'view'
316       end
317     end
318   end
319
320   ##
321   # sets a user's status
322   def set_status
323     @this_user.update_attributes(:status => params[:status])
324     redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
325   end
326
327   ##
328   # delete a user, marking them as deleted and removing personal data
329   def delete
330     @this_user.delete
331     redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
332   end
333
334   ##
335   # display a list of users matching specified criteria
336   def list
337     if request.post?
338       ids = params[:user].keys.collect { |id| id.to_i }
339
340       User.update_all("status = 'confirmed'", :id => ids) if params[:confirm]
341       User.update_all("status = 'deleted'", :id => ids) if params[:hide]
342
343       redirect_to url_for(:status => params[:status], :ip => params[:ip], :page => params[:page])
344     else
345       conditions = Hash.new
346       conditions[:status] = params[:status] if params[:status]
347       conditions[:creation_ip] = params[:ip] if params[:ip]
348
349       @user_pages, @users = paginate(:users,
350                                      :conditions => conditions,
351                                      :order => :id,
352                                      :per_page => 50)
353     end
354   end
355
356 private
357
358   ##
359   # require that the user is a administrator, or fill out a helpful error message
360   # and return them to the user page.
361   def require_administrator
362     if @user and not @user.administrator?
363       flash[:error] = t('user.filter.not_an_administrator')
364
365       if params[:display_name]
366         redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
367       else
368         redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
369       end
370     elsif not @user
371       redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
372     end
373   end
374
375   ##
376   # ensure that there is a "this_user" instance variable
377   def lookup_this_user
378     @this_user = User.find_by_display_name(params[:display_name])
379   rescue ActiveRecord::RecordNotFound
380     redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name] unless @this_user
381   end
382 end