module Warden module GitHub class User < Struct.new(:attribs, :token, :browser_session_id) ATTRIBUTES = %w[id login name gravatar_id avatar_url email company site_admin].freeze attr_accessor :memberships def self.load(access_token, browser_session_id = nil) api = Octokit::Client.new(access_token: access_token) data = { } api.user.to_hash.each do |k,v| data[k.to_s] = v if ATTRIBUTES.include?(k.to_s) end new(data, access_token, browser_session_id) end def marshal_dump Hash[members.zip(values)] end def marshal_load(hash) hash.each { |k,v| send("#{k}=", v) } end ATTRIBUTES.each do |name| define_method(name) { attribs[name] } end # See if the user is a public member of the named organization # # name - the organization name # # Returns: true if the user is publicized as an org member def organization_public_member?(org_name) membership_cache.fetch_membership(:org_pub, org_name) do api.organization_public_member?(org_name, login) end end # Backwards compatibility: alias_method :publicized_organization_member?, :organization_public_member? # See if the user is a member of the named organization # # name - the organization name # # Returns: true if the user has access, false otherwise def organization_member?(org_name) membership_cache.fetch_membership(:org, org_name) do api.organization_member?(org_name, login) end end # See if the user is a member of the team id # # team_id - the team's id # # Returns: true if the user has access, false otherwise def team_member?(team_id) membership_cache.fetch_membership(:team, team_id) do api.team_member?(team_id, login) end end # Identify GitHub employees/staff members. # # Returns: true if the authenticated user is a GitHub employee, false otherwise def site_admin? !!site_admin end # Identify if the browser session is still valid # # Returns: true if the browser session is still active or the GitHub API is unavailable def browser_session_valid?(since = 120) return true unless using_single_sign_out? client = api client.get("/user/sessions/active", browser_session_id: browser_session_id) client.last_response.status == 204 rescue Octokit::ServerError # GitHub API unavailable true rescue Octokit::ClientError => e # GitHub API failed false end # Identify if the user is on a GitHub SSO property # # Returns: true if a browser_session_id is present, false otherwise. def using_single_sign_out? !(browser_session_id.nil? || browser_session_id == "") end # Access the GitHub API from Octokit # # Octokit is a robust client library for the GitHub API # https://github.com/octokit/octokit.rb # # Returns a cached client object for easy use def api # Don't cache instance for now because of a ruby marshaling bug present # in MRI 1.9.3 (Bug #7627) that causes instance variables to be # marshaled even when explicitly specifying #marshal_dump. Octokit::Client.new(login: login, access_token: token) end private def membership_cache self.memberships ||= {} @membership_cache ||= MembershipCache.new(memberships) end end end end