2018-02-04 05:42:13 +01:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2023-12-01 06:00:41 -05:00
|
|
|
module User::Omniauthable
|
2018-02-04 05:42:13 +01:00
|
|
|
extend ActiveSupport::Concern
|
|
|
|
|
|
|
|
TEMP_EMAIL_PREFIX = 'change@me'
|
2023-04-26 19:46:18 -04:00
|
|
|
TEMP_EMAIL_REGEX = /\A#{TEMP_EMAIL_PREFIX}/
|
2018-02-04 05:42:13 +01:00
|
|
|
|
|
|
|
included do
|
2019-03-14 02:13:42 +01:00
|
|
|
devise :omniauthable
|
|
|
|
|
2018-02-04 05:42:13 +01:00
|
|
|
def omniauth_providers
|
|
|
|
Devise.omniauth_configs.keys
|
|
|
|
end
|
|
|
|
|
2022-03-09 06:07:35 -05:00
|
|
|
def email_present?
|
2018-02-04 05:42:13 +01:00
|
|
|
email && email !~ TEMP_EMAIL_REGEX
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class_methods do
|
|
|
|
def find_for_oauth(auth, signed_in_resource = nil)
|
|
|
|
# EOLE-SSO Patch
|
|
|
|
auth.uid = (auth.uid[0][:uid] || auth.uid[0][:user]) if auth.uid.is_a? Hashie::Array
|
|
|
|
identity = Identity.find_for_oauth(auth)
|
|
|
|
|
|
|
|
# If a signed_in_resource is provided it always overrides the existing user
|
|
|
|
# to prevent the identity being locked with accidentally created accounts.
|
|
|
|
# Note that this may leave zombie accounts (with no associated identity) which
|
|
|
|
# can be cleaned up at a later date.
|
2019-09-16 20:42:29 +02:00
|
|
|
user = signed_in_resource || identity.user
|
2024-02-09 15:06:07 +01:00
|
|
|
user ||= reattach_for_oauth(auth)
|
2019-09-16 20:42:29 +02:00
|
|
|
user ||= create_for_oauth(auth)
|
2018-02-04 05:42:13 +01:00
|
|
|
|
|
|
|
if identity.user.nil?
|
|
|
|
identity.user = user
|
|
|
|
identity.save!
|
|
|
|
end
|
|
|
|
|
|
|
|
user
|
|
|
|
end
|
|
|
|
|
2024-02-09 15:06:07 +01:00
|
|
|
def reattach_for_oauth(auth)
|
|
|
|
# If allowed, check if a user exists with the provided email address,
|
|
|
|
# and return it if they does not have an associated identity with the
|
|
|
|
# current authentication provider.
|
|
|
|
|
|
|
|
# This can be used to provide a choice of alternative auth providers
|
|
|
|
# or provide smooth gradual transition between multiple auth providers,
|
|
|
|
# but this is discouraged because any insecure provider will put *all*
|
|
|
|
# local users at risk, regardless of which provider they registered with.
|
|
|
|
|
|
|
|
return unless ENV['ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH'] == 'true'
|
|
|
|
|
|
|
|
email, email_is_verified = email_from_oauth(auth)
|
|
|
|
return unless email_is_verified
|
|
|
|
|
|
|
|
user = User.find_by(email: email)
|
|
|
|
return if user.nil? || Identity.exists?(provider: auth.provider, user_id: user.id)
|
|
|
|
|
|
|
|
user
|
|
|
|
end
|
|
|
|
|
2018-02-04 05:42:13 +01:00
|
|
|
def create_for_oauth(auth)
|
2024-02-09 15:06:07 +01:00
|
|
|
# Create a user for the given auth params. If no email was provided,
|
2022-03-09 06:07:35 -05:00
|
|
|
# we assign a temporary email and ask the user to verify it on
|
Change unconfirmed user login behaviour (#11375)
Allow access to account settings, 2FA, authorized applications, and
account deletions to unconfirmed and pending users, as well as
users who had their accounts disabled. Suspended users cannot update
their e-mail or password or delete their account.
Display account status on account settings page, for example, when
an account is frozen, limited, unconfirmed or pending review.
After sign up, login users straight away and show a simple page that
tells them the status of their account with links to account settings
and logout, to reduce onboarding friction and allow users to correct
wrongly typed e-mail addresses.
Move the final sign-up step of SSO integrations to be the same
as above to reduce code duplication.
2019-07-22 10:48:50 +02:00
|
|
|
# the next step via Auth::SetupController.show
|
2018-02-04 05:42:13 +01:00
|
|
|
|
2024-02-09 15:06:07 +01:00
|
|
|
email, email_is_verified = email_from_oauth(auth)
|
2019-09-16 20:42:29 +02:00
|
|
|
|
|
|
|
user = User.new(user_params_from_auth(email, auth))
|
|
|
|
|
2023-01-13 15:40:06 +00:00
|
|
|
begin
|
2023-02-18 06:37:47 -05:00
|
|
|
user.account.avatar_remote_url = auth.info.image if /\A#{URI::DEFAULT_PARSER.make_regexp(%w(http https))}\z/.match?(auth.info.image)
|
2023-01-13 15:40:06 +00:00
|
|
|
rescue Mastodon::UnexpectedResponseError
|
|
|
|
user.account.avatar_remote_url = nil
|
|
|
|
end
|
|
|
|
|
2024-01-15 19:04:58 +01:00
|
|
|
user.mark_email_as_confirmed! if email_is_verified
|
2018-02-04 05:42:13 +01:00
|
|
|
user.save!
|
|
|
|
user
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2024-02-09 15:06:07 +01:00
|
|
|
def email_from_oauth(auth)
|
|
|
|
strategy = Devise.omniauth_configs[auth.provider.to_sym].strategy
|
|
|
|
assume_verified = strategy&.security&.assume_email_is_verified
|
|
|
|
email_is_verified = auth.info.verified || auth.info.verified_email || auth.info.email_verified || assume_verified
|
|
|
|
email = auth.info.verified_email || auth.info.email
|
|
|
|
|
|
|
|
[email, email_is_verified]
|
|
|
|
end
|
|
|
|
|
2019-09-16 20:42:29 +02:00
|
|
|
def user_params_from_auth(email, auth)
|
2018-02-04 05:42:13 +01:00
|
|
|
{
|
2018-10-08 13:50:11 +11:00
|
|
|
email: email || "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
|
2019-01-25 12:36:54 +01:00
|
|
|
agreement: true,
|
2019-04-25 02:49:25 +02:00
|
|
|
external: true,
|
2018-02-04 05:42:13 +01:00
|
|
|
account_attributes: {
|
2022-03-09 06:07:35 -05:00
|
|
|
username: ensure_unique_username(ensure_valid_username(auth.uid)),
|
|
|
|
display_name: auth.info.full_name || auth.info.name || [auth.info.first_name, auth.info.last_name].join(' '),
|
2018-02-04 05:42:13 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def ensure_unique_username(starting_username)
|
|
|
|
username = starting_username
|
|
|
|
i = 0
|
|
|
|
|
2020-04-30 14:39:05 +02:00
|
|
|
while Account.exists?(username: username, domain: nil)
|
2018-02-04 05:42:13 +01:00
|
|
|
i += 1
|
|
|
|
username = "#{starting_username}_#{i}"
|
|
|
|
end
|
|
|
|
|
|
|
|
username
|
|
|
|
end
|
2022-03-09 06:07:35 -05:00
|
|
|
|
|
|
|
def ensure_valid_username(starting_username)
|
|
|
|
starting_username = starting_username.split('@')[0]
|
|
|
|
temp_username = starting_username.gsub(/[^a-z0-9_]+/i, '')
|
2023-02-08 01:06:50 -05:00
|
|
|
temp_username.truncate(30, omission: '')
|
2022-03-09 06:07:35 -05:00
|
|
|
end
|
2018-02-04 05:42:13 +01:00
|
|
|
end
|
|
|
|
end
|