# frozen_string_literal: true module Octokit class Client # Methods for the Users API # # @see https://developer.github.com/v3/users/ module Users # List all GitHub users # # This provides a list of every user, in the order that they signed up # for GitHub. # # @param options [Hash] Optional options. # @option options [Integer] :since The integer ID of the last User that # you’ve seen. # # @see https://developer.github.com/v3/users/#get-all-users # # @return [Array] List of GitHub users. def all_users(options = {}) paginate 'users', options end # Get a single user # # @param user [Integer, String] GitHub user login or id. # @return [Sawyer::Resource] # @see https://developer.github.com/v3/users/#get-a-single-user # @see https://developer.github.com/v3/users/#get-the-authenticated-user # @example # Octokit.user("sferik") def user(user = nil, options = {}) get User.path(user), options end # Retrieve the access_token. # # @param code [String] Authorization code generated by GitHub. # @param app_id [String] Client Id we received when our application was registered with GitHub. Defaults to client_id. # @param app_secret [String] Client Secret we received when our application was registered with GitHub. Defaults to client_secret. # @return [Sawyer::Resource] Hash holding the access token. # @see https://developer.github.com/v3/oauth/#web-application-flow # @example # Octokit.exchange_code_for_token('aaaa', 'xxxx', 'yyyy', {:accept => 'application/json'}) def exchange_code_for_token(code, app_id = client_id, app_secret = client_secret, options = {}) options = options.merge({ code: code, client_id: app_id, client_secret: app_secret, headers: { content_type: 'application/json', accept: 'application/json' } }) post "#{web_endpoint}login/oauth/access_token", options end # Refresh a user's access token with a refresh token. # # Applications can refresh an access token without requiring a user to re-authorize using refresh access token. # # @param code [String] 40 character GitHub OAuth refresh access token # # @return [Sawyer::Resource] # @see https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/refreshing-user-access-tokens#refreshing-a-user-access-token-with-a-refresh-token # # @example # client = Octokit::Client.new(:client_id => 'abcdefg12345', :client_secret => 'secret') # client.refresh_access_token('40-character-refresh-token') def refresh_access_token(code, app_id = client_id, app_secret = client_secret, options = {}) options = options.merge({ refresh_token: code, client_id: app_id, client_secret: app_secret, grant_type: 'refresh_token', headers: { content_type: 'application/json', accept: 'application/json' } }) post "#{web_endpoint}login/oauth/access_token", options end # Validate user username and password # # @param options [Hash] User credentials # @option options [String] :login GitHub login # @option options [String] :password GitHub password # @return [Boolean] True if credentials are valid def validate_credentials(options = {}) !self.class.new(options).user.nil? rescue Octokit::Unauthorized false end # Update the authenticated user # # @param options [Hash] A customizable set of options. # @option options [String] :name # @option options [String] :email Publically visible email address. # @option options [String] :blog # @option options [String] :company # @option options [String] :location # @option options [Boolean] :hireable # @option options [String] :bio # @return [Sawyer::Resource] # @see https://developer.github.com/v3/users/#update-the-authenticated-user # @example # Octokit.update_user(:name => "Erik Michaels-Ober", :email => "sferik@gmail.com", :company => "Code for America", :location => "San Francisco", :hireable => false) def update_user(options) patch 'user', options end # Get a user's followers. # # @param user [Integer, String] GitHub user login or id of the user whose # list of followers you are getting. # @return [Array] Array of hashes representing users # followers. # @see https://developer.github.com/v3/users/followers/#list-followers-of-a-user # @example # Octokit.followers('pengwynn') def followers(user = login, options = {}) paginate "#{User.path user}/followers", options end # Get list of users a user is following. # # @param user [Intger, String] GitHub user login or id of the user who you # are getting the list of the people they follow. # @return [Array] Array of hashes representing users a # user is following. # @see https://developer.github.com/v3/users/followers/#list-users-followed-by-another-user # @example # Octokit.following('pengwynn') def following(user = login, options = {}) paginate "#{User.path user}/following", options end # Check if you are following a user. Alternatively, check if a given user # is following a target user. # # Requries an authenticated client. # # @overload follows?(target) # @param target [String] GitHub login of the user that you want to # check if you are following. # @overload follows?(user, target) # @param user [Integer, String] GitHub user login or id of first user # @param target [String] GitHub login of the target user # @return [Boolean] True following target user, false otherwise. # @see https://developer.github.com/v3/users/followers/#check-if-you-are-following-a-user # @see https://developer.github.com/v3/users/followers/#check-if-one-user-follows-another # @example # @client.follows?('pengwynn') # @example # @client.follows?('catsby', 'pengwynn') def follows?(*args) target = args.pop user = args.first boolean_from_response :get, "#{User.path user}/following/#{target}" end # Follow a user. # # Requires authenticatied client. # # @param user [String] Username of the user to follow. # @return [Boolean] True if follow was successful, false otherwise. # @see https://developer.github.com/v3/users/followers/#follow-a-user # @example # @client.follow('holman') def follow(user, options = {}) boolean_from_response :put, "user/following/#{user}", options end # Unfollow a user. # # Requires authenticated client. # # @param user [String] Username of the user to unfollow. # @return [Boolean] True if unfollow was successful, false otherwise. # @see https://developer.github.com/v3/users/followers/#unfollow-a-user # @example # @client.unfollow('holman') def unfollow(user, options = {}) boolean_from_response :delete, "user/following/#{user}", options end # Get list of repos starred by a user. # # @param user [Integer, String] GitHub user login of the user to get the # list of their starred repositories. # @param options [Hash] Optional options # @option options [String] :sort (created) Sort: created or updated. # @option options [String] :direction (desc) Direction: asc or desc. # @return [Array] Array of hashes representing repositories starred by user. # @see https://developer.github.com/v3/activity/starring/#list-repositories-being-starred # @example # Octokit.starred('pengwynn') def starred(user = login, options = {}) paginate user_path(user, 'starred'), options end # Check if you are starring a repo. # # Requires authenticated client. # # @param repo [String, Hash, Repository] A GitHub repository # @return [Boolean] True if you are following the repo, false otherwise. # @see https://developer.github.com/v3/activity/starring/#check-if-you-are-starring-a-repository # @example # @client.starred?('pengwynn/octokit') def starred?(repo, options = {}) boolean_from_response :get, "user/starred/#{Repository.new(repo)}", options end # Get a public key. # # Note, when using dot notation to retrieve the values, ruby will return # the hash key for the public keys value instead of the actual value, use # symbol or key string to retrieve the value. See example. # # Requires authenticated client. # # @param key_id [Integer] Key to retreive. # @return [Sawyer::Resource] Hash representing the key. # @see https://developer.github.com/v3/users/keys/#get-a-single-public-key # @example # @client.key(1) # @example Retrieve public key contents # public_key = @client.key(1) # public_key.key # # => Error # # public_key[:key] # # => "ssh-rsa AAA..." # # public_key['key'] # # => "ssh-rsa AAA..." def key(key_id, options = {}) get "user/keys/#{key_id}", options end # Get list of public keys for user. # # Requires authenticated client. # # @return [Array] Array of hashes representing public keys. # @see https://developer.github.com/v3/users/keys/#list-your-public-keys # @example # @client.keys def keys(options = {}) paginate 'user/keys', options end # Get list of public keys for user. # # @param user [Integer, String] GitHub user login or id. # @return [Array] Array of hashes representing public keys. # @see https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user # @example # @client.user_keys('pengwynn') def user_keys(user, options = {}) # TODO: Roll this into .keys paginate "#{User.path user}/keys", options end # Add public key to user account. # # Requires authenticated client. # # @param title [String] Title to give reference to the public key. # @param key [String] Public key. # @return [Sawyer::Resource] Hash representing the newly added public key. # @see https://developer.github.com/v3/users/keys/#create-a-public-key # @example # @client.add_key('Personal projects key', 'ssh-rsa AAA...') def add_key(title, key, options = {}) post 'user/keys', options.merge({ title: title, key: key }) end # Update a public key # # Requires authenticated client # # @param key_id [Integer] Id of key to update. # @param options [Hash] Hash containing attributes to update. # @option options [String] :title # @option options [String] :key # @return [Sawyer::Resource] Hash representing the updated public key. # # @deprecated This method is no longer supported in the API # @see https://developer.github.com/v3/users/keys/#update-a-public-key # @see https://developer.github.com/changes/2014-02-24-finer-grained-scopes-for-ssh-keys/ # @example # @client.update_key(1, :title => 'new title', :key => "ssh-rsa BBB") def update_key(key_id, options = {}) patch "user/keys/#{key_id}", options end # Remove a public key from user account. # # Requires authenticated client. # # @param id [String] Id of the public key to remove. # @return [Boolean] True if removal was successful, false otherwise. # @see https://developer.github.com/v3/users/keys/#delete-a-public-key # @example # @client.remove_key(1) def remove_key(id, options = {}) boolean_from_response :delete, "user/keys/#{id}", options end # List email addresses for a user. # # Requires authenticated client. # # @return [Array] Array of email addresses. # @see https://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user # @example # @client.emails def emails(options = {}) paginate 'user/emails', options end # Add email address to user. # # Requires authenticated client. # # @param email [String] Email address to add to the user. # @return [Array] Array of all email addresses of the user. # @see https://developer.github.com/v3/users/emails/#add-email-addresses # @example # @client.add_email('new_email@user.com') def add_email(email, _options = {}) email = Array(email) post 'user/emails', email end # Remove email from user. # # Requires authenticated client. # # @param email [String] Email address to remove. # @return [Array] Array of all email addresses of the user. # @see https://developer.github.com/v3/users/emails/#delete-email-addresses # @example # @client.remove_email('old_email@user.com') def remove_email(email) email = Array(email) boolean_from_response :delete, 'user/emails', email end # List repositories being watched by a user. # # @param user [Integer, String] GitHub user login or id. # @return [Array] Array of repositories. # @see https://developer.github.com/v3/activity/watching/#list-repositories-being-watched # @example # @client.subscriptions("pengwynn") def subscriptions(user = login, options = {}) paginate user_path(user, 'subscriptions'), options end alias watched subscriptions # Initiates the generation of a migration archive. # # Requires authenticated user. # # @param repositories [Array] :repositories Repositories for the organization. # @option options [Boolean, optional] :lock_repositories Indicates whether repositories should be locked during migration # @option options [Boolean, optional] :exclude_attachments Exclude attachments fro the migration data # @return [Sawyer::Resource] Hash representing the new migration. # @example # @client.start_migration(['octocat/hello-world']) # @see https://docs.github.com/en/rest/reference/migrations#start-a-user-migration def start_user_migration(repositories, options = {}) options[:repositories] = repositories post 'user/migrations', options end # Lists the most recent migrations. # # Requires authenticated user. # # @return [Array] Array of migration resources. # @see https://docs.github.com/en/rest/reference/migrations#list-user-migrations def user_migrations(options = {}) paginate 'user/migrations', options end # Fetches the status of a migration. # # Requires authenticated user. # # @param id [Integer] ID number of the migration. # @see https://docs.github.com/en/rest/reference/migrations#get-a-user-migration-status def user_migration_status(id, options = {}) get "user/migrations/#{id}", options end # Fetches the URL to a migration archive. # # Requires authenticated user. # # @param id [Integer] ID number of the migration. # @see https://docs.github.com/en/rest/reference/migrations#download-a-user-migration-archive def user_migration_archive_url(id, options = {}) url = "user/migrations/#{id}/archive" response = client_without_redirects(options).get(url) response.headers['location'] end # Deletes a previous migration archive. # # Requires authenticated user. # # @param id [Integer] ID number of the migration. # @see https://docs.github.com/en/rest/reference/migrations#delete-a-user-migration-archive def delete_user_migration_archive(id, options = {}) delete "user/migrations/#{id}/archive", options end # List repositories for a user migration. # # Requires authenticated user. # # @param id [Integer] ID number of the migration. # @see https://docs.github.com/en/rest/reference/migrations#list-repositories-for-a-user-migration def user_migration_repositories(id, options = {}) get "user/migrations/#{id}/repositories", options end # Unlock a user repository which has been locked by a migration. # # Requires authenticated user. # # @param id [Integer] ID number of the migration. # @param repo [String] Name of the repository. # @see https://docs.github.com/en/rest/reference/migrations#unlock-a-user-repository def unlock_user_repository(id, repo, options = {}) delete "user/migrations/#{id}/repos/#{repo}/lock", options end end private # convenience method for constructing a user specific path, if the user is logged in def user_path(user, path) if user == login && user_authenticated? "user/#{path}" else "#{User.path user}/#{path}" end end end end