From 37f08f7146c0146766f6de201b222d5e69a35ee3 Mon Sep 17 00:00:00 2001 From: Peter Cai <222655+pcai@users.noreply.github.com> Date: Mon, 8 Jul 2024 20:40:01 +0000 Subject: [PATCH] oauth support by @fliebe92 --- lib/ews/connection.rb | 67 ++++++++++++++++++++--------- lib/ews/ews_client.rb | 23 ++++++---- spec/ews/ews_client_spec.rb | 2 +- spec/unit/mailbox_accessors_spec.rb | 2 +- spec/unit/meeting_accessors_spec.rb | 2 +- 5 files changed, 63 insertions(+), 33 deletions(-) diff --git a/lib/ews/connection.rb b/lib/ews/connection.rb index edc4ab55..f5fc0e70 100644 --- a/lib/ews/connection.rb +++ b/lib/ews/connection.rb @@ -32,28 +32,15 @@ class Viewpoint::EWS::Connection # seconds # @option opts [Array] :trust_ca an array of hashed dir paths or a file # @option opts [String] :user_agent the http user agent to use in all requests - def initialize(endpoint, opts = {}) + def initialize(auth, opts = {}) @log = Logging.logger[self.class.name.to_s.to_sym] - if opts[:user_agent] - @httpcli = HTTPClient.new(agent_name: opts[:user_agent]) - else - @httpcli = HTTPClient.new - end - if opts[:trust_ca] - @httpcli.ssl_config.clear_cert_store - opts[:trust_ca].each do |ca| - @httpcli.ssl_config.add_trust_ca ca - end - end + @httpcli = http_object(opts) - @httpcli.ssl_config.verify_mode = opts[:ssl_verify_mode] if opts[:ssl_verify_mode] - @httpcli.ssl_config.ssl_version = opts[:ssl_version] if opts[:ssl_version] - # Up the keep-alive so we don't have to do the NTLM dance as often. - @httpcli.keep_alive_timeout = 60 - @httpcli.receive_timeout = opts[:receive_timeout] if opts[:receive_timeout] - @httpcli.connect_timeout = opts[:connect_timeout] if opts[:connect_timeout] - @endpoint = endpoint + @auth_type = auth[:type] + @auth_token = @auth_type == 'oauth' ? auth[:token] : nil + + @endpoint = auth[:endpoint] end def set_auth(user,pass) @@ -99,8 +86,11 @@ def get # @return [String] If the request is successful (200) it returns the body of # the response. def post(xmldoc) - headers = {'Content-Type' => 'text/xml'} - check_response( @httpcli.post(@endpoint, xmldoc, headers) ) + headers = { 'Content-Type' => 'text/xml' } + if @auth_type == 'oauth' && @auth_token.present? + headers = headers.merge({ 'Authorization' => "Bearer #{@auth_token}" }) + end + check_response(@httpcli.post(@endpoint, xmldoc, headers)) end @@ -137,4 +127,39 @@ def parse_soap_error(xml) [err_string, err_code] end + def http_object(opts) + @httpcli = if opts[:user_agent] + HTTPClient.new(agent_name: opts[:user_agent]) + else + HTTPClient.new + end + + trust_ca_option(opts) + ssl_config(opts) + timeout_options(opts) + + @httpcli + end + + def trust_ca_option(opts) + return if opts[:trust_ca].nil? + + @httpcli.ssl_config.clear_cert_store + opts[:trust_ca].each do |ca| + @httpcli.ssl_config.add_trust_ca ca + end + end + + def ssl_config(opts) + @httpcli.ssl_config.verify_mode = opts[:ssl_verify_mode] if opts[:ssl_verify_mode] + @httpcli.ssl_config.ssl_version = opts[:ssl_version] if opts[:ssl_version] + end + + def timeout_options(opts) + # Up the keep-alive so we don't have to do the NTLM dance as often. + @httpcli.keep_alive_timeout = 60 + @httpcli.receive_timeout = opts[:receive_timeout] if opts[:receive_timeout] + @httpcli.connect_timeout = opts[:connect_timeout] if opts[:connect_timeout] + end + end diff --git a/lib/ews/ews_client.rb b/lib/ews/ews_client.rb index 2d0a43d3..e871c35a 100644 --- a/lib/ews/ews_client.rb +++ b/lib/ews/ews_client.rb @@ -39,16 +39,21 @@ class Viewpoint::EWSClient # Viewpoint::EWS::SOAP::ExchangeWebService. # @option opts [Object] :http_class specify an alternate HTTP connection class. # @option opts [Hash] :http_opts options to pass to the connection - def initialize(endpoint, username, password, opts = {}) - # dup all. @see ticket https://github.com/zenchild/Viewpoint/issues/68 - @endpoint = endpoint.dup - @username = username.dup - password = password.dup - opts = opts.dup + def initialize(auth, opts = {}) + auth = auth.dup + + @auth_type = auth[:type] + @auth_token = @auth_type == 'oauth' ? auth[:token] : nil + + @endpoint = auth[:endpoint] + @username = auth[:user] + password = @auth_type == 'basic' ? auth[:password] : nil + http_klass = opts[:http_class] || Viewpoint::EWS::Connection - con = http_klass.new(endpoint, opts[:http_opts] || {}) - con.set_auth @username, password - @ews = SOAP::ExchangeWebService.new(con, opts) + connection = http_klass.new(auth, opts[:http_opts] || {}) + connection.set_auth(@username, password) unless password.nil? + + @ews = Viewpoint::EWS::SOAP::ExchangeWebService.new(connection, opts) end # @param deepen [Boolean] true to autodeepen, false otherwise diff --git a/spec/ews/ews_client_spec.rb b/spec/ews/ews_client_spec.rb index 871d86c6..a80b4e9e 100644 --- a/spec/ews/ews_client_spec.rb +++ b/spec/ews/ews_client_spec.rb @@ -3,7 +3,7 @@ describe Viewpoint::EWSClient do describe "#set_auto_deepen" do - let(:client) { described_class.new "http://www.example.com", "test", "test" } + let(:client) { described_class.new({endpoint: "http://www.example.com", type: "basic", user: "test", password: "test"}) } it "sets autodeepen to true on the web service" do ews = double "ews" diff --git a/spec/unit/mailbox_accessors_spec.rb b/spec/unit/mailbox_accessors_spec.rb index 5afacfe4..49b341d8 100644 --- a/spec/unit/mailbox_accessors_spec.rb +++ b/spec/unit/mailbox_accessors_spec.rb @@ -1,7 +1,7 @@ require_relative '../spec_helper' describe Viewpoint::EWS::MailboxAccessors do - let(:ecli) { Viewpoint::EWSClient.new('dontcare', 'dontcare', 'dontcare') } + let(:ecli) { Viewpoint::EWSClient.new({endpoint: 'dontcare', user: 'dontcare', password: 'dontcare'}) } let(:recipients) { ['anyrecipient'] } let(:timezone_request) do " diff --git a/spec/unit/meeting_accessors_spec.rb b/spec/unit/meeting_accessors_spec.rb index d2dd46e6..1cf8f9fc 100644 --- a/spec/unit/meeting_accessors_spec.rb +++ b/spec/unit/meeting_accessors_spec.rb @@ -1,7 +1,7 @@ require_relative '../spec_helper' describe Viewpoint::EWS::MeetingAccessors do - let(:ecli) { Viewpoint::EWSClient.new('dontcare', 'dontcare', 'dontcare') } + let(:ecli) { Viewpoint::EWSClient.new({endpoint: 'dontcare', user: 'dontcare', password: 'dontcare'}) } let(:default_opts) do {