# frozen_string_literal: true

require "has_errors"

class Auth::GithubAuthenticator < Auth::ManagedAuthenticator
  def name
    "github"
  end

  def enabled?
    SiteSetting.enable_github_logins
  end

  def after_authenticate(auth_token, existing_account: nil)
    result = super
    return result if result.user
    # If email domain restrictions are configured,
    # pick a secondary email which is allowed
    all_github_emails(auth_token).each do |candidate|
      next if !EmailValidator.allowed?(candidate[:email])
      result.email = candidate[:email]
      result.email_valid = !!candidate[:verified]
      break
    end

    result
  end

  def find_user_by_email(auth_token)
    # Use verified secondary emails to find a match
    all_github_emails(auth_token).each do |candidate|
      next if !candidate[:verified]
      if user = User.find_by_email(candidate[:email])
        return user
      end
    end
    nil
  end

  def all_github_emails(auth_token)
    emails = Array.new(auth_token[:extra][:all_emails])
    primary_email = emails.find { |email| email[:primary] }
    if primary_email
      emails.delete(primary_email)
      emails.unshift(primary_email)
    end
    emails
  end

  def register_middleware(omniauth)
    omniauth.provider :github,
                      setup:
                        lambda { |env|
                          strategy = env["omniauth.strategy"]
                          strategy.options[:client_id] = SiteSetting.github_client_id
                          strategy.options[:client_secret] = SiteSetting.github_client_secret
                        },
                      scope: "user:email"
  end

  # the omniauth-github gem only picks up the primary email if it's verified:
  # https://github.com/omniauth/omniauth-github/blob/0ac46b59ccdabd4cbe5be4a665df269355081915/lib/omniauth/strategies/github.rb#L58-L61
  def primary_email_verified?(auth_token)
    true
  end
end