mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 19:13:38 +08:00
81 lines
2.2 KiB
Ruby
81 lines
2.2 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["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 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
|