]> git.openstreetmap.org Git - rails.git/blob - app/controllers/user_controller.rb
Avoid integer overflow when computing shortcodes
[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], :unless => STATUS == :database_offline
20
21   def terms
22     @legale = params[:legale] || OSM.IPToCountry(request.remote_ip) || DEFAULT_LEGALE
23     @text = OSM.legal_text_for_country(@legale)
24
25     if request.xhr?
26       render :update do |page|
27         page.replace_html "contributorTerms", :partial => "terms", :locals => { :has_decline => params[:has_decline] }
28       end
29     else
30       @title = t 'user.terms.title'
31       @user = User.new(params[:user]) if params[:user]
32
33       if @user
34         if @user.invalid?
35           if @user.new_record?
36             render :action => :new
37           else
38             flash[:errors] = @user.errors
39             redirect_to :action => :account, :display_name => @user.display_name
40           end
41         elsif @user.terms_agreed?
42           redirect_to :action => :account, :display_name => @user.display_name
43         end
44       else
45         redirect_to :action => :login, :referer => request.request_uri
46       end
47     end
48   end
49
50   def save
51     @title = t 'user.new.title'
52
53     if Acl.find_by_address(request.remote_ip, :conditions => {:k => "no_account_creation"})
54       render :action => 'new'
55     elsif params[:decline]
56       redirect_to t('user.terms.declined')
57     elsif @user
58       if !@user.terms_agreed?
59         @user.consider_pd = params[:user][:consider_pd]
60         @user.terms_agreed = Time.now.getutc
61         if @user.save
62           flash[:notice] = t 'user.new.terms accepted'
63         end
64       end
65
66       redirect_to :action => :account, :display_name => @user.display_name
67     else
68       @user = User.new(params[:user])
69
70       @user.status = "pending"
71       @user.data_public = true
72       @user.description = "" if @user.description.nil?
73       @user.creation_ip = request.remote_ip
74       @user.languages = request.user_preferred_languages
75       @user.terms_agreed = Time.now.getutc
76
77       if @user.save
78         flash[:notice] = t 'user.new.flash create success message', :email => @user.email
79         Notifier.deliver_signup_confirm(@user, @user.tokens.create(:referer => params[:referer]))
80         session[:token] = @user.tokens.create.token
81         redirect_to :action => 'login'
82       else
83         render :action => 'new'
84       end
85     end
86   end
87
88   def account
89     @title = t 'user.account.title'
90     @tokens = @user.oauth_tokens.find :all, :conditions => 'oauth_tokens.invalidated_at is null and oauth_tokens.authorized_at is not null'
91
92     if params[:user] and params[:user][:display_name] and params[:user][:description]
93       @user.display_name = params[:user][:display_name]
94       @user.new_email = params[:user][:new_email]
95
96       if params[:user][:pass_crypt].length > 0 or params[:user][:pass_crypt_confirmation].length > 0
97         @user.pass_crypt = params[:user][:pass_crypt]
98         @user.pass_crypt_confirmation = params[:user][:pass_crypt_confirmation]
99       end
100
101       @user.description = params[:user][:description]
102       @user.languages = params[:user][:languages].split(",")
103
104       case params[:image_action]
105         when "new" then @user.image = params[:user][:image]
106         when "delete" then @user.image = nil
107       end
108
109       @user.home_lat = params[:user][:home_lat]
110       @user.home_lon = params[:user][:home_lon]
111
112       if params[:user][:preferred_editor] == "default"
113         @user.preferred_editor = nil
114       else
115         @user.preferred_editor = params[:user][:preferred_editor]
116       end
117
118       if @user.save
119         set_locale
120
121         if @user.new_email.nil? or @user.new_email.empty?
122           flash[:notice] = t 'user.account.flash update success'
123         else
124           flash[:notice] = t 'user.account.flash update success confirm needed'
125
126           begin
127             Notifier.deliver_email_confirm(@user, @user.tokens.create)
128           rescue
129             # Ignore errors sending email
130           end
131         end
132
133         redirect_to :action => "account", :display_name => @user.display_name
134       end
135     else
136       if flash[:errors]
137         flash[:errors].each do |attr,msg|
138           attr = "new_email" if attr == "email" and !@user.new_email.nil?
139           @user.errors.add(attr,msg)
140         end
141       end
142     end
143   end
144
145   def go_public
146     @user.data_public = true
147     @user.save
148     flash[:notice] = t 'user.go_public.flash success'
149     redirect_to :controller => 'user', :action => 'account', :display_name => @user.display_name
150   end
151
152   def lost_password
153     @title = t 'user.lost_password.title'
154
155     if params[:user] and params[:user][:email]
156       user = User.find_by_email(params[:user][:email], :conditions => {:status => ["pending", "active", "confirmed"]})
157
158       if user
159         token = user.tokens.create
160         Notifier.deliver_lost_password(user, token)
161         flash[:notice] = t 'user.lost_password.notice email on way'
162         redirect_to :action => 'login'
163       else
164         flash.now[:error] = t 'user.lost_password.notice email cannot find'
165       end
166     end
167   end
168
169   def reset_password
170     @title = t 'user.reset_password.title'
171
172     if params[:token]
173       token = UserToken.find_by_token(params[:token])
174
175       if token
176         @user = token.user
177
178         if params[:user]
179           @user.pass_crypt = params[:user][:pass_crypt]
180           @user.pass_crypt_confirmation = params[:user][:pass_crypt_confirmation]
181           @user.status = "active" if @user.status == "pending"
182           @user.email_valid = true
183
184           if @user.save
185             token.destroy
186             flash[:notice] = t 'user.reset_password.flash changed'
187             redirect_to :action => 'login'
188           end
189         end
190       else
191         flash[:error] = t 'user.reset_password.flash token bad'
192         redirect_to :action => 'lost_password'
193       end
194     end
195   end
196
197   def new
198     @title = t 'user.new.title'
199
200     # The user is logged in already, so don't show them the signup
201     # page, instead send them to the home page
202     redirect_to :controller => 'site', :action => 'index' if session[:user]
203   end
204
205   def login
206     @title = t 'user.login.title'
207
208     if params[:user]
209       email_or_display_name = params[:user][:email]
210       pass = params[:user][:password]
211       user = User.authenticate(:username => email_or_display_name, :password => pass)
212
213       if user
214         session[:user] = user.id
215         session_expires_after 1.month if params[:remember_me]
216
217         # The user is logged in, if the referer param exists, redirect
218         # them to that unless they've also got a block on them, in
219         # which case redirect them to the block so they can clear it.
220         if user.blocked_on_view
221           redirect_to user.blocked_on_view, :referer => params[:referer]
222         elsif params[:referer]
223           redirect_to params[:referer]
224         else
225           redirect_to :controller => 'site', :action => 'index'
226         end
227       elsif user = User.authenticate(:username => email_or_display_name, :password => pass, :pending => true)
228         flash.now[:error] = t 'user.login.account not active', :reconfirm => url_for(:action => 'confirm_resend', :display_name => user.display_name)
229       elsif User.authenticate(:username => email_or_display_name, :password => pass, :suspended => true)
230         webmaster = link_to t('user.login.webmaster'), "mailto:webmaster@openstreetmap.org"
231         flash.now[:error] = t 'user.login.account suspended', :webmaster => webmaster
232       else
233         flash.now[:error] = t 'user.login.auth failure'
234       end
235     elsif flash[:notice].nil?
236       flash.now[:notice] =  t 'user.login.notice'
237     end
238   end
239
240   def logout
241     @title = t 'user.logout.title'
242
243     if params[:session] == request.session_options[:id]
244       if session[:token]
245         token = UserToken.find_by_token(session[:token])
246         if token
247           token.destroy
248         end
249         session[:token] = nil
250       end
251       session[:user] = nil
252       session_expires_automatically
253       if params[:referer]
254         redirect_to params[:referer]
255       else
256         redirect_to :controller => 'site', :action => 'index'
257       end
258     end
259   end
260
261   def confirm
262     if request.post?
263       if token = UserToken.find_by_token(params[:confirm_string])
264         if token.user.active?
265           flash[:error] = t('user.confirm.already active')
266           redirect_to :action => 'login'
267         else
268           user = token.user
269           user.status = "active"
270           user.email_valid = true
271           user.save!
272           referer = token.referer
273           token.destroy
274
275           if session[:token] 
276             token = UserToken.find_by_token(session[:token])
277             session.delete(:token)
278           else
279             token = nil
280           end
281
282           if token.nil? or token.user != user
283             flash[:notice] = t('user.confirm.success')
284             redirect_to :action => :login, :referer => referer
285           else
286             token.destroy
287
288             session[:user] = user.id
289
290             if referer.nil?
291               flash[:notice] = t('user.confirm.success') + "<br /><br />" + t('user.confirm.before you start')
292               redirect_to :action => :account, :display_name => user.display_name
293             else
294               flash[:notice] = t('user.confirm.success')
295               redirect_to referer
296             end
297           end
298         end
299       else
300         user = User.find_by_display_name(params[:display_name])
301
302         if user and user.active?
303           flash[:error] = t('user.confirm.already active')
304         elsif user
305           flash[:error] = t('user.confirm.unknown token') + t('user.confirm.reconfirm', :reconfirm => url_for(:action => 'confirm_resend', :display_name => params[:display_name]))
306         else
307           flash[:error] = t('user.confirm.unknown token')
308         end
309
310         redirect_to :action => 'login'
311       end
312     end
313   end
314
315   def confirm_resend
316     if user = User.find_by_display_name(params[:display_name])
317       Notifier.deliver_signup_confirm(user, user.tokens.create)
318       flash[:notice] = t 'user.confirm_resend.success', :email => user.email
319     else
320       flash[:notice] = t 'user.confirm_resend.failure', :name => params[:display_name]
321     end
322
323     redirect_to :action => 'login'
324   end
325
326   def confirm_email
327     if request.post?
328       token = UserToken.find_by_token(params[:confirm_string])
329       if token and token.user.new_email?
330         @user = token.user
331         @user.email = @user.new_email
332         @user.new_email = nil
333         @user.email_valid = true
334         if @user.save
335           flash[:notice] = t 'user.confirm_email.success'
336         else
337           flash[:errors] = @user.errors
338         end
339         token.destroy
340         session[:user] = @user.id
341         redirect_to :action => 'account', :display_name => @user.display_name
342       else
343         flash[:error] = t 'user.confirm_email.failure'
344         redirect_to :action => 'account', :display_name => @user.display_name
345       end
346     end
347   end
348
349   def api_gpx_files
350     doc = OSM::API.new.get_xml_doc
351     @user.traces.each do |trace|
352       doc.root << trace.to_xml_node() if trace.public? or trace.user == @user
353     end
354     render :text => doc.to_s, :content_type => "text/xml"
355   end
356
357   def view
358     @this_user = User.find_by_display_name(params[:display_name])
359
360     if @this_user and
361        (@this_user.visible? or (@user and @user.administrator?))
362       @title = @this_user.display_name
363     else
364       @title = t 'user.no_such_user.title'
365       @not_found_user = params[:display_name]
366       render :action => 'no_such_user', :status => :not_found
367     end
368   end
369
370   def make_friend
371     if params[:display_name]
372       name = params[:display_name]
373       new_friend = User.find_by_display_name(name, :conditions => {:status => ["active", "confirmed"]})
374       friend = Friend.new
375       friend.user_id = @user.id
376       friend.friend_user_id = new_friend.id
377       unless @user.is_friends_with?(new_friend)
378         if friend.save
379           flash[:notice] = t 'user.make_friend.success', :name => name
380           Notifier.deliver_friend_notification(friend)
381         else
382           friend.add_error(t('user.make_friend.failed', :name => name))
383         end
384       else
385         flash[:warning] = t 'user.make_friend.already_a_friend', :name => name
386       end
387
388       if params[:referer]
389         redirect_to params[:referer]
390       else
391         redirect_to :controller => 'user', :action => 'view'
392       end
393     end
394   end
395
396   def remove_friend
397     if params[:display_name]
398       name = params[:display_name]
399       friend = User.find_by_display_name(name, :conditions => {:status => ["active", "confirmed"]})
400       if @user.is_friends_with?(friend)
401         Friend.delete_all "user_id = #{@user.id} AND friend_user_id = #{friend.id}"
402         flash[:notice] = t 'user.remove_friend.success', :name => friend.display_name
403       else
404         flash[:error] = t 'user.remove_friend.not_a_friend', :name => friend.display_name
405       end
406
407       if params[:referer]
408         redirect_to params[:referer]
409       else
410         redirect_to :controller => 'user', :action => 'view'
411       end
412     end
413   end
414
415   ##
416   # sets a user's status
417   def set_status
418     @this_user.update_attributes(:status => params[:status])
419     redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
420   end
421
422   ##
423   # delete a user, marking them as deleted and removing personal data
424   def delete
425     @this_user.delete
426     redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
427   end
428
429   ##
430   # display a list of users matching specified criteria
431   def list
432     if request.post?
433       ids = params[:user].keys.collect { |id| id.to_i }
434
435       User.update_all("status = 'confirmed'", :id => ids) if params[:confirm]
436       User.update_all("status = 'deleted'", :id => ids) if params[:hide]
437
438       redirect_to url_for(:status => params[:status], :ip => params[:ip], :page => params[:page])
439     else
440       conditions = Hash.new
441       conditions[:status] = params[:status] if params[:status]
442       conditions[:creation_ip] = params[:ip] if params[:ip]
443
444       @user_pages, @users = paginate(:users,
445                                      :conditions => conditions,
446                                      :order => :id,
447                                      :per_page => 50)
448     end
449   end
450
451 private
452
453   ##
454   # require that the user is a administrator, or fill out a helpful error message
455   # and return them to the user page.
456   def require_administrator
457     if @user and not @user.administrator?
458       flash[:error] = t('user.filter.not_an_administrator')
459
460       if params[:display_name]
461         redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
462       else
463         redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
464       end
465     elsif not @user
466       redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
467     end
468   end
469
470   ##
471   # ensure that there is a "this_user" instance variable
472   def lookup_this_user
473     @this_user = User.find_by_display_name(params[:display_name])
474   rescue ActiveRecord::RecordNotFound
475     redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name] unless @this_user
476   end
477 end