Add a "database readonly" state that allows all writes to the database
[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 = 1")
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   end
124
125   def login
126     @title = 'login'
127     if params[:user]
128       email_or_display_name = params[:user][:email]
129       pass = params[:user][:password]
130       user = User.authenticate(:username => email_or_display_name, :password => pass)
131       if user
132         session[:user] = user.id
133         if params[:referer]
134           redirect_to params[:referer]
135         else
136           redirect_to :controller => 'site', :action => 'index'
137         end
138         return
139       elsif User.authenticate(:username => email_or_display_name, :password => pass, :inactive => true)
140         @notice = "Sorry, your account is not active yet.<br>Please click on the link in the account confirmation email to activate your account."
141       else
142         @notice = "Sorry, couldn't log in with those details."
143       end
144     end
145   end
146
147   def logout
148     if session[:token]
149       token = UserToken.find_by_token(session[:token])
150       if token
151         token.destroy
152       end
153       session[:token] = nil
154     end
155     session[:user] = nil
156     if params[:referer]
157       redirect_to params[:referer]
158     else
159       redirect_to :controller => 'site', :action => 'index'
160     end
161   end
162
163   def confirm
164     if params[:confirm_action]
165       token = UserToken.find_by_token(params[:confirm_string])
166       if token and !token.user.active?
167         @user = token.user
168         @user.active = true
169         @user.email_valid = true
170         @user.save!
171         token.destroy
172         flash[:notice] = 'Confirmed your account, thanks for signing up!'
173         session[:user] = @user.id
174         redirect_to :action => 'account', :display_name => @user.display_name
175       else
176         @notice = 'Something went wrong confirming that user.'
177       end
178     end
179   end
180
181   def confirm_email
182     if params[:confirm_action]
183       token = UserToken.find_by_token(params[:confirm_string])
184       if token and token.user.new_email?
185         @user = token.user
186         @user.email = @user.new_email
187         @user.new_email = nil
188         @user.active = true
189         @user.email_valid = true
190         @user.save!
191         token.destroy
192         flash[:notice] = 'Confirmed your email address, thanks for signing up!'
193         session[:user] = @user.id
194         redirect_to :action => 'account', :display_name => @user.display_name
195       else
196         @notice = 'Something went wrong confirming that email address.'
197       end
198     end
199   end
200
201   def upload_image
202     @user.image = params[:user][:image]
203     @user.save!
204     redirect_to :controller => 'user', :action => 'view', :display_name => @user.display_name
205   end
206
207   def delete_image
208     @user.image = nil
209     @user.save!
210     redirect_to :controller => 'user', :action => 'view', :display_name => @user.display_name
211   end
212
213   def api_details
214     render :text => @user.to_xml.to_s, :content_type => "text/xml"
215   end
216
217   def api_gpx_files
218     doc = OSM::API.new.get_xml_doc
219     @user.traces.each do |trace|
220       doc.root << trace.to_xml_node() if trace.public? or trace.user == @user
221     end
222     render :text => doc.to_s, :content_type => "text/xml"
223   end
224
225   def view
226     @this_user = User.find_by_display_name(params[:display_name], :conditions => "visible = 1")
227
228     if @this_user
229       @title = @this_user.display_name
230     else
231       @not_found_user = params[:display_name]
232       render :action => 'no_such_user', :status => :not_found
233     end
234   end
235
236   def make_friend
237     if params[:display_name]     
238       name = params[:display_name]
239       new_friend = User.find_by_display_name(name, :conditions => "visible = 1")
240       friend = Friend.new
241       friend.user_id = @user.id
242       friend.friend_user_id = new_friend.id
243       unless @user.is_friends_with?(new_friend)
244         if friend.save
245           flash[:notice] = "#{name} is now your friend."
246           Notifier.deliver_friend_notification(friend)
247         else
248           friend.add_error("Sorry, failed to add #{name} as a friend.")
249         end
250       else
251         flash[:notice] = "You are already friends with #{name}."  
252       end
253
254       redirect_to :controller => 'user', :action => 'view'
255     end
256   end
257
258   def remove_friend
259     if params[:display_name]     
260       name = params[:display_name]
261       friend = User.find_by_display_name(name, :conditions => "visible = 1")
262       if @user.is_friends_with?(friend)
263         Friend.delete_all "user_id = #{@user.id} AND friend_user_id = #{friend.id}"
264         flash[:notice] = "#{friend.display_name} was removed from your friends."
265       else
266         flash[:notice] = "#{friend.display_name} is not one of your friends."
267       end
268
269       redirect_to :controller => 'user', :action => 'view'
270     end
271   end
272 end