diff --git a/app/controllers/answers_controller.rb b/app/controllers/answers_controller.rb index fcd60c6391278897330d8d34c398671cd82cc965..a30ba3f64b51dff519403da0fb387232fd879511 100644 --- a/app/controllers/answers_controller.rb +++ b/app/controllers/answers_controller.rb @@ -1,166 +1,10 @@ # Web controller. Provides actions that relate to answers. Pretty much the standard set of resources, really - it's # questions that have a few more actions. class AnswersController < ApplicationController - before_action :authenticate_user!, only: [:new, :create, :edit, :update, :destroy, :undelete, :convert_to_comment] - before_action :set_answer, only: [:edit, :update, :destroy, :undelete, :convert_to_comment] + before_action :authenticate_user!, only: [:convert_to_comment] + before_action :set_answer, only: [:convert_to_comment] before_action :verify_moderator, only: [:convert_to_comment] - before_action :check_if_answer_locked, only: [:edit, :update, :destroy, :undelete, :convert_to_comment] - - def new - @answer = Answer.new - @question = Question.find params[:id] - end - - def create - @question = Question.find params[:id] - - @answer = Answer.new(answer_params.merge(parent: @question, user: current_user, score: 0, - body: helpers.post_markdown(:answer, :body_markdown), - last_activity: DateTime.now, last_activity_by: current_user, - category: @question.category)) - - recent_second_level_posts = Post.where(created_at: 24.hours.ago..Time.zone.now, user: current_user) - .where(post_type_id: second_level_post_types).count - - max_slps = SiteSetting[if current_user.privilege?('unrestricted') - 'RL_SecondLevelPosts' - else - 'RL_NewUserSecondLevelPosts' - end] - - post_limit_msg = if current_user.privilege? 'unrestricted' - "You may only post #{max_slps} answers per day." - else - "You may only post #{max_slps} answers per day. " \ - 'Once you have some well-received posts, that limit will increase.' - end - - if recent_second_level_posts >= max_slps - @answer.errors.add :base, post_limit_msg - AuditLog.rate_limit_log(event_type: 'second_level_post', related: @question, user: current_user, - comment: "limit: #{max_slps}\n\npost:\n#{@answer.attributes_print}") - render :new, status: :bad_request - return - end - - unless current_user.id == @question.user.id - @question.user.create_notification("New answer to your question '#{@question.title.truncate(50)}'", - share_question_url(@question)) - end - if @answer.save - @question.update(last_activity: DateTime.now, last_activity_by: current_user) - unless current_user.id == @question.user.id - @question.user.create_notification("New answer to your question '#{@question.title.truncate(50)}'", - share_question_url(@question)) - end - redirect_to url_for(controller: :questions, action: :show, id: params[:id]) - else - render :new, status: :unprocessable_entity - end - end - - def edit; end - - def update - can_post_in_category = @answer.parent.category.present? && - (@answer.parent.category.min_trust_level || -1) <= current_user&.trust_level - unless current_user&.has_post_privilege?('edit_posts', @answer) && can_post_in_category - return update_as_suggested_edit - end - - if params[:answer][:body_markdown] == @answer.body_markdown - flash[:danger] = "No changes were saved because you didn't edit the post." - return redirect_to question_path(@answer.parent) - end - - before = @answer.body_markdown - if @answer.update(answer_params.merge(body: helpers.post_markdown(:answer, :body_markdown), - last_activity: DateTime.now, last_activity_by: current_user, - last_edited_at: DateTime.now, last_edited_by: current_user, - license_id: @answer.license_id)) - PostHistory.post_edited(@answer, current_user, before: before, - after: params[:answer][:body_markdown], comment: params[:edit_comment]) - redirect_to share_answer_path(qid: @answer.parent_id, id: @answer.id) - else - render :edit - end - end - - def update_as_suggested_edit - return if check_edits_limit! @answer - - if params[:answer][:body_markdown] == @answer.body_markdown - flash[:danger] = "No changes were saved because you didn't edit the post." - return redirect_to question_path(@answer.parent) - end - - updates = { - post: @answer, - user: current_user, - community: @answer.community, - body: helpers.post_markdown(:answer, :body_markdown), - body_markdown: params[:answer][:body_markdown] == @answer.body_markdown ? nil : params[:answer][:body_markdown], - comment: params[:edit_comment], - active: true, accepted: false, - decided_at: nil, decided_by: nil, - rejected_comment: nil - } - - @edit = SuggestedEdit.new(updates) - if @edit.save - @answer.user.create_notification("Edit suggested on your answer to #{@answer.parent.title.truncate(50)}", - share_answer_url(qid: @answer.parent_id, id: @answer.id)) - redirect_to share_answer_path(qid: @answer.parent_id, id: @answer.id) - else - @answer.errors = @edit.errors - render :edit - end - end - - def destroy - unless check_your_privilege('flag_curate', @answer, false) - flash[:danger] = helpers.ability_err_msg(:flag_curate, 'delete this answer') - redirect_to(question_path(@answer.parent)) && return - end - - if @answer.deleted - flash[:danger] = "Can't delete a deleted answer." - redirect_to(question_path(@answer.parent)) && return - end - - if @answer.update(deleted: true, deleted_at: DateTime.now, deleted_by: current_user, - last_activity: DateTime.now, last_activity_by: current_user) - PostHistory.post_deleted(@answer, current_user) - else - flash[:danger] = "Can't delete this answer right now. Try again later." - end - redirect_to question_path(@answer.parent) - end - - def undelete - unless check_your_privilege('flag_curate', @answer, false) - flash[:danger] = flash[:danger] = helpers.ability_err_msg(:flag_curate, 'undelete this answer') - redirect_to(question_path(@answer.parent)) && return - end - - unless @answer.deleted - flash[:danger] = "Can't undelete an undeleted answer." - redirect_to(question_path(@answer.parent)) && return - end - - if @answer.deleted_by.is_moderator && !current_user.is_moderator - flash[:danger] = 'You cannot undelete this post deleted by a moderator.' - redirect_to(question_path(@answer.parent)) && return - end - - if @answer.update(deleted: false, deleted_at: nil, deleted_by: nil, - last_activity: DateTime.now, last_activity_by: current_user) - PostHistory.post_undeleted(@answer, current_user) - else - flash[:danger] = "Can't undelete this answer right now. Try again later." - end - redirect_to question_path(@answer.parent) - end + before_action :check_if_answer_locked, only: [:convert_to_comment] def convert_to_comment text = @answer.body_markdown @@ -176,10 +20,6 @@ class AnswersController < ApplicationController private - def answer_params - params.require(:answer).permit(:body_markdown, :license_id) - end - def set_answer @answer = Answer.find params[:id] end diff --git a/app/controllers/articles_controller.rb b/app/controllers/articles_controller.rb index 21debf8bbf969c23acfe8368eef4b02c14ea59ad..7f9d4ba3537b138736060c424a47128486047b76 100644 --- a/app/controllers/articles_controller.rb +++ b/app/controllers/articles_controller.rb @@ -1,137 +1,11 @@ class ArticlesController < ApplicationController before_action :set_article before_action :check_article - before_action :check_if_article_locked, only: [:edit, :update, :destroy, :undelete, :close, :reopen] - - def show - if @article.deleted? - check_your_privilege('flag_curate', @article) # || return - end - end def share redirect_to article_path(params[:id]) end - def edit; end - - def update - can_post_in_category = @article.category.present? && - (@article.category.min_trust_level || -1) <= current_user&.trust_level - unless current_user&.has_post_privilege?('edit_posts', @article) && can_post_in_category - return update_as_suggested_edit - end - - tags_cache = params[:article][:tags_cache]&.reject { |e| e.to_s.empty? } - after_tags = Tag.where(tag_set_id: @article.category.tag_set_id, name: tags_cache) - - if @article.tags == after_tags && @article.body_markdown == params[:article][:body_markdown] && - @article.title == params[:article][:title] - flash[:danger] = "No changes were saved because you didn't edit the post." - return redirect_to article_path(@article) - end - - body_rendered = helpers.post_markdown(:article, :body_markdown) - before = { body: @article.body_markdown, title: @article.title, tags: @article.tags } - if @article.update(article_params.merge(tags_cache: tags_cache, body: body_rendered, - last_activity: DateTime.now, last_activity_by: current_user, - last_edited_at: DateTime.now, last_edited_by: current_user)) - PostHistory.post_edited(@article, current_user, before: before[:body], - after: params[:article][:body_markdown], comment: params[:edit_comment], - before_title: before[:title], after_title: params[:article][:title], - before_tags: before[:tags], after_tags: after_tags) - redirect_to share_article_path(@article) - else - render :edit - end - end - - def update_as_suggested_edit - return if check_edits_limit! @article - - body_rendered = helpers.post_markdown(:article, :body_markdown) - new_tags_cache = params[:article][:tags_cache]&.reject(&:empty?) - - body_markdown = if params[:article][:body_markdown] != @article.body_markdown - params[:article][:body_markdown] - end - - if @article.tags_cache == new_tags_cache && @article.body_markdown == params[:article][:body_markdown] && - @article.title == params[:article][:title] - flash[:danger] = "No changes were saved because you didn't edit the post." - return redirect_to article_path(@article) - end - - updates = { - post: @article, - user: current_user, - community: @article.community, - body: body_rendered, - title: params[:article][:title] == @article.title ? nil : params[:article][:title], - tags_cache: new_tags_cache == @article.tags_cache ? @article.tags_cache : new_tags_cache, - body_markdown: body_markdown, - comment: params[:edit_comment], - active: true, accepted: false, - decided_at: nil, decided_by: nil, - rejected_comment: nil - } - - @edit = SuggestedEdit.new(updates) - if @edit.save - @article.user.create_notification("Edit suggested on your post #{@article.title.truncate(50)}", - article_url(@article)) - redirect_to share_article_path(@article) - else - @article.errors = @edit.errors - render :edit - end - end - - def destroy - unless check_your_privilege('flag_curate', @article, false) - flash[:danger] = helpers.ability_err_msg(:flag_curate, 'delete this article') - redirect_to article_path(@article) && return - end - - if @article.deleted - flash[:danger] = "Can't delete a deleted post." - redirect_to article_path(@article) && return - end - - if @article.update(deleted: true, deleted_at: DateTime.now, deleted_by: current_user, - last_activity: DateTime.now, last_activity_by: current_user) - PostHistory.post_deleted(@article, current_user) - else - flash[:danger] = "Can't delete this post right now. Try again later." - end - redirect_to article_path(@article) - end - - def undelete - unless check_your_privilege('flag_curate', @article, false) - flash[:danger] = helpers.ability_err_msg(:flag_curate, 'undelete this article') - redirect_to article_path(@article) && return - end - - unless @article.deleted - flash[:danger] = "Can't undelete an undeleted post." - redirect_to article_path(@article) && return - end - - if @article.deleted_by.is_moderator && !current_user.is_moderator - flash[:danger] = 'You cannot undelete this post deleted by a moderator.' - redirect_to(article_path(@article)) && return - end - - if @article.update(deleted: false, deleted_at: nil, deleted_by: nil, - last_activity: DateTime.now, last_activity_by: current_user) - PostHistory.post_undeleted(@article, current_user) - else - flash[:danger] = "Can't undelete this article right now. Try again later." - end - redirect_to article_path(@article) - end - private def set_article @@ -146,12 +20,4 @@ class ArticlesController < ApplicationController not_found end end - - def article_params - params.require(:article).permit(:body_markdown, :title, :tags_cache) - end - - def check_if_article_locked - check_if_locked(@article) - end end diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index e12ef42471a635d8120b3d2782f00a9261287039..e4f7a9e50dc6341b78f40ffe1d849152ed2e0ab5 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -13,13 +13,13 @@ class PostsController < ApplicationController @parent = Post.where(id: params[:parent]).first @post = Post.new(category: @category, post_type: @post_type, parent: @parent) - if @post_type.has_category? && @category.nil? && @parent.nil? - flash[:danger] = helpers.i18ns('posts.type_requires_category', type: @post_type.name) + if @post_type.has_parent? && @parent.nil? + flash[:danger] = helpers.i18ns('posts.type_requires_parent', type: @post_type.name) redirect_back fallback_location: root_path end - if @post_type.has_parent? && @parent.nil? - flash[:danger] = helpers.i18ns('posts.type_requires_parent', type: @post_type.name) + if @post_type.has_category? && @category.nil? && @parent.nil? + flash[:danger] = helpers.i18ns('posts.type_requires_category', type: @post_type.name) redirect_back fallback_location: root_path end @@ -41,14 +41,14 @@ class PostsController < ApplicationController @post = Post.new(post_params.merge(user: current_user, body: helpers.post_markdown(:post, :body_markdown), category: @category, post_type: @post_type, parent: @parent)) - if @post_type.has_category? && @category.nil? && @parent.nil? - flash[:danger] = helpers.i18ns('posts.type_requires_category', type: @post_type.name) + if @post_type.has_parent? && @parent.nil? + flash[:danger] = helpers.i18ns('posts.type_requires_parent', type: @post_type.name) redirect_back fallback_location: root_path return end - if @post_type.has_parent? && @parent.nil? - flash[:danger] = helpers.i18ns('posts.type_requires_parent', type: @post_type.name) + if @post_type.has_category? && @category.nil? && @parent.nil? + flash[:danger] = helpers.i18ns('posts.type_requires_category', type: @post_type.name) redirect_back fallback_location: root_path return end diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index 0efe22b97833eb1dc41ae27004df2c4ddaa8dd5d..1b57bce8494fefe93112ac946b66ba7069e37e18 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -1,10 +1,6 @@ # Web controller. Provides actions that relate to questions - this is essentially the standard set of resources, plus a # couple for the extra question lists (such as listing by tag). class QuestionsController < ApplicationController - before_action :authenticate_user!, only: [:destroy, :undelete, :close, :reopen] - before_action :set_question, only: [:destroy, :undelete, :close, :reopen] - before_action :check_if_question_locked, only: [:destroy, :undelete, :close, :reopen] - def lottery ids = Rails.cache.fetch 'lottery_questions', expires_in: 24.hours do # noinspection RailsParamDefResolve @@ -23,29 +19,4 @@ class QuestionsController < ApplicationController format.rss { render layout: false } end end - - private - - def question_params - params.require(:question).permit(:body_markdown, :title, :tags_cache) - end - - def set_question - @question = Question.find params[:id] - rescue - if current_user&.privilege?('flag_curate') - @question ||= Question.unscoped.find params[:id] - end - if @question.nil? - not_found - return - end - unless @question.post_type_id == Question.post_type_id - not_found - end - end - - def check_if_question_locked - check_if_locked(@question) - end end diff --git a/config/routes.rb b/config/routes.rb index 7cfa5fa1576e803b511b7b6dc377888a674d7615..044e3a95c28758ecbdf3471a3962fcfa5f3b13f6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -64,7 +64,6 @@ Rails.application.routes.draw do get 'questions/lottery', to: 'questions#lottery', as: :questions_lottery get 'questions/feed', to: 'questions#feed', as: :question_feed - get 'questions/tagged/:tag_set/:tag', to: 'questions#tagged', as: :questions_tagged get 'questions/:id', to: 'posts#redirect', as: :question scope 'posts' do diff --git a/test/controllers/posts_controller_test.rb b/test/controllers/posts_controller_test.rb index 3405e8668bdc52f21a69f91b21f63b35b8d3680a..ce99f5d5ae7eca98323ed9380c8ad32847368167 100644 --- a/test/controllers/posts_controller_test.rb +++ b/test/controllers/posts_controller_test.rb @@ -80,6 +80,22 @@ class PostsControllerTest < ActionController::TestCase assert_redirected_to new_user_session_path end + test 'new rejects category post type without category' do + sign_in users(:standard_user) + get :new, params: { post_type: post_types(:question).id } + assert_response 302 + assert_redirected_to root_path + assert_not_nil flash[:danger] + end + + test 'new rejects parented post type without parent' do + sign_in users(:standard_user) + get :new, params: { post_type: post_types(:answer).id } + assert_response 302 + assert_redirected_to root_path + assert_not_nil flash[:danger] + end + # Create test 'can create help post' do diff --git a/test/controllers/questions_controller_test.rb b/test/controllers/questions_controller_test.rb index 8515e933d29e394d254977cfd29c6af388919000..5164c708ef072ffa37b48bdd24dfc1f81e27968a 100644 --- a/test/controllers/questions_controller_test.rb +++ b/test/controllers/questions_controller_test.rb @@ -3,10 +3,4 @@ require 'test_helper' class QuestionsControllerTest < ActionController::TestCase include Devise::Test::ControllerHelpers include ApplicationTestHelper - - test 'should get tagged page' do - get :tagged, params: { tag: 'discussion', tag_set: tag_sets(:main).id } - assert_not_nil assigns(:questions) - assert_response(200) - end end