]> git.openstreetmap.org Git - rails.git/blob - app/controllers/diary_entries_controller.rb
Require user names to be unique after unicode normalisation
[rails.git] / app / controllers / diary_entries_controller.rb
1 class DiaryEntriesController < ApplicationController
2   include UserMethods
3
4   layout "site", :except => :rss
5
6   before_action :authorize_web
7   before_action :set_locale
8   before_action :check_database_readable
9
10   authorize_resource
11
12   before_action :lookup_user, :only => [:show, :comments]
13   before_action :check_database_writable, :only => [:new, :create, :edit, :update, :comment, :hide, :hidecomment, :subscribe, :unsubscribe]
14   before_action :allow_thirdparty_images, :only => [:new, :create, :edit, :update, :index, :show, :comments]
15
16   def index
17     if params[:display_name]
18       @user = User.active.find_by(:display_name => params[:display_name])
19
20       if @user
21         @title = t ".user_title", :user => @user.display_name
22         entries = @user.diary_entries
23       else
24         render_unknown_user params[:display_name]
25         return
26       end
27     elsif params[:friends]
28       if current_user
29         @title = t ".title_friends"
30         entries = DiaryEntry.where(:user => current_user.friends)
31       else
32         require_user
33         return
34       end
35     elsif params[:nearby]
36       if current_user
37         @title = t ".title_nearby"
38         entries = DiaryEntry.where(:user => current_user.nearby)
39       else
40         require_user
41         return
42       end
43     else
44       entries = DiaryEntry.joins(:user).where(:users => { :status => %w[active confirmed] })
45
46       if params[:language]
47         @title = t ".in_language_title", :language => Language.find(params[:language]).english_name
48         entries = entries.where(:language_code => params[:language])
49       else
50         @title = t ".title"
51       end
52     end
53
54     entries = entries.visible unless can? :unhide, DiaryEntry
55
56     @params = params.permit(:display_name, :friends, :nearby, :language)
57
58     @entries, @newer_entries_id, @older_entries_id = get_page_items(entries, [:user, :language])
59   end
60
61   def show
62     entries = @user.diary_entries
63     entries = entries.visible unless can? :unhide, DiaryEntry
64     @entry = entries.find_by(:id => params[:id])
65     if @entry
66       @title = t ".title", :user => params[:display_name], :title => @entry.title
67       @comments = can?(:unhidecomment, DiaryEntry) ? @entry.comments : @entry.visible_comments
68     else
69       @title = t "diary_entries.no_such_entry.title", :id => params[:id]
70       render :action => "no_such_entry", :status => :not_found
71     end
72   end
73
74   def new
75     @title = t ".title"
76
77     default_lang = current_user.preferences.find_by(:k => "diary.default_language")
78     lang_code = default_lang ? default_lang.v : current_user.preferred_language
79     @diary_entry = DiaryEntry.new(entry_params.merge(:language_code => lang_code))
80     set_map_location
81     render :action => "new"
82   end
83
84   def edit
85     @title = t ".title"
86     @diary_entry = DiaryEntry.find(params[:id])
87
88     redirect_to diary_entry_path(@diary_entry.user, @diary_entry) if current_user != @diary_entry.user
89
90     set_map_location
91   rescue ActiveRecord::RecordNotFound
92     render :action => "no_such_entry", :status => :not_found
93   end
94
95   def create
96     @title = t "diary_entries.new.title"
97
98     @diary_entry = DiaryEntry.new(entry_params)
99     @diary_entry.user = current_user
100
101     if @diary_entry.save
102       default_lang = current_user.preferences.find_by(:k => "diary.default_language")
103       if default_lang
104         default_lang.v = @diary_entry.language_code
105         default_lang.save!
106       else
107         current_user.preferences.create(:k => "diary.default_language", :v => @diary_entry.language_code)
108       end
109
110       # Subscribe user to diary comments
111       @diary_entry.subscriptions.create(:user => current_user)
112
113       redirect_to :action => "index", :display_name => current_user.display_name
114     else
115       render :action => "new"
116     end
117   end
118
119   def update
120     @title = t "diary_entries.edit.title"
121     @diary_entry = DiaryEntry.find(params[:id])
122
123     if current_user != @diary_entry.user ||
124        (params[:diary_entry] && @diary_entry.update(entry_params))
125       redirect_to diary_entry_path(@diary_entry.user, @diary_entry)
126     else
127       set_map_location
128       render :action => "edit"
129     end
130   rescue ActiveRecord::RecordNotFound
131     render :action => "no_such_entry", :status => :not_found
132   end
133
134   def comment
135     @entry = DiaryEntry.find(params[:id])
136     @comments = @entry.visible_comments
137     @diary_comment = @entry.comments.build(comment_params)
138     @diary_comment.user = current_user
139     if @diary_comment.save
140
141       # Notify current subscribers of the new comment
142       @entry.subscribers.visible.each do |user|
143         UserMailer.diary_comment_notification(@diary_comment, user).deliver_later if current_user != user
144       end
145
146       # Add the commenter to the subscribers if necessary
147       @entry.subscriptions.create(:user => current_user) unless @entry.subscribers.exists?(current_user.id)
148
149       redirect_to diary_entry_path(@entry.user, @entry)
150     else
151       render :action => "show"
152     end
153   rescue ActiveRecord::RecordNotFound
154     render :action => "no_such_entry", :status => :not_found
155   end
156
157   def subscribe
158     diary_entry = DiaryEntry.find(params[:id])
159
160     diary_entry.subscriptions.create(:user => current_user) unless diary_entry.subscribers.exists?(current_user.id)
161
162     redirect_to diary_entry_path(diary_entry.user, diary_entry)
163   rescue ActiveRecord::RecordNotFound
164     render :action => "no_such_entry", :status => :not_found
165   end
166
167   def unsubscribe
168     diary_entry = DiaryEntry.find(params[:id])
169
170     diary_entry.subscriptions.where(:user => current_user).delete_all if diary_entry.subscribers.exists?(current_user.id)
171
172     redirect_to diary_entry_path(diary_entry.user, diary_entry)
173   rescue ActiveRecord::RecordNotFound
174     render :action => "no_such_entry", :status => :not_found
175   end
176
177   def rss
178     if params[:display_name]
179       user = User.active.find_by(:display_name => params[:display_name])
180
181       if user
182         @entries = user.diary_entries
183         @title = t("diary_entries.feed.user.title", :user => user.display_name)
184         @description = t("diary_entries.feed.user.description", :user => user.display_name)
185         @link = url_for :action => "index", :display_name => user.display_name, :host => Settings.server_url, :protocol => Settings.server_protocol
186       else
187         head :not_found
188         return
189       end
190     else
191       @entries = DiaryEntry.joins(:user).where(:users => { :status => %w[active confirmed] })
192
193       # Items can't be flagged as deleted in the RSS format.
194       # For the general feeds, allow a delay before publishing, to help spam fighting
195       @entries = @entries.where("created_at < :time", :time => Settings.diary_feed_delay.hours.ago)
196
197       if params[:language]
198         @entries = @entries.where(:language_code => params[:language])
199         @title = t("diary_entries.feed.language.title", :language_name => Language.find(params[:language]).english_name)
200         @description = t("diary_entries.feed.language.description", :language_name => Language.find(params[:language]).english_name)
201         @link = url_for :action => "index", :language => params[:language], :host => Settings.server_url, :protocol => Settings.server_protocol
202       else
203         @title = t("diary_entries.feed.all.title")
204         @description = t("diary_entries.feed.all.description")
205         @link = url_for :action => "index", :host => Settings.server_url, :protocol => Settings.server_protocol
206       end
207     end
208     @entries = @entries.visible.includes(:user).order("created_at DESC").limit(20)
209   end
210
211   def hide
212     entry = DiaryEntry.find(params[:id])
213     entry.update(:visible => false)
214     redirect_to :action => "index", :display_name => entry.user.display_name
215   end
216
217   def unhide
218     entry = DiaryEntry.find(params[:id])
219     entry.update(:visible => true)
220     redirect_to :action => "index", :display_name => entry.user.display_name
221   end
222
223   def hidecomment
224     comment = DiaryComment.find(params[:comment])
225     comment.update(:visible => false)
226     redirect_to diary_entry_path(comment.diary_entry.user, comment.diary_entry)
227   end
228
229   def unhidecomment
230     comment = DiaryComment.find(params[:comment])
231     comment.update(:visible => true)
232     redirect_to diary_entry_path(comment.diary_entry.user, comment.diary_entry)
233   end
234
235   def comments
236     @title = t ".title", :user => @user.display_name
237
238     comments = DiaryComment.where(:user => @user)
239     comments = comments.visible unless can? :unhidecomment, DiaryEntry
240
241     @params = params.permit(:display_name, :before, :after)
242
243     @comments, @newer_comments_id, @older_comments_id = get_page_items(comments, [:user])
244   end
245
246   private
247
248   ##
249   # return permitted diary entry parameters
250   def entry_params
251     params.require(:diary_entry).permit(:title, :body, :language_code, :latitude, :longitude)
252   rescue ActionController::ParameterMissing
253     ActionController::Parameters.new.permit(:title, :body, :language_code, :latitude, :longitude)
254   end
255
256   ##
257   # return permitted diary comment parameters
258   def comment_params
259     params.require(:diary_comment).permit(:body)
260   end
261
262   ##
263   # decide on a location for the diary entry map
264   def set_map_location
265     if @diary_entry.latitude && @diary_entry.longitude
266       @lon = @diary_entry.longitude
267       @lat = @diary_entry.latitude
268       @zoom = 12
269     elsif !current_user.home_location?
270       @lon = params[:lon] || -0.1
271       @lat = params[:lat] || 51.5
272       @zoom = params[:zoom] || 4
273     else
274       @lon = current_user.home_lon
275       @lat = current_user.home_lat
276       @zoom = 12
277     end
278   end
279
280   def get_page_items(items, includes)
281     id_column = "#{items.table_name}.id"
282     page_items = if params[:before]
283                    items.where("#{id_column} < ?", params[:before]).order(:id => :desc)
284                  elsif params[:after]
285                    items.where("#{id_column} > ?", params[:after]).order(:id => :asc)
286                  else
287                    items.order(:id => :desc)
288                  end
289
290     page_items = page_items.limit(20)
291     page_items = page_items.includes(includes)
292     page_items = page_items.sort.reverse
293
294     newer_items_id = page_items.first.id if page_items.count.positive? && items.exists?(["#{id_column} > ?", page_items.first.id])
295     older_items_id = page_items.last.id if page_items.count.positive? && items.exists?(["#{id_column} < ?", page_items.last.id])
296
297     [page_items, newer_items_id, older_items_id]
298   end
299 end