diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e3b0e20a74ac39fb33de9ea3bb340fe9c763477d..4f55356b8b3cf2094f31d6c9367dc14d2e2cf55c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -31,13 +31,28 @@ class ApplicationController < ActionController::Base end def not_found - render 'errors/not_found', layout: 'without_sidebar', status: :not_found + respond_to do |format| + format.html do + render 'errors/not_found', layout: 'without_sidebar', status: :not_found + end + format.json do + render json: { status: 'failed', errors: ['not_found'] }, status: :not_found + end + end false end def verify_moderator if !user_signed_in? || !(current_user.is_moderator || current_user.is_admin) - render 'errors/not_found', layout: 'without_sidebar', status: :not_found + respond_to do |format| + format.html do + render 'errors/not_found', layout: 'without_sidebar', status: :not_found + end + format.json do + render json: { status: 'failed', errors: ['not_found'] }, status: :not_found + end + end + return false end true diff --git a/app/controllers/articles_controller.rb b/app/controllers/articles_controller.rb deleted file mode 100644 index 7f9d4ba3537b138736060c424a47128486047b76..0000000000000000000000000000000000000000 --- a/app/controllers/articles_controller.rb +++ /dev/null @@ -1,23 +0,0 @@ -class ArticlesController < ApplicationController - before_action :set_article - before_action :check_article - - def share - redirect_to article_path(params[:id]) - end - - private - - def set_article - @article = Article.find params[:id] - if @article.deleted && !current_user&.has_post_privilege?('flag_curate', @article) - not_found - end - end - - def check_article - unless @article.post_type_id == Article.post_type_id - not_found - end - end -end diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 1480024223a52613a77bc1770b59e7d206844f47..f8843272a27a706e2f203ae048bd95608a1ffd3e 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -322,14 +322,6 @@ class PostsController < ApplicationController render json: { link: uploaded_url(@blob.key) } end - def share_q - redirect_to question_path(id: params[:id]) - end - - def share_a - redirect_to question_path(id: params[:qid], anchor: "answer-#{params[:id]}") - end - def help_center @posts = Post.where(post_type_id: [PolicyDoc.post_type_id, HelpDoc.post_type_id]) .or(Post.unscoped.where(post_type_id: [PolicyDoc.post_type_id, HelpDoc.post_type_id], @@ -367,15 +359,11 @@ class PostsController < ApplicationController end def toggle_comments - @post.comments_disabled = !@post.comments_disabled - @post.save + @post.update(comments_disabled: !@post.comments_disabled) if @post.comments_disabled && params[:delete_all_comments] - @post.comments.undeleted.map do |c| - c.deleted = true - c.save - end + @post.comments.update_all(deleted: true) end - render json: { success: true } + render json: { status: 'success', success: true } end def lock diff --git a/app/views/articles/_form.html.erb b/app/views/articles/_form.html.erb deleted file mode 100644 index 594316ee5b7a93ac6810684bf5a2f845178e27eb..0000000000000000000000000000000000000000 --- a/app/views/articles/_form.html.erb +++ /dev/null @@ -1,48 +0,0 @@ -<%= render 'posts/markdown_script' %> - -<% if @article.errors.any? %> - <div class="notice is-danger is-filled"> - The following errors prevented this post from being saved: - <ul> - <% @article.errors.full_messages.each do |msg| %> - <li><%= msg %></li> - <% end %> - </ul> - </div> -<% end %> - -<%= render 'posts/image_upload' %> - -<%= form_for @article, url: edit_article_path(@article) do |f| %> - <div class="form-group"> - <%= f.label :title, "Title your post:", class: "form-element" %> - <%= f.text_field :title, class: "form-element" %> - </div> - - <%= render 'shared/body_field', f: f, field_name: :body_markdown, field_label: 'Body', post: @article %> - - <div class="post-preview"></div> - - <div class="form-group"> - <%= f.label :tags_cache, "Tags", class: "form-element" %> - <div class="form-caption"> - Tags help to categorize posts. Separate them by space. Use hyphens for multiple-word tags. - </div> - <%= f.select :tags_cache, options_for_select(@article.tags_cache.map { |t| [t, t] }, selected: @article.tags_cache), - { include_blank: true }, multiple: true, class: "form-element js-tag-select", - data: { tag_set: @article.category.tag_set.id } %> - </div> - - <div class="form-group"> - <%= label_tag :edit_comment, 'Edit comment', class: "form-element" %> - <div class="form-caption"> - Describe—if necessary—what you are changing and why you are making this edit. - </div> - <%= text_field_tag :edit_comment, params[:edit_comment], class: 'form-element' %> - </div> - - <div class="form-group"> - <%= f.submit check_your_post_privilege(@article, 'edit_posts') ? "Save changes" : "Suggest changes", class: "button is-filled" %> - <%= link_to 'Cancel', article_path(@article), class: 'button is-outlined is-muted' %> - </div> -<% end %> diff --git a/app/views/articles/edit.html.erb b/app/views/articles/edit.html.erb deleted file mode 100644 index 6727a85a707a9f1bfb920d6498c26629bb9bfc8f..0000000000000000000000000000000000000000 --- a/app/views/articles/edit.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= render 'form', is_edit: true %> \ No newline at end of file diff --git a/app/views/articles/show.html.erb b/app/views/articles/show.html.erb deleted file mode 100644 index ffbd774949cb4b6869468649a2c380dcff20517b..0000000000000000000000000000000000000000 --- a/app/views/articles/show.html.erb +++ /dev/null @@ -1,19 +0,0 @@ -<% content_for :title, @article.title.truncate(50) %> -<% content_for :description do %> - <% Rails.cache.fetch "posts/#{@article.id}/description" do %> - <%= @article.body_plain[0..74].strip %>... - <% end %> -<% end %> - -<% content_for :twitter_card_meta do %> - <meta name="twitter:card" content="summary" /> - <% if @article.user.twitter.present? %> - <meta name="twitter:creator" content="@<%= @article.user.twitter %>" /> - <% end %> - <meta property="og:url" content="<%= question_url(@article) %>" /> - <meta property="og:title" content="<%= @article.title %>" /> - <meta property="og:description" content="<%= @article.body_plain[0..150].strip %>..." /> - <meta property="og:image" content="<%= "https://#{RequestContext.community.host}#{SiteSetting['SiteLogoPath']}" %>" /> -<% end %> - -<%= render 'posts/expanded', post: @article %> \ No newline at end of file diff --git a/app/views/posts/_form_old.html.erb b/app/views/posts/_form_old.html.erb deleted file mode 100644 index 91758e9ce08e8a349f07ca4df125c84ed6b919a1..0000000000000000000000000000000000000000 --- a/app/views/posts/_form_old.html.erb +++ /dev/null @@ -1,102 +0,0 @@ -<% with_post_type ||= false %> - -<% content_for :head do %> - <%= render 'posts/markdown_script' %> -<% end %> - -<div class="notice is-info"> - <p><strong>Posting Tips</strong></p> - <div class="has-font-size-caption"> - <% guidance = @category.asking_guidance_override %> - <%= raw(sanitize(render_markdown(guidance.present? ? guidance : SiteSetting['AskingGuidance']), scrubber: scrubber)) %> - </div> -</div> - -<% if @post.errors.any? %> - <div class="notice is-danger is-filled"> - <p>The following errors prevented your post being saved:</p> - <ul> - <% @post.errors.full_messages.each do |msg| %> - <li><%= msg %></li> - <% end %> - </ul> - </div> -<% end %> - -<%= render 'posts/image_upload' %> - -<%= form_for @post, url: submit_path, html: { class: 'has-margin-top-4' } do |f| %> - <%= f.hidden_field :category_id %> - - <% if with_post_type %> - <div class="form-group"> - <%= f.label :post_type_id, 'Post type', class: 'form-element' %> - <span class="form-caption">What kind of post is this? Questions can have answers; articles only have comments.</span> - <% ids = @category.display_post_types.reject { |e| e.to_s.empty? } %> - <% post_types = PostType.where(id: ids) %> - <% opts = post_types.map { |pt| [pt.name, pt.id] } %> - <%= f.select :post_type_id, options_for_select(opts, selected: @post.post_type_id), - { include_blank: true }, class: 'form-element' %> - </div> - <% else %> - <%= f.hidden_field :post_type_id %> - <% end %> - - <%= render 'shared/body_field', f: f, field_name: :body_markdown, field_label: 'Body', post: @post %> - - <div class="post-preview"></div> - - <div class="form-group"> - <%= f.label :title, 'Summarize your post with a title:', class: 'form-element' %> - <%= f.text_field :title, class: 'form-element' %> - </div> - - <div class="form-group"> - <%= f.label :tags_cache, 'Tags (at least one):', class: 'form-element' %> - <% required_tags = @category.required_tags.to_a %> - <% unless required_tags.empty? %> - <span class="form-caption"> - Requires at least one of - <% required_tags.each do |tag| %> - <a class="badge is-tag is-filled js-add-required-tag" href="javascript:void(0)" data-tag-id="<%= tag.id %>" - data-tag-name="<%= tag.name %>"> - <%= tag.name %> - </a> - <% end %> - </span> - <% end %> - <%= f.select :tags_cache, options_for_select(@post.tags_cache.map { |t| [t, t] }, selected: @post.tags_cache), - { include_blank: true }, multiple: true, class: "form-element js-tag-select", - data: { tag_set: @category.tag_set_id } %> - </div> - - <% unless @post.id.present? %> - <div class="form-group"> - <%= f.label :license_id, 'License', class: 'form-element' %> - <span class="form-caption"> - <% site_default = License.site_default %> - <% category_default = @category.license %> - <% if site_default.present? %> - site default: <a href="javascript:void(0)" class="js-license-autofill" data-license-id="<%= site_default.id %>"> - <%= site_default.name %> - </a> - <% end %> - <% if site_default.present? && category_default.present? %> - · - <% end %> - <% if category_default.present? %> - category default: <a href="javascript:void(0)" class="js-license-autofill" data-license-id="<%= category_default.id %>"> - <%= category_default.name %> - </a> - <% end %> - </span> - <%= f.select :license_id, options_for_select(License.enabled.default_order(@category).map { |l| [l.name, l.id] }, - selected: @post.license_id), {}, class: 'form-element' %> - </div> - <% end %> - - <div class="actions"> - <%= f.submit "Save Post in #{@category.name}", class: 'button is-filled' %> - <%= link_to 'Cancel', category_path(@category), class: 'button is-muted is-outlined' %> - </div> -<% end %> \ No newline at end of file diff --git a/app/views/posts/document.html.erb b/app/views/posts/document.html.erb index 00e5560a2ee51cad47a051b13a3bd162c0063532..a5cb84a167ba3c82b7ae75a9110be610f0b9a887 100644 --- a/app/views/posts/document.html.erb +++ b/app/views/posts/document.html.erb @@ -3,7 +3,7 @@ <% end %> <% unless @post.nil? %> <% if (moderator? && @post.post_type_id == HelpDoc.post_type_id) || (admin? && @post.post_type_id == PolicyDoc.post_type_id) %> - <%= link_to 'edit', edit_help_post_path(@post), class: "button is-outlined is-muted" %> + <%= link_to 'edit', edit_post_path(@post), class: "button is-outlined is-muted" %> <% end %> <% end %> diff --git a/app/views/posts/edit_help.html.erb b/app/views/posts/edit_help.html.erb deleted file mode 100644 index 1122a1799bcacc0a265c803b9a1483fee671438f..0000000000000000000000000000000000000000 --- a/app/views/posts/edit_help.html.erb +++ /dev/null @@ -1,39 +0,0 @@ -<% content_for :title, "Editing '#{@post.title.truncate(50)}'" %> - -<% if @post.errors.any? %> - <div class="notice is-danger"> - These errors prevented this post being saved: - <ul> - <% @post.errors.full_messages.each do |msg| %> - <li><%= msg %></li> - <% end %> - </ul> - </div> -<% end %> - -<h1>Edit <%= @post.policy_doc? ? 'Policy' : (@post.help_doc? ? 'Help Article' : 'Post') %></h1> -<%= form_for @post, url: update_help_post_path(@post) do |f| %> - <div class="form-group"> - <%= f.label :title, "Title your post:", class: "form-element" %> - <%= f.text_field :title, class: "form-element" %> - </div> - <div class="form-group"> - <%= f.label :body_markdown, 'Body', class: "form-element" %> - <%= f.text_area :body_markdown, { class: "form-element is-large post-field", rows: 15 } %> - </div> - <div class="form-group"> - <%= f.label :help_category, 'Category', class: 'form-element' %> - <span class="form-caption"> - Name a category under which to display this post in the help center. - </span> - <%= f.text_field :help_category, class: 'form-element' %> - </div> - <div class="form-group"> - <%= f.label :help_ordering, 'Order', class: 'form-element' %> - <span class="form-caption"> - Control where this post appears in the list of help articles. Higher values appear later in the list. - </span> - <%= f.number_field :help_ordering, class: 'form-element' %> - </div> - <%= f.submit "Update", class: "button is-filled is-very-large" %> -<% end %> diff --git a/app/views/posts/new_help.html.erb b/app/views/posts/new_help.html.erb deleted file mode 100644 index a65f5646e2e9fd1f34e36a58b936b6324a62d387..0000000000000000000000000000000000000000 --- a/app/views/posts/new_help.html.erb +++ /dev/null @@ -1,55 +0,0 @@ -<% content_for :title, "New Policy Document" %> - -<% if @post.errors.any? %> - <div class="notice is-danger"> - These errors prevented this post being saved: - <ul> - <% @post.errors.full_messages.each do |msg| %> - <li><%= msg %></li> - <% end %> - </ul> - </div> -<% end %> - -<h1>New Policy Document</h1> -<p> - If you're a moderator, you may use this page to create help documents that you can link to from /help/<document>. - If you're an administrator, you can also create policy documents, including legal documents. -</p> -<%= form_for @post, url: create_help_post_path do |f| %> - <div class="form-group"> - <%= f.label :post_type_id, 'Post type', class: "form-element" %> - <%= f.select :post_type_id, options_for_select(current_user.is_admin ? - [['Policy', PolicyDoc.post_type_id], ['Help', HelpDoc.post_type_id]] : - [['Help', HelpDoc.post_type_id]]), - { include_blank: true }, class: 'form-element' %> - </div> - <div class="form-group"> - <%= f.label :doc_slug, 'URL slug', class: "form-element" %> - <span class="form-caption">In a URL of "https://yoursite.codidact.com/help/topic", the "topic" is the slug.</span> - <%= f.text_field :doc_slug, class: 'form-element' %> - </div> - <div class="form-group"> - <%= f.label :title, "Title your post:", class: "form-element" %> - <%= f.text_field :title, class: "form-element" %> - </div> - <div class="form-group"> - <%= f.label :body_markdown, 'Body', class: "form-element" %> - <%= f.text_area :body_markdown, { class: "form-element post-field", rows: 15 } %> - </div> - <div class="form-group"> - <%= f.label :help_category, 'Category', class: 'form-element' %> - <span class="form-caption"> - Name a category under which to display this post in the help center. - </span> - <%= f.text_field :help_category, class: 'form-element' %> - </div> - <div class="form-group"> - <%= f.label :help_ordering, 'Order', class: 'form-element' %> - <span class="form-caption"> - Control where this post appears in the list of help articles. Higher values appear later in the list. - </span> - <%= f.number_field :help_ordering, class: 'form-element' %> - </div> - <%= f.submit "Create", class: "button is-filled is-very-large" %> -<% end %> diff --git a/app/views/posts/new_old.html.erb b/app/views/posts/new_old.html.erb deleted file mode 100644 index 1db9ccf3fdc9292ecaef382020eb94e25d15532c..0000000000000000000000000000000000000000 --- a/app/views/posts/new_old.html.erb +++ /dev/null @@ -1,5 +0,0 @@ -<h1 class="has-margin-bottom-2">New Post in <%= @category.name %></h1> -<p class="has-color-tertiary-500">Not where you meant to post? See <%= link_to 'Categories', categories_path %></p> - -<%= render 'form', with_post_type: @category.display_post_types.reject { |e| e.to_s.empty? }.size > 1, - submit_path: create_post_path(@category.id) %> \ No newline at end of file diff --git a/test/controllers/posts_controller_test.rb b/test/controllers/posts_controller_test.rb index ce99f5d5ae7eca98323ed9380c8ad32847368167..f89ed09f261ed4ba3d0425e607826a0fafa5d488 100644 --- a/test/controllers/posts_controller_test.rb +++ b/test/controllers/posts_controller_test.rb @@ -3,24 +3,49 @@ require 'test_helper' class PostsControllerTest < ActionController::TestCase include Devise::Test::ControllerHelpers - test 'should successfully get help center' do + # Help + + test 'can get help center' do get :help_center assert_response 200 assert_not_nil assigns(:posts) end - test 'question permalink should correctly redirect' do - get :share_q, params: { id: posts(:question_one).id } - assert_response 302 - assert_redirected_to question_path(posts(:question_one)) + test 'can get help article' do + get :document, params: { slug: posts(:help_article).doc_slug } + assert_response 200 + assert_not_nil assigns(:post) end - test 'answer permalink should correctly redirect' do - get :share_a, params: { qid: posts(:question_one).id, id: posts(:answer_one).id } - assert_response 302 - assert_redirected_to question_path(id: posts(:question_one).id, anchor: "answer-#{posts(:answer_one).id}") + test 'moderator can get mod help article' do + sign_in users(:moderator) + get :document, params: { slug: posts(:mod_help_article).doc_slug } + assert_response 200 + assert_not_nil assigns(:post) + end + + test 'moderator help requires authentication' do + get :document, params: { slug: posts(:mod_help_article).doc_slug } + assert_response 404 + assert_not_nil assigns(:post) + end + + test 'regular user cannot get mod help' do + sign_in users(:standard_user) + get :document, params: { slug: posts(:mod_help_article).doc_slug } + assert_response 404 + assert_not_nil assigns(:post) end + test 'cannot get disabled help article' do + sign_in users(:moderator) + get :document, params: { slug: posts(:disabled_help_article).doc_slug } + assert_response 404 + assert_not_nil assigns(:post) + end + + # Change category + test 'should change category' do sign_in users(:deleter) post :change_category, params: { id: posts(:article_one).id, target_id: categories(:articles_only).id } @@ -604,4 +629,46 @@ class PostsControllerTest < ActionController::TestCase assert_response 401 assert_equal before_history, after_history, 'PostHistory event incorrectly created on deletion' end + + # Toggle comments + + test 'can toggle comments' do + sign_in users(:moderator) + post :toggle_comments, params: { id: posts(:question_one).id } + assert_response 200 + assert_not_nil assigns(:post) + assert_nothing_raised do + JSON.parse(response.body) + end + assert_equal 'success', JSON.parse(response.body)['status'] + assert assigns(:post).comments_disabled + end + + test 'toggle comments requires authentication' do + post :toggle_comments, params: { id: posts(:question_one).id } + assert_response 302 + assert_redirected_to new_user_session_path + assert_not assigns(:post).comments_disabled + end + + test 'regular users cannot toggle comments' do + sign_in users(:standard_user) + post :toggle_comments, params: { id: posts(:question_one).id } + assert_response 404 + assert_not_nil assigns(:post) + assert_not assigns(:post).comments_disabled + end + + test 'specifying delete all results in comments being deleted' do + sign_in users(:moderator) + post :toggle_comments, params: { id: posts(:question_one).id, delete_all_comments: true } + assert_response 200 + assert_not_nil assigns(:post) + assert_nothing_raised do + JSON.parse(response.body) + end + assert_equal 'success', JSON.parse(response.body)['status'] + assert assigns(:post).comments_disabled + assert assigns(:post).comments.all?(&:deleted?) + end end diff --git a/test/fixtures/posts.yml b/test/fixtures/posts.yml index d58e8ca3c6fc6999f381139fc270647727c83ddc..25ac1dd327909d03773cbe268cf4e1d3a5eacd28 100644 --- a/test/fixtures/posts.yml +++ b/test/fixtures/posts.yml @@ -256,3 +256,33 @@ deleted_article: deleted_by: deleter upvote_count: 0 downvote_count: 0 + +help_article: + post_type: help_doc + body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + body_markdown: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + user: system + community: sample + help_category: Site Information + help_ordering: 99 + doc_slug: sample + +mod_help_article: + post_type: help_doc + body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + body_markdown: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + user: system + community: sample + help_category: $Moderator + help_ordering: 99 + doc_slug: sample-mod + +disabled_help_article: + post_type: help_doc + body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + body_markdown: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + user: system + community: sample + help_category: $Disabled + help_ordering: 99 + doc_slug: sample-disable diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index 460c4740e67c90eafc37c89bccfc14355045669a..b3b65427bca634104cb3728508140c486d7cfec1 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -84,3 +84,13 @@ no_community_user: is_global_admin: false is_global_moderator: false confirmed_at: 2020-01-01T00:00:00.000000Z + +system: + id: -99 + email: system@qpixel-test.net + encrypted_password: abcdefghijklmnopqrstuvwxyz + sign_in_count: 1337 + username: system + is_global_admin: true + is_global_moderator: true + confirmed_at: 2020-01-01T00:00:00.000000Z