discourse/app/models/email_token.rb
Osama Sayegh 45ccadeeeb
DEV: Upgrade Rails to 6.1.3.1 (#12688)
Rails 6.1.3.1 deprecates a few API and has some internal changes that break our tests suite, so this commit fixes all the deprecations and errors and now Discourse should be fully compatible with Rails 6.1.3.1. We also have a new release of the rails_failover gem that's compatible with Rails 6.1.3.1.
2021-04-21 12:36:32 +03:00

116 lines
2.9 KiB
Ruby

# frozen_string_literal: true
class EmailToken < ActiveRecord::Base
belongs_to :user
validates :token, :user_id, :email, presence: true
before_validation(on: :create) do
self.token = EmailToken.generate_token
self.email = self.email.downcase if self.email
end
after_create do
# Expire the previous tokens
EmailToken.where(user_id: self.user_id)
.where("id != ?", self.id)
.update_all(expired: true)
end
def self.token_length
16
end
def self.valid_after
SiteSetting.email_token_valid_hours.hours.ago
end
def self.unconfirmed
where(confirmed: false)
end
def self.active
where(expired: false).where('created_at > ?', valid_after)
end
def self.generate_token
SecureRandom.hex(EmailToken.token_length)
end
def self.valid_token_format?(token)
token.present? && token =~ /\h{#{token.length / 2}}/i
end
def self.atomic_confirm(token)
failure = { success: false }
return failure unless valid_token_format?(token)
email_token = confirmable(token)
return failure if email_token.blank?
user = email_token.user
failure[:user] = user
row_count = EmailToken.where(confirmed: false, id: email_token.id, expired: false).update_all 'confirmed = true'
if row_count == 1
{ success: true, user: user, email_token: email_token }
else
failure
end
end
def self.confirm(token, skip_reviewable: false)
User.transaction do
result = atomic_confirm(token)
user = result[:user]
if result[:success]
# If we are activating the user, send the welcome message
user.send_welcome_message = !user.active?
user.email = result[:email_token].email
user.active = true
user.custom_fields.delete('activation_reminder')
user.save!
user.create_reviewable unless skip_reviewable
user.set_automatic_groups
DiscourseEvent.trigger(:user_confirmed_email, user)
end
if user
if Invite.redeem_from_email(user.email).present?
user.reload
end
user
end
end
rescue ActiveRecord::RecordInvalid
# If the user's email is already taken, just return nil (failure)
end
def self.confirmable(token)
EmailToken.where(token: token)
.where(expired: false, confirmed: false)
.where("created_at >= ?", EmailToken.valid_after)
.includes(:user)
.first
end
end
# == Schema Information
#
# Table name: email_tokens
#
# id :integer not null, primary key
# user_id :integer not null
# email :string not null
# token :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
#
# Indexes
#
# index_email_tokens_on_token (token) UNIQUE
# index_email_tokens_on_user_id (user_id)
#