diff --git a/README.md b/README.md index f977b7c..280e77d 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,17 @@ Or install it yourself as: ### Generating an access token -To use the `pcloud_api` client, you will need to first generate an access token. You may do this by cloning and running the script in [`./bin/generate_access_token`](https://github.com/jhunschejones/pcloud_api/blob/master/bin/generate_access_token). It will take you through the process of setting up a pCloud app and completing the OAuth2 flow in the browser. +To use the `pcloud_api` client, you will need to first generate an access token. You may do this by opening a Rails console or IRB session and entering the following code: + +```ruby +irb(main):001:0> require "pcloud_api" +=> true +irb(main):002:0> Pcloud::Client.generate_access_token +=== Follow these steps to generate a pCloud app and access token === +... +``` + +You will be presented with an interactive prompt which will take you through the process of setting up a pCloud app and completing the OAuth2 flow in the browser. At the end of the prompt, your new access token will be displayed. You should save this value in a secure location as it can be used to access your pCloud account data. ### Configuration diff --git a/bin/generate_access_token b/bin/generate_access_token deleted file mode 100755 index 6c61f2b..0000000 --- a/bin/generate_access_token +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env ruby - -require "json" -require "uri" -require "net/http" - -class String - def green; "\033[32m#{self}\033[0m" end - def cyan; "\033[36m#{self}\033[0m" end -end - -puts "1. Register an app at `https://docs.pcloud.com/my_apps/`".cyan - - -puts "2. Enter the client id and secret for the app:".cyan -print "Client ID > " -client_id = $stdin.gets.chomp.freeze -print "Client Secret > " -client_secret = $stdin.gets.chomp.freeze - - -puts "3. Enter the data region of your pCloud account [EU/US]:".cyan -print "> " -region_specific_api_base = $stdin.gets.chomp == "EU" ? "eapi.pcloud.com" : "api.pcloud.com" - - -puts "4. Navigate to this URL to start the access code flow:".cyan -puts "`https://my.pcloud.com/oauth2/authorize?client_id=#{client_id}&response_type=code`" - - -puts "5. After logging in, enter the access code provided below:".cyan -print "> " -access_code = $stdin.gets.chomp.freeze - - -puts "6. Requesting access token from pCloud...".cyan -query = { client_id: client_id, client_secret: client_secret, code: access_code } -uri = URI.parse("https://#{region_specific_api_base}/oauth2_token?#{URI.encode_www_form(query)}") -http = Net::HTTP.new(uri.host, uri.port) -http.use_ssl = true -request = Net::HTTP::Post.new(uri.request_uri) -request["Accept"] = "application/json" -response = http.request(request) -json_response = JSON.parse(response.body) -raise json_response["error"] if json_response["error"] -puts "Done! Your access token is: #{json_response["access_token"]}".green diff --git a/lib/pcloud/client.rb b/lib/pcloud/client.rb index c49c6c4..0b12e90 100644 --- a/lib/pcloud/client.rb +++ b/lib/pcloud/client.rb @@ -33,6 +33,41 @@ def execute(method, query: {}, body: {}) json_response end + def generate_access_token + puts "=== Follow these steps to generate a pCloud app and access token ===" + puts "1. Register an app at `https://docs.pcloud.com/my_apps/`" + + puts "2. Enter the client id and secret for the app:" + print "Client ID > " + client_id = $stdin.gets.chomp + + print "Client Secret > " + client_secret = $stdin.gets.chomp + + puts "3. Enter the data region of your pCloud account [EU/US]:" + print "> " + region_specific_api_base = $stdin.gets.chomp == "EU" ? "eapi.pcloud.com" : "api.pcloud.com" + + puts "4. Navigate to this URL to start the access code flow:" + puts "`https://my.pcloud.com/oauth2/authorize?client_id=#{client_id}&response_type=code`" + puts "5. After logging in, enter the access code provided below:" + print "> " + access_code = $stdin.gets.chomp + + puts "6. Requesting access token from pCloud..." + query = { client_id: client_id, client_secret: client_secret, code: access_code } + response = HTTParty.post( + "https://#{region_specific_api_base}/oauth2_token?#{URI.encode_www_form(query)}", + headers: { "Accept" => "application/json" } + ) + + json_response = JSON.parse(response.body) + raise json_response["error"] if json_response["error"] + puts "Done! Your access token is: \n#{json_response["access_token"]}" + puts "\nStore this value somewhere secure as it can be used to access your" + puts "pCloud account data and it will not be shown again." + end + private def data_region_from_config_or_env diff --git a/lib/pcloud_api.rb b/lib/pcloud_api.rb index 621359d..db762ec 100644 --- a/lib/pcloud_api.rb +++ b/lib/pcloud_api.rb @@ -2,6 +2,8 @@ require "tzinfo" require "json" require "time" +require "json" +require "uri" require "pcloud/version" require "pcloud/time_helper" diff --git a/spec/pcloud/client_spec.rb b/spec/pcloud/client_spec.rb index eed2e36..ac4f643 100644 --- a/spec/pcloud/client_spec.rb +++ b/spec/pcloud/client_spec.rb @@ -73,6 +73,40 @@ end end + describe ".generate_access_token" do + let(:httparty_response) { double(HTTParty::Response) } + + before do + # silence console output from the interactive CLI + allow(Pcloud::Client).to receive(:puts) + allow(Pcloud::Client).to receive(:print) + + allow(httparty_response).to receive(:body).and_return({ access_token: "Here's your access token!" }.to_json) + allow(HTTParty).to receive(:post).and_return(httparty_response) + end + + it "makes the expected web request to get an access token" do + client_id = "my_client_id" + client_secret = "my_client_secret" + access_code = "pcloud_access_code" + + allow($stdin).to receive(:gets).and_return( + client_id, + client_secret, + "EU", # user specified data region + access_code, # access code provided by pCloud + ) + expect(HTTParty) + .to receive(:post) + .with( + "https://eapi.pcloud.com/oauth2_token?client_id=#{client_id}&client_secret=#{client_secret}&code=#{access_code}", + { headers: { "Accept" => "application/json" } } + ).and_return(httparty_response) + + Pcloud::Client.generate_access_token + end + end + describe ".data_region_from_config_or_env" do it "reads from module configuration" do Pcloud::Client.configure(access_token: "test-token", data_region: "EU")