Skip to content

Commit

Permalink
Merge pull request #59 from RubyOnWorld/model-emoji
Browse files Browse the repository at this point in the history
model-emoji
  • Loading branch information
xmas7 authored Nov 8, 2022
2 parents e60cd15 + b445d95 commit 8b063f1
Show file tree
Hide file tree
Showing 5 changed files with 601 additions and 0 deletions.
41 changes: 41 additions & 0 deletions app/models/email_style.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# frozen_string_literal: true

class EmailStyle
include ActiveModel::Serialization

attr_accessor :html, :css, :default_html, :default_css

def id
'email-style'
end

def html
SiteSetting.email_custom_template.presence || default_html
end

def css
SiteSetting.email_custom_css || default_css
end

def compiled_css
SiteSetting.email_custom_css_compiled.presence || css
end

def default_html
self.class.default_template
end

def default_css
self.class.default_css
end

def self.default_template
@_default_template ||= File.read(
File.join(Rails.root, 'app', 'views', 'email', 'default_template.html')
)
end

def self.default_css
''
end
end
128 changes: 128 additions & 0 deletions app/models/email_token.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# frozen_string_literal: true

class EmailToken < ActiveRecord::Base
class TokenAccessError < StandardError; end

belongs_to :user

validates :user_id, :email, :token_hash, presence: true

scope :unconfirmed, -> { where(confirmed: false) }
scope :active, -> { where(expired: false).where('created_at >= ?', SiteSetting.email_token_valid_hours.hours.ago) }

after_initialize do
if self.token_hash.blank?
@token ||= SecureRandom.hex
self.token_hash = self.class.hash_token(@token)
end
end

after_create do
EmailToken
.where(user_id: self.user_id)
.where(scope: [nil, self.scope])
.where.not(id: self.id)
.update_all(expired: true)
end

before_validation do
self.email = self.email.downcase if self.email
end

before_save do
if self.scope.blank?
Discourse.deprecate("EmailToken#scope cannot be empty.", output_in_test: true)
end
end

# TODO(2022-01-01): Remove
self.ignored_columns = %w{token}

def self.scopes
@scopes ||= Enum.new(
signup: 1,
password_reset: 2,
email_login: 3,
email_update: 4,
)
end

def token
raise TokenAccessError.new if @token.blank?

@token
end

def self.confirm(token, scope: nil, skip_reviewable: false)
User.transaction do
email_token = confirmable(token, scope: scope)
return if email_token.blank?

email_token.update!(confirmed: true)

user = email_token.user
user.send_welcome_message = !user.active?
user.email = email_token.email
user.active = true
user.custom_fields.delete('activation_reminder')
user.save!
user.create_reviewable if !skip_reviewable
user.set_automatic_groups
DiscourseEvent.trigger(:user_confirmed_email, user)
Invite.redeem_from_email(user.email) if scope == EmailToken.scopes[:signup]

user.reload
end
rescue ActiveRecord::RecordInvalid
# If the user's email is already taken, just return nil (failure)
end

def self.confirmable(token, scope: nil)
return nil if token.blank?

relation = unconfirmed.active
.includes(:user)
.where(token_hash: hash_token(token))

# TODO(2022-01-01): All email tokens should have scopes by now
if !scope
relation.first
else
relation.where(scope: scope).first || relation.where(scope: nil).first
end
end

def self.enqueue_signup_email(email_token, to_address: nil)
Jobs.enqueue(
:critical_user_email,
type: "signup",
user_id: email_token.user_id,
email_token: email_token.token,
to_address: to_address
)
end

def self.hash_token(token)
Digest::SHA256.hexdigest(token)
end
end

# == Schema Information
#
# Table name: email_tokens
#
# id :integer not null, primary key
# user_id :integer not null
# email :string not null
# confirmed :boolean default(FALSE), not null
# expired :boolean default(FALSE), not null
# created_at :datetime not null
# updated_at :datetime not null
# token_hash :string not null
# scope :integer
#
# Indexes
#
# index_email_tokens_on_token_hash (token_hash) UNIQUE
# index_email_tokens_on_user_id (user_id)
#
88 changes: 88 additions & 0 deletions app/models/embeddable_host.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# frozen_string_literal: true

class EmbeddableHost < ActiveRecord::Base
validate :host_must_be_valid
belongs_to :category
after_destroy :reset_embedding_settings

before_validation do
self.host.sub!(/^https?:\/\//, '')
self.host.sub!(/\/.*$/, '')
end

# TODO(2021-07-23): Remove
self.ignored_columns = ["path_whitelist"]

def self.record_for_url(uri)
if uri.is_a?(String)
uri = begin
URI(UrlHelper.normalized_encode(uri))
rescue URI::Error, Addressable::URI::InvalidURIError
end
end

return false unless uri.present?

host = uri.host
return false unless host.present?

if uri.port.present? && uri.port != 80 && uri.port != 443
host << ":#{uri.port}"
end

path = uri.path
path << "?" << uri.query if uri.query.present?

where("lower(host) = ?", host).each do |eh|
return eh if eh.allowed_paths.blank?

path_regexp = Regexp.new(eh.allowed_paths)
return eh if path_regexp.match(path) || path_regexp.match(UrlHelper.unencode(path))
end

nil
end

def self.url_allowed?(url)
return false if url.nil?

# Work around IFRAME reload on WebKit where the referer will be set to the Forum URL
return true if url&.starts_with?(Discourse.base_url) && EmbeddableHost.exists?

uri = begin
URI(UrlHelper.normalized_encode(url))
rescue URI::Error
end

uri.present? && record_for_url(uri).present?
end

private

def reset_embedding_settings
unless EmbeddableHost.exists?
Embedding.settings.each { |s| SiteSetting.set(s.to_s, SiteSetting.defaults[s]) }
end
end

def host_must_be_valid
if host !~ /\A[a-z0-9]+([\-\.]+{1}[a-z0-9]+)*\.[a-z]{2,24}(:[0-9]{1,5})?(\/.*)?\Z/i &&
host !~ /\A(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(:[0-9]{1,5})?(\/.*)?\Z/ &&
host !~ /\A([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.)?localhost(\:[0-9]{1,5})?(\/.*)?\Z/i
errors.add(:host, I18n.t('errors.messages.invalid'))
end
end
end

# == Schema Information
#
# Table name: embeddable_hosts
#
# id :integer not null, primary key
# host :string not null
# category_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# class_name :string
# allowed_paths :string
#
42 changes: 42 additions & 0 deletions app/models/embedding.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

require 'has_errors'

class Embedding < OpenStruct
include HasErrors

def self.settings
%i(embed_by_username
embed_post_limit
embed_title_scrubber
embed_truncate
embed_unlisted
allowed_embed_selectors
blocked_embed_selectors
allowed_embed_classnames)
end

def base_url
Discourse.base_url
end

def save
Embedding.settings.each do |s|
SiteSetting.set(s, public_send(s))
end
true
rescue Discourse::InvalidParameters => p
errors.add :base, p.to_s
false
end

def embeddable_hosts
EmbeddableHost.all.order(:host)
end

def self.find
embedding_args = { id: 'default' }
Embedding.settings.each { |s| embedding_args[s] = SiteSetting.get(s) }
Embedding.new(embedding_args)
end
end
Loading

0 comments on commit 8b063f1

Please sign in to comment.