From 1ec564d7f2cd8ee872c31e8de799ca5508aa90e7 Mon Sep 17 00:00:00 2001 From: Jason Frey Date: Tue, 26 Mar 2024 13:47:05 -0400 Subject: [PATCH 1/2] Add GitHub Actions for CI Additionally fix an issue where the delegation module was not required --- .github/workflows/ci.yaml | 36 ++++++++++++++++++++++++++++++++++++ .gitignore | 1 + .rspec | 1 + Gemfile | 6 ++++-- lib/servicenow.rb | 1 + spec/spec_helper.rb | 4 ++++ 6 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/ci.yaml create mode 100644 .rspec diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..94c8b55 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,36 @@ +name: CI + +on: + push: + pull_request: + schedule: + - cron: '0 0 * * 0' + workflow_dispatch: + +jobs: + ci: + runs-on: ubuntu-latest + strategy: + matrix: + ruby-version: + - '2.7' + - '3.0' + - '3.1' + rails-version: + - '5.2' + - '6.0' + - '6.1' + - '7.0' + env: + TEST_RAILS_VERSION: ${{ matrix.rails-version }} + CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} + steps: + - uses: actions/checkout@v4 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby-version }} + bundler-cache: true + timeout-minutes: 30 + - name: Run tests + run: bundle exec rake diff --git a/.gitignore b/.gitignore index 5011f4d..bd1f5de 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,4 @@ build-iPhoneSimulator/ # .rubocop-https?--* Gemfile.lock +.rspec_status diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..c99d2e7 --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--require spec_helper diff --git a/Gemfile b/Gemfile index 2ca2854..1bbabcb 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,8 @@ source "https://rubygems.org" -git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } - # Specify your gem's dependencies in servicenow-ruby.gemspec gemspec + +if ENV["TEST_RAILS_VERSION"] + gem "activesupport", "~> #{ENV["TEST_RAILS_VERSION"]}.0" +end diff --git a/lib/servicenow.rb b/lib/servicenow.rb index 141b3f6..9996cc3 100644 --- a/lib/servicenow.rb +++ b/lib/servicenow.rb @@ -2,6 +2,7 @@ require "active_support" require "active_support/core_ext/hash" +require "active_support/core_ext/module/delegation" module ServiceNow require "servicenow/api" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 0c47393..60037bc 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -12,3 +12,7 @@ c.syntax = :expect end end + +require "active_support" +puts +puts "\e[93mUsing ActiveSupport #{ActiveSupport.version}\e[0m" From 79703c2915ff063cdbeaafa062dfbaecf7f84e6d Mon Sep 17 00:00:00 2001 From: Jason Frey Date: Tue, 26 Mar 2024 11:32:04 -0400 Subject: [PATCH 2/2] Add ability to authenticate with a refresh token --- lib/servicenow/client.rb | 30 +++++++++++++++------- spec/client_spec.rb | 54 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 spec/client_spec.rb diff --git a/lib/servicenow/client.rb b/lib/servicenow/client.rb index 9abba32..2dcb650 100644 --- a/lib/servicenow/client.rb +++ b/lib/servicenow/client.rb @@ -6,6 +6,26 @@ class Client class << self def authenticate(instance_id, client_id, client_secret, username, password) + authenticate_with_params(instance_id, + grant_type: "password", + client_id: client_id, + client_secret: client_secret, + username: username, + password: password + ) + end + + def authenticate_with_refresh_token(instance_id, client_id, client_secret, refresh_token) + authenticate_with_params(instance_id, + grant_type: "refresh_token", + client_id: client_id, + client_secret: client_secret, + refresh_token: refresh_token, + scope: "useraccount" + ) + end + + private def authenticate_with_params(instance_id, params) connection_options = { url: "https://#{instance_id}.service-now.com/" } @@ -17,14 +37,6 @@ def authenticate(instance_id, client_id, client_secret, username, password) faraday.adapter Faraday.default_adapter end - params = { - grant_type: "password", - client_id: client_id, - client_secret: client_secret, - username: username, - password: password - } - response = conn.post('oauth_token.do', params) connection = Connection.new(instance_id, response.body["access_token"]) Client.new(connection) @@ -47,4 +59,4 @@ def cmdb_instance(instance_class) Client::CMDB.new(@connection, instance_class) end end -end \ No newline at end of file +end diff --git a/spec/client_spec.rb b/spec/client_spec.rb new file mode 100644 index 0000000..ee0e151 --- /dev/null +++ b/spec/client_spec.rb @@ -0,0 +1,54 @@ +RSpec.describe ServiceNow::Client do + let(:instance_id) { "instance_id_foo" } + let(:client_id) { "client_id_foo" } + let(:client_secret) { "client_secret_foo" } + let(:username) { "some_user" } + let(:password) { "p4ssw0rd" } + let(:refresh_token) { "refresh_token_foo" } + let(:access_token) { "access_token_foo" } + + let(:connection) { double(Faraday) } + let(:response) { double(Faraday::Response, body: {"access_token" => access_token}) } + + describe ".authenticate" do + it "connects" do + expect(Faraday).to receive(:new).with({url: "https://#{instance_id}.service-now.com/"}).and_return(connection) + expect(connection).to receive(:post).with("oauth_token.do", + { + client_id: client_id, + client_secret: client_secret, + grant_type: "password", + username: username, + password: password + } + ).and_return(response) + + client = described_class.authenticate(instance_id, client_id, client_secret, username, password) + + expect(client).to be_a(described_class) + expect(client.connection).to be_a(ServiceNow::Connection) + expect(client.connection.headers["Authorization"]).to eq("Bearer #{access_token}") + end + end + + describe ".authenticate_with_refresh_token" do + it "connects" do + expect(Faraday).to receive(:new).with({url: "https://#{instance_id}.service-now.com/"}).and_return(connection) + expect(connection).to receive(:post).with("oauth_token.do", + { + client_id: client_id, + client_secret: client_secret, + grant_type: "refresh_token", + refresh_token: refresh_token, + scope: "useraccount" + } + ).and_return(response) + + client = described_class.authenticate_with_refresh_token(instance_id, client_id, client_secret, refresh_token) + + expect(client).to be_a(described_class) + expect(client.connection).to be_a(ServiceNow::Connection) + expect(client.connection.headers["Authorization"]).to eq("Bearer #{access_token}") + end + end +end