docbrown/app/services/articles/builder.rb
Jeremy Friesen cf53758476
Removing Articles::Builder making policy decision (#16536)
* Removing Articles::Builder making policy decision

This change is a refactoring through triangulation.  Given that
`ArticlePolicy#new?` returned true, I'm prepared to assume that calling
`authorize(Article)` in all cases is acceptable.

So to narrow the Builder making a policy decision I renamed the returned
value to reflect what it was actually doing in the logic.  And in
renaming, flipped the polarity of the boolean.  Why the flip?  Because
`needs_authorization == !store_location`.

In consultation with Allison and Jennie, I'm proceeding with a short-cut
to get me unstuck.  That unstuck is namely "I need to ensure that the
articles#new action can go through authorization."

Given that I'll be spending time in the authorization layer, I hope
these noted short-cuts and comments will be useful in future spelunking
efforts regarding authorization.

Closes #16529

* Update app/policies/article_policy.rb

Co-authored-by: Michael Kohl <me@citizen428.net>

* Disabling spec

* Update app/policies/article_policy.rb

Co-authored-by: Dwight Scott <dwight@forem.com>

* Update app/policies/article_policy.rb

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

Co-authored-by: Michael Kohl <me@citizen428.net>
Co-authored-by: Dwight Scott <dwight@forem.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-02-14 11:39:22 -05:00

113 lines
3.3 KiB
Ruby

module Articles
class Builder
LINE_BREAK = "\n".freeze
def initialize(user, tag, prefill)
@user = user
@tag = tag
@prefill = prefill
@editor_version2 = @user&.setting&.editor_version == "v2"
end
def self.call(...)
new(...).call
end
# the Builder returns a pair of [article, store_location]
# => store_location can be either true or false
#
# @note [@jeremyf] I renamed the boolean return value from
# needs_authorization to store_location. Why? because in the
# ArticlesController#new action (the one place that instantiates the
# Articles::Builder) when "needs_authorization" was true, we'd call
# authorize(Article). But at the time of writing, the implementation
# details of ArticlePolicy#new? always returned true. So the
# "needs_authorization" was in fact behaving as a "should we store
# this location or not?" Hence the rename and "switching the
# polarity" of the boolean.
#
# @see https://github.com/forem/forem/issues/16529 for snapshot of past
# state
def call
return [tag_user_editor_v2, false] if tag && editor_version2
return [tag_user, false] if tag&.submission_template.present? && user
return [prefill_user_editor_v2, false] if prefill.present? && editor_version2
return [prefill_user, false] if prefill.present? && user
return [tag_article, true] if tag
return [user_editor_v2, true] if editor_version2
[user_editor_v1, true]
end
private
attr_reader :user, :tag, :prefill, :editor_version2
def tag_user_editor_v2
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: user.id,
title: normalized_text(submission_template, "title:"),
)
end
def tag_user
Article.new(
body_markdown: tag.submission_template_customized(user.name),
processed_html: "",
user_id: user.id,
)
end
def prefill_user_editor_v2
Article.new(
body_markdown: prefill.split("---").last.to_s.strip,
cached_tag_list: normalized_text(prefill, "tags:"),
processed_html: "",
user_id: user.id,
title: normalized_text(prefill, "title:"),
)
end
def prefill_user
Article.new(
body_markdown: prefill,
processed_html: "",
user_id: user.id,
)
end
def tag_article
Article.new(
body_markdown: "---\ntitle: \npublished: false\ndescription: \ntags: #{tag.name}\n---\n\n",
processed_html: "",
user_id: user&.id,
)
end
def user_editor_v2
Article.new(user_id: user.id)
end
def user_editor_v1
body = "---\ntitle: \npublished: false\ndescription: " \
"\ntags: \n//cover_image: https://direct_url_to_image.jpg\n---\n\n"
Article.new(
body_markdown: body,
processed_html: "",
user_id: user&.id,
)
end
def normalized_text(source, split_pattern)
text = source.split(split_pattern).second.to_s
text.split(LINE_BREAK).first.to_s.strip
end
end
end