168 lines
4.4 KiB
Ruby
168 lines
4.4 KiB
Ruby
class Auth::FacebookAuthenticator < Auth::Authenticator
|
|
|
|
AVATAR_SIZE ||= 480
|
|
|
|
def name
|
|
"facebook"
|
|
end
|
|
|
|
def enabled?
|
|
SiteSetting.enable_facebook_logins
|
|
end
|
|
|
|
def description_for_user(user)
|
|
info = FacebookUserInfo.find_by(user_id: user.id)
|
|
info&.email || info&.username || ""
|
|
end
|
|
|
|
def can_revoke?
|
|
true
|
|
end
|
|
|
|
def revoke(user, skip_remote: false)
|
|
info = FacebookUserInfo.find_by(user_id: user.id)
|
|
raise Discourse::NotFound if info.nil?
|
|
|
|
if skip_remote
|
|
info.destroy!
|
|
return true
|
|
end
|
|
|
|
response = Excon.delete(revoke_url(info.facebook_user_id))
|
|
|
|
if response.status == 200
|
|
info.destroy!
|
|
return true
|
|
end
|
|
|
|
false
|
|
end
|
|
|
|
def revoke_url(fb_user_id)
|
|
"https://graph.facebook.com/#{fb_user_id}/permissions?access_token=#{SiteSetting.facebook_app_id}|#{SiteSetting.facebook_app_secret}"
|
|
end
|
|
|
|
def can_connect_existing_user?
|
|
true
|
|
end
|
|
|
|
def after_authenticate(auth_token, existing_account: nil)
|
|
result = Auth::Result.new
|
|
|
|
session_info = parse_auth_token(auth_token)
|
|
facebook_hash = session_info[:facebook]
|
|
|
|
result.email = email = session_info[:email]
|
|
result.email_valid = !email.blank?
|
|
result.name = facebook_hash[:name]
|
|
|
|
result.extra_data = facebook_hash
|
|
|
|
user_info = FacebookUserInfo.find_by(facebook_user_id: facebook_hash[:facebook_user_id])
|
|
|
|
if existing_account && (user_info.nil? || existing_account.id != user_info.user_id)
|
|
user_info.destroy! if user_info
|
|
result.user = existing_account
|
|
user_info = FacebookUserInfo.create!({ user_id: result.user.id }.merge(facebook_hash))
|
|
else
|
|
result.user = user_info&.user
|
|
end
|
|
|
|
if !result.user && !email.blank? && result.user = User.find_by_email(email)
|
|
FacebookUserInfo.create!({ user_id: result.user.id }.merge(facebook_hash))
|
|
end
|
|
|
|
user_info.update_columns(facebook_hash) if user_info
|
|
|
|
retrieve_avatar(result.user, result.extra_data)
|
|
retrieve_profile(result.user, result.extra_data)
|
|
|
|
if email.blank?
|
|
UserHistory.create(
|
|
action: UserHistory.actions[:facebook_no_email],
|
|
details: "name: #{facebook_hash[:name]}, facebook_user_id: #{facebook_hash[:facebook_user_id]}"
|
|
)
|
|
end
|
|
|
|
result
|
|
end
|
|
|
|
def after_create_account(user, auth)
|
|
extra_data = auth[:extra_data]
|
|
FacebookUserInfo.create!({ user_id: user.id }.merge(extra_data))
|
|
|
|
retrieve_avatar(user, extra_data)
|
|
retrieve_profile(user, extra_data)
|
|
|
|
true
|
|
end
|
|
|
|
def register_middleware(omniauth)
|
|
omniauth.provider :facebook,
|
|
setup: lambda { |env|
|
|
strategy = env["omniauth.strategy"]
|
|
strategy.options[:client_id] = SiteSetting.facebook_app_id
|
|
strategy.options[:client_secret] = SiteSetting.facebook_app_secret
|
|
strategy.options[:info_fields] = 'gender,email,name,about,first_name,link,last_name,website,location'
|
|
},
|
|
scope: "email"
|
|
end
|
|
|
|
protected
|
|
|
|
def parse_auth_token(auth_token)
|
|
raw_info = auth_token["extra"]["raw_info"]
|
|
info = auth_token["info"]
|
|
|
|
email = auth_token["info"][:email]
|
|
|
|
website = (info["urls"] && info["urls"]["Website"]) || nil
|
|
|
|
{
|
|
facebook: {
|
|
facebook_user_id: auth_token["uid"],
|
|
link: raw_info["link"],
|
|
username: raw_info["username"],
|
|
first_name: raw_info["first_name"],
|
|
last_name: raw_info["last_name"],
|
|
email: email,
|
|
gender: raw_info["gender"],
|
|
name: raw_info["name"],
|
|
avatar_url: info["image"],
|
|
location: info["location"],
|
|
website: website,
|
|
about_me: info["description"]
|
|
},
|
|
email: email,
|
|
email_valid: true
|
|
}
|
|
end
|
|
|
|
def retrieve_avatar(user, data)
|
|
return unless user
|
|
return if user.user_avatar.try(:custom_upload_id).present?
|
|
|
|
if (avatar_url = data[:avatar_url]).present?
|
|
url = "#{avatar_url}?height=#{AVATAR_SIZE}&width=#{AVATAR_SIZE}"
|
|
Jobs.enqueue(:download_avatar_from_url, url: url, user_id: user.id, override_gravatar: false)
|
|
end
|
|
end
|
|
|
|
def retrieve_profile(user, data)
|
|
return unless user
|
|
|
|
bio = data[:about_me] || data[:about]
|
|
location = data[:location]
|
|
website = data[:website]
|
|
|
|
if bio || location || website
|
|
profile = user.user_profile
|
|
profile.bio_raw = bio unless profile.bio_raw.present?
|
|
profile.location = location unless profile.location.present?
|
|
profile.website = website unless profile.website.present?
|
|
profile.save
|
|
end
|
|
end
|
|
|
|
end
|