docbrown/app/models/badge_achievement.rb
Jeremy Friesen aa7712a80e
Extracting container for allowed tags & attrs (#15338)
* Extracting container for allowed tags & attrs

Prior to this commit, we had several different locations in which we
specified ALLOWED_TAGS and ALLOWED_ATTRIBUTES for HTML rendering and
sanitization.

Curious to see how these either intersected or didn't, I opted to
create a container module that allows for us to more readily normalize
these allowed tags and attributes.  It's possible that we won't do any
normalization, but this work helps make that easier.

Ideally, I'd love us to contextualize "why did we choose the
tags/attributes we chose?"  But for now, I think consolidating these
tags and attributes will help make adding a `details` and `summary` tag
easier.

This relates to forem/rfcs#296

See [Google Sheet][1] for analysis of what tags/attributes are used, the
intersection and union.

[1]:https://docs.google.com/spreadsheets/d/1yj-a1qus1o0o4cj-_gOMP5yteeg-_f3s5z7kvK0Y7RM/edit#gid=0

* Fixing misnamed constant

* Fixing misnamed constant

* Extracting additional HtmlRendering use cases

* Adding comparative documentation for HTML tags

* Fixing broken parameter signature

* Moving constants into MarkdownProcessor
2021-12-16 12:24:45 -05:00

56 lines
1.7 KiB
Ruby

# @note When we destroy the related user, it's using dependent:
# :delete for the relationship. That means no before/after
# destroy callbacks will be called on this object.
class BadgeAchievement < ApplicationRecord
resourcify
belongs_to :user
belongs_to :badge
belongs_to :rewarder, class_name: "User", optional: true
delegate :slug, to: :badge, prefix: true
delegate :title, to: :badge, prefix: true
delegate :badge_image_url, to: :badge, prefix: false
counter_culture :user, column_name: "badge_achievements_count"
validates :badge_id, uniqueness: { scope: :user_id }
before_validation :render_rewarding_context_message_html
after_create :award_credits
after_create_commit :notify_recipient
after_create_commit :send_email_notification
private
def render_rewarding_context_message_html
return unless rewarding_context_message_markdown
parsed_markdown = MarkdownProcessor::Parser.new(rewarding_context_message_markdown)
html = parsed_markdown.finalize
final_html = ActionController::Base.helpers.sanitize(
html,
tags: MarkdownProcessor::AllowedTags::BADGE_ACHIEVEMENT_CONTEXT_MESSAGE,
attributes: MarkdownProcessor::AllowedAttributes::BADGE_ACHIEVEMENT_CONTEXT_MESSAGE,
)
self.rewarding_context_message = final_html
end
def notify_recipient
Notification.send_new_badge_achievement_notification(self)
end
def send_email_notification
return unless user.is_a?(User)
return unless user.email && user.notification_setting.email_badge_notifications
BadgeAchievements::SendEmailNotificationWorker.perform_async(id)
end
def award_credits
return if badge.credits_awarded.zero?
Credit.add_to(user, badge.credits_awarded)
end
end