Allow see posts history to unlogged users
[shapado:piglops-shapado.git] / app / controllers / answers_controller.rb
1 class AnswersController < ApplicationController
2   before_filter :login_required, :except => [:show, :create, :index, :history, :diff]
3   before_filter :check_permissions, :only => [:destroy, :create]
4   before_filter :check_update_permissions, :only => [:edit, :update, :revert]
5
6   helper :votes
7
8   def index
9     exclude = [:votes, :_keywords]
10     if params[:question_id]
11       @question = current_group.questions.by_slug(params[:question_id])
12       @answers = @question.answers.without(exclude).page(params["page"])
13     else
14       @answers = current_group.answers.without(exclude).page(params["page"])
15     end
16
17     respond_to do |format|
18       format.html
19       format.json { render :json => @answers }
20     end
21   end
22
23   def history
24     @answer = current_group.answers.find(params[:id])
25     @question = @answer.question
26
27     respond_to do |format|
28       format.html
29       format.json { render :json => @answer.versions.to_json }
30     end
31   end
32
33   def diff
34     @answer = current_group.answers.find(params[:id])
35     @question = @answer.question
36     @prev = params[:prev]
37     @curr = params[:curr]
38     if @prev.blank? || @curr.blank? || @prev == @curr
39       flash[:error] = "please, select two versions"
40       render :history
41     else
42       if @prev
43         @prev = (@prev == "current" ? :current : @prev.to_i)
44       end
45
46       if @curr
47         @curr = (@curr == "current" ? :current : @curr.to_i)
48       end
49     end
50   end
51
52   def revert
53     @question = @answer.question
54     @answer.load_version(params[:version].to_i)
55
56     respond_to do |format|
57       format.html
58     end
59   end
60
61   def show
62     @answer = current_group.answers.find!(params[:id])
63     @question = @answer.question
64     respond_to do |format|
65       format.html
66       format.mobile
67       format.json  { render :json => @answer.to_json }
68     end
69   end
70
71   def create
72     @answer = Answer.new
73     @answer.safe_update(%w[body wiki anonymous position], params[:answer])
74     @answer.anonymous = params[:answer][:anonymous] if current_group.enable_anonymous
75     @question = current_group.questions.by_slug(params[:question_id])
76
77     @answer.question = @question
78     @answer.group_id = @question.group_id
79
80     # workaround, seems like mm default values are broken
81     @answer.votes_count = 0
82     @answer.votes_average = 0
83     @answer.flags_count = 0
84
85     @answer.user = current_user
86     if !logged_in?
87       if recaptcha_valid? && params[:user]
88         @user = User.where(:email => params[:user][:email]).first
89         if @user.present?
90           if !@user.anonymous
91             flash[:notice] = "The user is already registered, please log in"
92             return create_draft!
93           else
94             @answer.user = @user
95           end
96         elsif current_group.enable_anonymous
97           @user = User.new(:anonymous => true, :login => "Anonymous")
98           @user.safe_update(%w[name email website], params[:user])
99           @user.login = @user.name if @user.name.present?
100           @user.save!
101           @answer.user = @user
102         end
103       elsif !AppConfig.recaptcha["activate"] || !current_group.enable_anonymous
104         return create_draft!
105       end
106     end
107
108     respond_to do |format|
109       if (logged_in? || (recaptcha_valid? && @answer.user.valid?)) && @answer.save
110         @question.add_contributor(current_user || @answer.user)
111         link = question_answer_url(@question, @answer)
112
113         Jobs::Activities.async.on_create_answer(@answer.id).commit!
114         Jobs::Answers.async.on_create_answer(@question.id, @answer.id, link).commit!
115
116         @question.answer_added!
117         sweep_question(@question) # TODO move to magent
118         html = ""
119         if params[:facebook]
120           html = render_to_string(:partial => "facebook/answer",
121                                   :locals => {:answer => @answer, :question => @question})
122         else
123           html = render_to_string(:partial => "questions/answer",
124                                   :locals => {:answer => @answer, :question => @question})
125         end
126         Magent::WebSocketChannel.push({id: "newanswer", object_id: @answer.id, name: @answer.body, channel_id: current_group.slug,
127                                        owner_id: @answer.user.id, owner_name: @answer.user.login,
128                                        question_id: @question.id, question_title: @question.title,
129                                        html: html})
130
131         flash[:notice] = t(:flash_notice, :scope => "answers.create")
132         format.html{redirect_to question_path(@question)}
133         format.mobile{redirect_to question_path(@question, :format => :mobile)}
134         format.json { render :json => @answer.to_json(:except => %w[_keywords]) }
135         format.js do
136           render(:json => {:success => true, :message => flash[:notice],
137                            :html => html, :question_id => @question.id}.to_json)
138         end
139       else
140         @answer.errors.add(:captcha, "is invalid") if !logged_in? && !recaptcha_valid?
141
142         errors = @answer.errors
143         errors.merge!(@answer.user.errors) if @answer.user && @answer.user.anonymous && !@answer.user.valid?
144         puts errors.full_messages
145
146         flash.now[:error] = errors.full_messages
147         format.html{redirect_to question_path(@question)}
148         format.json { render :json => errors, :status => :unprocessable_entity }
149         format.js {render :json => {:success => false, :message => flash.now[:error] }.to_json }
150       end
151     end
152   end
153
154   def edit
155     @question = @answer.question
156     respond_to do |format|
157       format.html
158       format.js {render :json => {:success => false, :html => render_to_string(:partial => "answers/edit_form",
159                                    :locals => {:question => @question, :answer => @answer}) }.to_json }
160     end
161   end
162
163   def update
164     respond_to do |format|
165       @question = @answer.question
166       @answer.safe_update(%w[body wiki version_message], params[:answer])
167       @answer.updated_by = current_user
168
169       if @answer.valid? && @answer.save
170         @question.add_contributor(current_user)
171
172         sweep_answer(@answer)
173
174         Question.update_last_target(@question.id, @answer)
175
176         flash[:notice] = t(:flash_notice, :scope => "answers.update")
177
178         Jobs::Activities.async.on_update_answer(@answer.id).commit!
179
180         Magent::WebSocketChannel.push({id: "updateanswer", object_id: @answer.id, name: @answer.body, channel_id: current_group.slug,
181                                        owner_id: @answer.user.id, owner_name: @answer.user.login,
182                                        question_id: @question.id, question_title: @question.title,
183                                        html: render_to_string(:partial => "questions/answer",
184                                                               :locals => {:answer => @answer, :question => @question})})
185
186         format.html { redirect_to(question_path(@answer.question, :anchor => "answer#{@answer.id}")) }
187         format.json { head :ok }
188       else
189         format.html { render :action => "edit" }
190         format.json { render :json => @answer.errors, :status => :unprocessable_entity }
191       end
192     end
193   end
194
195   def destroy
196     @question = @answer.question
197     if @answer.user_id == current_user.id
198       @answer.user.update_reputation(:delete_answer, current_group)
199     end
200     Jobs::Activities.async.on_destroy_answer(current_user.id, @answer.attributes).commit!
201     sweep_answer(@answer)
202     @answer.destroy
203     @question.answer_removed!
204     sweep_question(@question)
205
206     respond_to do |format|
207       format.html { redirect_to(question_path(@question)) }
208       format.json { head :ok }
209     end
210   end
211
212   def favorite
213     @answer = Answer.find(params[:id])
214     @answer.add_favorite!(current_user)
215     link = question_answer_url(@answer.question, @answer)
216     Jobs::Mailer.async.on_favorite_answer(@answer.id, current_user.id).commit!
217     Jobs::Answers.async.on_favorite_answer(@answer.id, current_user.id, link).commit!
218
219     respond_to do |format|
220       flash[:notice] = t("favorites.create.success")
221       format.html { redirect_to(question_path(@answer.question)) }
222       format.mobile { redirect_to(question_path(@answer.question, :format => :mobile)) }
223       format.json { head :ok }
224       format.js {
225         render(:json => {:success => true,
226                  :message => flash[:notice], :increment => 1 }.to_json)
227       }
228     end
229   end
230
231   def unfavorite
232     @answer = Answer.find(params[:id])
233     @answer.remove_favorite!(current_user)
234
235     flash[:notice] = t("unfavorites.create.success")
236     respond_to do |format|
237       format.html { redirect_to(question_path(@answer.question)) }
238       format.mobile { redirect_to(question_path(@answer.question, :format => :mobile)) }
239       format.js {
240         render(:json => {:success => true,
241                  :message => flash[:notice], :increment => -1 }.to_json)
242       }
243       format.json  { head :ok }
244     end
245   end
246
247   protected
248   def check_permissions
249     if params[:id]
250       @answer = current_group.answers.find(params[:id])
251       if !@answer.nil?
252         unless (current_user.can_modify?(@answer) || current_user.mod_of?(@answer.group))
253           flash[:error] = t("global.permission_denied")
254           redirect_to question_path(@answer.question)
255         end
256       else
257         redirect_to questions_path
258       end
259     else
260       if logged_in? && !current_user.can_answer_on?(current_group)
261         reputation = current_group.reputation_constrains["answer"]
262
263         flash[:error] = I18n.t("users.messages.errors.reputation_needed",
264                               :min_reputation => reputation,
265                               :action => I18n.t("users.actions.answer"))
266
267         respond_to do |format|
268           format.html {redirect_to questions_path}
269           format.js {
270             render(:json => {:success => false,
271                            :message => flash[:error] }.to_json)
272           }
273         end
274       end
275     end
276   end
277
278   def check_update_permissions
279     @answer = current_group.answers.find!(params[:id])
280
281     allow_update = true
282     unless @answer.nil?
283       if !current_user.can_modify?(@answer)
284         if @answer.wiki
285           if !current_user.can_edit_wiki_post_on?(@answer.group)
286             allow_update = false
287             reputation = @answer.group.reputation_constrains["edit_wiki_post"]
288             flash[:error] = I18n.t("users.messages.errors.reputation_needed",
289                                         :min_reputation => reputation,
290                                         :action => I18n.t("users.actions.edit_wiki_post"))
291           end
292         else
293           if !current_user.can_edit_others_posts_on?(@answer.group)
294             allow_update = false
295             reputation = @answer.group.reputation_constrains["edit_others_posts"]
296             flash[:error] = I18n.t("users.messages.errors.reputation_needed",
297                                         :min_reputation => reputation,
298                                         :action => I18n.t("users.actions.edit_others_posts"))
299           end
300         end
301         return redirect_to question_path(@answer.question) if !allow_update
302       end
303     else
304       return redirect_to questions_path
305     end
306   end
307
308   def create_draft!
309     draft = Draft.create(:answer => @answer)
310     session[:draft] = draft.id
311     login_required
312   end
313 end