Merge api06 branch to trunk.
[rails.git] / app / controllers / user_controller.rb
1 class UserController < ApplicationController
2   layout 'site'
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 :require_user, :only => [:set_home, :account, :go_public, :make_friend, :remove_friend, :upload_image, :delete_image]
7   before_filter :check_database_readable, :except => [:api_details, :api_gpx_files]
8   before_filter :check_database_writable, :only => [:login, :new, :set_home, :account, :go_public, :make_friend, :remove_friend, :upload_image, :delete_image]
9   before_filter :check_api_readable, :only => [:api_details, :api_gpx_files]
10
11   filter_parameter_logging :password, :pass_crypt, :pass_crypt_confirmation
12
13   def save
14     @title = 'create account'
15
16     if Acl.find_by_address(request.remote_ip, :conditions => {:k => "no_account_creation"})
17       render :action => 'new'
18     else
19       @user = User.new(params[:user])
20
21       @user.visible = true
22       @user.data_public = true
23       @user.description = "" if @user.description.nil?
24       @user.creation_ip = request.remote_ip
25
26       if @user.save
27         flash[:notice] = "User was successfully created. Check your email for a confirmation note, and you\'ll be mapping in no time :-)<br>Please note that you won't be able to login until you've received and confirmed your email address."
28         Notifier.deliver_signup_confirm(@user, @user.tokens.create)
29         redirect_to :action => 'login'
30       else
31         render :action => 'new'
32       end
33     end
34   end
35
36   def account
37     @title = 'edit account'
38     if params[:user] and params[:user][:display_name] and params[:user][:description]
39       if params[:user][:email] != @user.email
40         @user.new_email = params[:user][:email]
41       end
42
43       @user.display_name = params[:user][:display_name]
44
45       if params[:user][:pass_crypt].length > 0 or params[:user][:pass_crypt_confirmation].length > 0
46         @user.pass_crypt = params[:user][:pass_crypt]
47         @user.pass_crypt_confirmation = params[:user][:pass_crypt_confirmation]
48       end
49
50       @user.description = params[:user][:description]
51       @user.home_lat = params[:user][:home_lat]
52       @user.home_lon = params[:user][:home_lon]
53
54       if @user.save
55         if params[:user][:email] == @user.new_email
56           @notice = "User information updated successfully. Check your email for a note to confirm your new email address."
57           Notifier.deliver_email_confirm(@user, @user.tokens.create)
58         else
59           @notice = "User information updated successfully."
60         end
61       end
62     end
63   end
64
65   def set_home
66     if params[:user][:home_lat] and params[:user][:home_lon]
67       @user.home_lat = params[:user][:home_lat].to_f
68       @user.home_lon = params[:user][:home_lon].to_f
69       if @user.save
70         flash[:notice] = "Home location saved successfully."
71         redirect_to :controller => 'user', :action => 'account'
72       end
73     end
74   end
75
76   def go_public
77     @user.data_public = true
78     @user.save
79     flash[:notice] = 'All your edits are now public.'
80     redirect_to :controller => 'user', :action => 'account', :display_name => @user.display_name
81   end
82
83   def lost_password
84     @title = 'lost password'
85     if params[:user] and params[:user][:email]
86       user = User.find_by_email(params[:user][:email], :conditions => {:visible => true})
87
88       if user
89         token = user.tokens.create
90         Notifier.deliver_lost_password(user, token)
91         @notice = "Sorry you lost it :-( but an email is on its way so you can reset it soon."
92       else
93         @notice = "Couldn't find that email address, sorry."
94       end
95     end
96   end
97
98   def reset_password
99     @title = 'reset password'
100     if params['token']
101       token = UserToken.find_by_token(params[:token])
102       if token
103         pass = OSM::make_token(8)
104         user = token.user
105         user.pass_crypt = pass
106         user.pass_crypt_confirmation = pass
107         user.active = true
108         user.email_valid = true
109         user.save!
110         token.destroy
111         Notifier.deliver_reset_password(user, pass)
112         flash[:notice] = "Your password has been changed and is on its way to your mailbox :-)"
113       else
114         flash[:notice] = "Didn't find that token, check the URL maybe?"
115       end
116     end
117
118     redirect_to :action => 'login'
119   end
120
121   def new
122     @title = 'create account'
123     # The user is logged in already, so don't show them the signup page, instead
124     # send them to the home page
125     redirect_to :controller => 'site', :action => 'index' if session[:user]
126   end
127
128   def login
129     if session[:user]
130       # The user is logged in already, if the referer param exists, redirect them to that
131       if params[:referer]
132         redirect_to params[:referer]
133       else
134         redirect_to :controller => 'site', :action => 'index'
135       end
136       return
137     end
138     @title = 'login'
139     if params[:user]
140       email_or_display_name = params[:user][:email]
141       pass = params[:user][:password]
142       user = User.authenticate(:username => email_or_display_name, :password => pass)
143       if user
144         session[:user] = user.id
145         if params[:referer]
146           redirect_to params[:referer]
147         else
148           redirect_to :controller => 'site', :action => 'index'
149         end
150         return
151       elsif User.authenticate(:username => email_or_display_name, :password => pass, :inactive => true)
152         @notice = "Sorry, your account is not active yet.<br>Please click on the link in the account confirmation email to activate your account."
153       else
154         @notice = "Sorry, couldn't log in with those details."
155       end
156     end
157   end
158
159   def logout
160     if session[:token]
161       token = UserToken.find_by_token(session[:token])
162       if token
163         token.destroy
164       end
165       session[:token] = nil
166     end
167     session[:user] = nil
168     if params[:referer]
169       redirect_to params[:referer]
170     else
171       redirect_to :controller => 'site', :action => 'index'
172     end
173   end
174
175   def confirm
176     if params[:confirm_action]
177       token = UserToken.find_by_token(params[:confirm_string])
178       if token and !token.user.active?
179         @user = token.user
180         @user.active = true
181         @user.email_valid = true
182         @user.save!
183         token.destroy
184         flash[:notice] = 'Confirmed your account, thanks for signing up!'
185         session[:user] = @user.id
186         redirect_to :action => 'account', :display_name => @user.display_name
187       else
188         @notice = 'Something went wrong confirming that user.'
189       end
190     end
191   end
192
193   def confirm_email
194     if params[:confirm_action]
195       token = UserToken.find_by_token(params[:confirm_string])
196       if token and token.user.new_email?
197         @user = token.user
198         @user.email = @user.new_email
199         @user.new_email = nil
200         @user.active = true
201         @user.email_valid = true
202         @user.save!
203         token.destroy
204         flash[:notice] = 'Confirmed your email address, thanks for signing up!'
205         session[:user] = @user.id
206         redirect_to :action => 'account', :display_name => @user.display_name
207       else
208         @notice = 'Something went wrong confirming that email address.'
209       end
210     end
211   end
212
213   def upload_image
214     @user.image = params[:user][:image]
215     @user.save!
216     redirect_to :controller => 'user', :action => 'view', :display_name => @user.display_name
217   end
218
219   def delete_image
220     @user.image = nil
221     @user.save!
222     redirect_to :controller => 'user', :action => 'view', :display_name => @user.display_name
223   end
224
225   def api_details
226     render :text => @user.to_xml.to_s, :content_type => "text/xml"
227   end
228
229   def api_gpx_files
230     doc = OSM::API.new.get_xml_doc
231     @user.traces.each do |trace|
232       doc.root << trace.to_xml_node() if trace.public? or trace.user == @user
233     end
234     render :text => doc.to_s, :content_type => "text/xml"
235   end
236
237   def view
238     @this_user = User.find_by_display_name(params[:display_name], :conditions => {:visible => true})
239
240     if @this_user
241       @title = @this_user.display_name
242     else
243       @not_found_user = params[:display_name]
244       render :action => 'no_such_user', :status => :not_found
245     end
246   end
247
248   def make_friend
249     if params[:display_name]     
250       name = params[:display_name]
251       new_friend = User.find_by_display_name(name, :conditions => {:visible => true})
252       friend = Friend.new
253       friend.user_id = @user.id
254       friend.friend_user_id = new_friend.id
255       unless @user.is_friends_with?(new_friend)
256         if friend.save
257           flash[:notice] = "#{name} is now your friend."
258           Notifier.deliver_friend_notification(friend)
259         else
260           friend.add_error("Sorry, failed to add #{name} as a friend.")
261         end
262       else
263         flash[:notice] = "You are already friends with #{name}."  
264       end
265
266       redirect_to :controller => 'user', :action => 'view'
267     end
268   end
269
270   def remove_friend
271     if params[:display_name]     
272       name = params[:display_name]
273       friend = User.find_by_display_name(name, :conditions => {:visible => true})
274       if @user.is_friends_with?(friend)
275         Friend.delete_all "user_id = #{@user.id} AND friend_user_id = #{friend.id}"
276         flash[:notice] = "#{friend.display_name} was removed from your friends."
277       else
278         flash[:notice] = "#{friend.display_name} is not one of your friends."
279       end
280
281       redirect_to :controller => 'user', :action => 'view'
282     end
283   end
284 end