docbrown/app/controllers/articles_controller.rb
Abraham Williams 9cb40e546b Enables Rails cops (#2186)
* Enable Rails cops

* Fix Rails/DynamicFindBy

* Fix Rails/HttpStatus

* Fix Rails/Blank

* Fix Rails/RequestReferer

* Fix Rails/ActiveRecordAliases

* Fix Rails/FindBy

* Fix Rails/Presence

* Fix Rails/Delegate

* Fix Rails/Validation

* Fix Rails/PluralizationGrammar

* Fix Rails/Present

* Fix Rails/Output

* Fix Rails/Blank

* Fix Rails/FilePath

* Fix Rails/InverseOf

* Fix Rails/LexicallyScopedActionFilter

* Add Rails/OutputSafety to TODO

* Add Rails/HasManyOrHasOneDependent to TODO

* Add Rails/SkipsModelValidations to TODO
2019-03-25 09:25:55 -04:00

231 lines
8.6 KiB
Ruby

class ArticlesController < ApplicationController
include ApplicationHelper
before_action :authenticate_user!, except: %i[feed new]
before_action :set_article, only: %i[edit update destroy]
before_action :raise_banned, only: %i[new create update]
before_action :set_cache_control_headers, only: %i[feed]
after_action :verify_authorized
def feed
skip_authorization
@articles = Article.where(published: true).
select(:published_at, :processed_html, :user_id, :organization_id, :title, :path).
order(published_at: :desc).
page(params[:page].to_i).per(12)
if params[:username]
if (@user = User.find_by(username: params[:username]))
@articles = @articles.where(user_id: @user.id)
elsif (@user = Organization.find_by(slug: params[:username]))
@articles = @articles.where(organization_id: @user.id).includes(:user)
else
render body: nil
return
end
else
@articles = @articles.where(featured: true).includes(:user)
end
set_surrogate_key_header "feed", @articles.map(&:record_key)
response.headers["Surrogate-Control"] = "max-age=600, stale-while-revalidate=30, stale-if-error=86400"
render layout: false
end
def new
@user = current_user
@organization = @user&.organization
@tag = Tag.find_by(name: params[:template])
@prefill = params[:prefill].to_s.gsub("\\n ", "\n").gsub("\\n", "\n")
@article = if @tag.present? && @user&.editor_version == "v2"
authorize Article
submission_template = @tag.submission_template_customized(@user.name).to_s
Article.new(body_markdown: submission_template.split("---").last.to_s.strip, cached_tag_list: @tag.name,
processed_html: "", user_id: current_user&.id, title: submission_template.split("title:")[1].to_s.split("\n")[0].to_s.strip)
elsif @tag&.submission_template.present? && @user
authorize Article
Article.new(body_markdown: @tag.submission_template_customized(@user.name),
processed_html: "", user_id: current_user&.id)
elsif @prefill.present? && @user&.editor_version == "v2"
authorize Article
Article.new(body_markdown: @prefill.split("---").last.to_s.strip, cached_tag_list: @prefill.split("tags:")[1].to_s.split("\n")[0].to_s.strip,
processed_html: "", user_id: current_user&.id, title: @prefill.split("title:")[1].to_s.split("\n")[0].to_s.strip)
elsif @prefill.present? && @user
authorize Article
Article.new(body_markdown: @prefill,
processed_html: "", user_id: current_user&.id)
elsif @tag.present?
skip_authorization
Article.new(
body_markdown: "---\ntitle: \npublished: false\ndescription: \ntags: " + @tag.name + "\n---\n\n",
processed_html: "", user_id: current_user&.id
)
else
skip_authorization
if @user&.editor_version == "v2"
Article.new(user_id: current_user&.id)
else
Article.new(
body_markdown: "---\ntitle: \npublished: false\ndescription: \ntags: \n---\n\n",
processed_html: "", user_id: current_user&.id
)
end
end
end
def edit
authorize @article
@user = @article.user
@organization = @user&.organization
end
def preview
authorize Article
begin
fixed_body_markdown = MarkdownFixer.fix_for_preview(params[:article_body])
parsed = FrontMatterParser::Parser.new(:md).call(fixed_body_markdown)
parsed_markdown = MarkdownParser.new(parsed.content)
processed_html = parsed_markdown.finalize
rescue StandardError => e
@article = Article.new(body_markdown: params[:article_body])
@article.errors[:base] << ErrorMessageCleaner.new(e.message).clean
end
respond_to do |format|
if @article
format.json { render json: @article.errors, status: :unprocessable_entity }
else
format.json { render json: { processed_html: processed_html, title: parsed["title"] }, status: 200 }
end
end
end
def create
authorize Article
@user = current_user
@article = ArticleCreationService.
new(@user, article_params, job_opportunity_params).
create!
redirect_after_creation
end
def update
authorize @article
@user = @article.user || current_user
@article.tag_list = []
@article.main_image = nil
edited_at_date = if @article.user == current_user && @article.published
Time.current
else
@article.edited_at
end
if @article.update(article_params.merge(edited_at: edited_at_date))
handle_org_assignment
handle_hiring_tag
if @article.published
Notification.send_to_followers(@article, "Published") if @article.saved_changes["published_at"]&.include?(nil)
path = @article.path
else
Notification.remove_all_without_delay(notifiable_id: @article.id, notifiable_type: "Article", action: "Published")
path = "/#{@article.username}/#{@article.slug}?preview=#{@article.password}"
end
redirect_to(params[:destination] || path)
else
render :edit
end
end
def delete_confirm
@article = current_user.articles.find_by(slug: params[:slug])
authorize @article
end
def destroy
authorize @article
@article.destroy!
Notification.remove_all_without_delay(notifiable_id: @article.id, notifiable_type: "Article", action: "Published")
Notification.remove_all(notifiable_id: @article.id, notifiable_type: "Article", action: "Reaction")
respond_to do |format|
format.html { redirect_to "/dashboard", notice: "Article was successfully deleted." }
format.json { head :no_content }
end
end
private
def handle_org_assignment
if @user.organization_id.present? && article_params[:publish_under_org].to_i == 1
@article.organization_id = @user.organization_id
@article.save
elsif article_params[:publish_under_org].present?
@article.organization_id = nil
@article.save
end
end
def handle_hiring_tag
if job_opportunity_params.present? && @article.tag_list.include?("hiring")
create_or_update_job_opportunity
elsif @article.job_opportunity && !@article.tag_list.include?("hiring")
@article.job_opportunity.destroy!
end
end
def create_or_update_job_opportunity
if @article.job_opportunity.present?
@article.job_opportunity.update(job_opportunity_params)
else
@job_opportunity = JobOpportunity.create(job_opportunity_params)
@article.job_opportunity = @job_opportunity
@article.save
end
end
def set_article
owner = User.find_by(username: params[:username]) || Organization.find_by(slug: params[:username])
found_article = if params[:slug]
owner.articles.includes(:user).find_by(slug: params[:slug])
else
Article.includes(:user).find(params[:id])
end
@article = found_article || not_found
end
def article_params
params[:article][:published] = true if params[:submit_button] == "PUBLISH"
modified_params = policy(Article).permitted_attributes
modified_params << :user_id if org_admin_user_change_privilege
modified_params << :comment_template if current_user.has_role?(:admin)
params.require(:article).permit(modified_params)
end
def job_opportunity_params
return nil if params[:article][:job_opportunity].blank?
params[:article].require(:job_opportunity).permit(
:remoteness, :location_given, :location_city, :location_postal_code,
:location_country_code, :location_lat, :location_long
)
end
def redirect_after_creation
@article.decorate
if @article.persisted?
redirect_to @article.current_state_path, notice: "Article was successfully created."
else
if @article.errors.to_h[:body_markdown] == "has already been taken"
@article = current_user.articles.find_by(body_markdown: @article.body_markdown)
redirect_to @article.current_state_path
return
end
render :new
end
end
def org_admin_user_change_privilege
params[:article][:user_id] &&
current_user.org_admin &&
current_user.organization_id == @article.organization_id &&
User.find(params[:article][:user_id])&.organization_id == @article.organization_id
end
end