mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-04-30 18:08:34 +08:00
This adds a link for each authentication providers that are listed in /my/preferences/account in the "Associated Accounts" section. This is particularly useful when Discourse is being used in the PWA or in the DiscourseMobile app where there's no browser bar available and the only way to visit the provider's website is to open a browser window. That way, they can _just_ click the provider's name. Internal ref - t/156255 --- **BEFORE**  **AFTER** 
89 lines
2.3 KiB
Ruby
89 lines
2.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Auth::DiscordAuthenticator < Auth::ManagedAuthenticator
|
|
class DiscordStrategy < OmniAuth::Strategies::OAuth2
|
|
option :name, "discord"
|
|
option :scope, "identify email guilds"
|
|
|
|
option :client_options,
|
|
site: "https://discord.com/api",
|
|
authorize_url: "oauth2/authorize",
|
|
token_url: "oauth2/token"
|
|
|
|
option :authorize_options, %i[scope permissions]
|
|
|
|
uid { raw_info["id"] }
|
|
|
|
info do
|
|
{
|
|
name: raw_info["global_name"] || raw_info["username"],
|
|
nickname: raw_info["username"],
|
|
email: raw_info["verified"] ? raw_info["email"] : nil,
|
|
image: "https://cdn.discordapp.com/avatars/#{raw_info["id"]}/#{raw_info["avatar"]}",
|
|
}
|
|
end
|
|
|
|
extra { { "raw_info" => raw_info } }
|
|
|
|
def raw_info
|
|
@raw_info ||=
|
|
access_token
|
|
.get("users/@me")
|
|
.parsed
|
|
.merge(guilds: access_token.get("users/@me/guilds").parsed)
|
|
end
|
|
|
|
def callback_url
|
|
full_host + script_name + callback_path
|
|
end
|
|
end
|
|
|
|
def name
|
|
"discord"
|
|
end
|
|
|
|
def display_name
|
|
"Discord"
|
|
end
|
|
|
|
def provider_url
|
|
"https://discord.com"
|
|
end
|
|
|
|
def enabled?
|
|
SiteSetting.enable_discord_logins?
|
|
end
|
|
|
|
def register_middleware(omniauth)
|
|
omniauth.provider DiscordStrategy,
|
|
setup:
|
|
lambda { |env|
|
|
strategy = env["omniauth.strategy"]
|
|
strategy.options[:client_id] = SiteSetting.discord_client_id
|
|
strategy.options[:client_secret] = SiteSetting.discord_secret
|
|
}
|
|
end
|
|
|
|
def after_authenticate(auth_token, existing_account: nil)
|
|
allowed_guild_ids = SiteSetting.discord_trusted_guilds.split("|")
|
|
|
|
if allowed_guild_ids.length > 0
|
|
user_guild_ids = auth_token.extra[:raw_info][:guilds].map { |g| g["id"] }
|
|
if (user_guild_ids & allowed_guild_ids).empty? # User is not in any allowed guilds
|
|
return(
|
|
Auth::Result.new.tap do |auth_result|
|
|
auth_result.failed = true
|
|
auth_result.failed_reason = I18n.t("discord.not_in_allowed_guild")
|
|
end
|
|
)
|
|
end
|
|
end
|
|
|
|
super
|
|
end
|
|
|
|
# the `info` block above only picks the email from Discord API if it's verified
|
|
def primary_email_verified?(auth_token)
|
|
true
|
|
end
|
|
end
|