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