ruby-office365 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3d07710145d0950ccf59cbb228b1ad453d4f157e7dfb941f912c76338e859548
4
- data.tar.gz: 7d62a6296186c5bb8813402890d911ff31e9c9f998e797932f1726a38b76751f
3
+ metadata.gz: d2c2997d3d775d3450dd11a6774e3edee59fc22b307b85b7d525ac561cd19eeb
4
+ data.tar.gz: 02bf02e037717417d889e4a81bbead7ead87210390adfb57f9d1643d851b905e
5
5
  SHA512:
6
- metadata.gz: 3fbea9fe5c09e3ea418f40dbb8fdb90126e0768cd47afd37a698aae0461fbf5d01efe885cd3cc96e55d220ef2067034b4e9cb1d1a1b54db041bd3aff794e20bf
7
- data.tar.gz: ff15f4d0b53888a343b2c39f3bfe060816b7317155b2908bb7d52f341bc0235a7c1ebfcea1cf93a1d6d1a0d4e824b1b1a975bfeae8e36f7bf8092e0c30927823
6
+ metadata.gz: e33d6e7f5d01292a86ecfd6dd70b432f8d4ed88cccdc427a2c09a0c9506610242444a1f49bf48f1c95a306213c7d11d995af5dabcb0fc76073749ea8d0aca14a
7
+ data.tar.gz: 707cd85b26cf08352590ae658cc76f981b0cca8a8c3ded186d44cc712e4ee334bf6ef59bc89ac5097f33441e4ea4c49f7f306dcd51d87d300832650fe25bdeb2
data/.rubocop.yml CHANGED
@@ -10,4 +10,13 @@ Style/StringLiteralsInInterpolation:
10
10
  EnforcedStyle: double_quotes
11
11
 
12
12
  Layout/LineLength:
13
- Max: 120
13
+ Max: 150
14
+
15
+ Metrics/AbcSize:
16
+ Max: 150
17
+
18
+ Style/Documentation:
19
+ Enabled: false
20
+
21
+ Metrics/BlockLength:
22
+ Max: 150
data/CHANGELOG.md CHANGED
@@ -2,4 +2,23 @@
2
2
 
3
3
  ## [0.1.0] - (2022-10-19)
4
4
 
5
- ### Project Setup
5
+ - Project setup and push to rubugems
6
+
7
+ ## [0.1.1] - (2022-10-21)
8
+
9
+ - Integrate REST API to get data from Graph API
10
+ - get profile `client.me`
11
+ - get mailbox `client.messages`
12
+ - get calenders `client.calenders`
13
+
14
+ ## [0.1.2] - (2022-10-21)
15
+
16
+ - Integrate REST API to get mailbox with pagination
17
+ - get mailbox data with next link `client.messages({next_link: 'xxx'})`
18
+ - get mailbox data with next link `client.calenders({next_link: 'xxx'})`
19
+
20
+ ## [0.1.3] - (2022-10-26)
21
+
22
+ - Integrate REST API to get contacts
23
+ - get profile `client.contacts`
24
+ - get contacts data with next link `client.contacts({next_link: 'xxx'})`
data/Gemfile CHANGED
@@ -8,5 +8,3 @@ gemspec
8
8
  gem "rake", "~> 13.0"
9
9
 
10
10
  gem "rspec", "~> 3.0"
11
-
12
- gem "rubocop", "~> 1.21"
data/Gemfile.lock CHANGED
@@ -1,17 +1,56 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby-office365 (0.1.0)
4
+ ruby-office365 (0.1.3)
5
+ faraday
6
+ faraday_middleware
5
7
 
6
8
  GEM
7
9
  remote: https://rubygems.org/
8
10
  specs:
11
+ addressable (2.8.1)
12
+ public_suffix (>= 2.0.2, < 6.0)
9
13
  ast (2.4.2)
14
+ coderay (1.1.3)
15
+ crack (0.4.5)
16
+ rexml
10
17
  diff-lcs (1.5.0)
18
+ faraday (1.10.2)
19
+ faraday-em_http (~> 1.0)
20
+ faraday-em_synchrony (~> 1.0)
21
+ faraday-excon (~> 1.1)
22
+ faraday-httpclient (~> 1.0)
23
+ faraday-multipart (~> 1.0)
24
+ faraday-net_http (~> 1.0)
25
+ faraday-net_http_persistent (~> 1.0)
26
+ faraday-patron (~> 1.0)
27
+ faraday-rack (~> 1.0)
28
+ faraday-retry (~> 1.0)
29
+ ruby2_keywords (>= 0.0.4)
30
+ faraday-em_http (1.0.0)
31
+ faraday-em_synchrony (1.0.0)
32
+ faraday-excon (1.1.0)
33
+ faraday-httpclient (1.0.1)
34
+ faraday-multipart (1.0.4)
35
+ multipart-post (~> 2)
36
+ faraday-net_http (1.0.1)
37
+ faraday-net_http_persistent (1.2.0)
38
+ faraday-patron (1.0.0)
39
+ faraday-rack (1.0.0)
40
+ faraday-retry (1.0.3)
41
+ faraday_middleware (1.2.0)
42
+ faraday (~> 1.0)
43
+ hashdiff (1.0.1)
11
44
  json (2.6.2)
45
+ method_source (1.0.0)
46
+ multipart-post (2.2.3)
12
47
  parallel (1.22.1)
13
48
  parser (3.1.2.1)
14
49
  ast (~> 2.4.1)
50
+ pry (0.14.1)
51
+ coderay (~> 1.1)
52
+ method_source (~> 1.0)
53
+ public_suffix (5.0.0)
15
54
  rainbow (3.1.1)
16
55
  rake (13.0.6)
17
56
  regexp_parser (2.6.0)
@@ -42,16 +81,27 @@ GEM
42
81
  rubocop-ast (1.22.0)
43
82
  parser (>= 3.1.1.0)
44
83
  ruby-progressbar (1.11.0)
84
+ ruby2_keywords (0.0.5)
45
85
  unicode-display_width (2.3.0)
86
+ vcr (6.1.0)
87
+ webmock (3.18.1)
88
+ addressable (>= 2.8.0)
89
+ crack (>= 0.3.2)
90
+ hashdiff (>= 0.4.0, < 2.0.0)
46
91
 
47
92
  PLATFORMS
93
+ ruby
48
94
  x86_64-darwin-21
95
+ x86_64-linux
49
96
 
50
97
  DEPENDENCIES
98
+ pry
51
99
  rake (~> 13.0)
52
100
  rspec (~> 3.0)
53
- rubocop (~> 1.21)
101
+ rubocop
54
102
  ruby-office365!
103
+ vcr
104
+ webmock
55
105
 
56
106
  BUNDLED WITH
57
- 2.3.22
107
+ 2.3.9
data/LICENSE.md ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2022 Encore Shao
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -14,15 +14,127 @@ If bundler is not being used to manage dependencies, install the gem by executin
14
14
 
15
15
  $ gem install ruby-office365
16
16
 
17
- ## Usage
17
+ ## Configuration
18
18
 
19
- TODO: Write usage instructions here
19
+ You can pass configuration options as a block to `Office365::REST::Client.new`.
20
20
 
21
- ## Development
21
+ ```ruby
22
+ client = Office365::REST::Client.new do |config|
23
+ config.tenant_id = "YOUR_ORG_TENANT_ID"
24
+ config.client_id = "YOUR_APP_CLIENT_ID"
25
+ config.client_secret = "YOUR_APP_CLIENT_SECRET"
26
+ config.redirect_uri = "YOUR_APP_REDIRECT_URL"
27
+ config.access_token = "YOUR_ACCESS_TOKEN"
28
+ config.refresh_token = "YOUR_REFRESH_TOKEN"
29
+ end
30
+ ```
22
31
 
23
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
32
+ ## Usage Examples
24
33
 
25
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
34
+ After configuring a `client`, you can do the following things.
35
+
36
+ **response**
37
+
38
+ - `results`: wrap all data into results
39
+ - `next_link`: get the new link for the next page of data
40
+
41
+ **to JSON**
42
+
43
+ - `as_json`: convert office365 object to JSON format
44
+
45
+ **Get Profile (as the authenticated user)**
46
+
47
+ ```ruby
48
+ irb(main):004:0> response = client.me
49
+ irb(main):010:0> response.display_name
50
+ => "Hello World"
51
+ irb(main):004:0> response.as_json
52
+ => {
53
+ :odata_context=>"https://graph.microsoft.com/v1.0/$metadata#users/$entity",
54
+ :display_name=>"Hello World",
55
+ :surname=>"Hello",
56
+ :given_name=>"World",
57
+ :id=>"d7e954e0b50095ad",
58
+ :user_principal_name=>"hello.world@mail.com",
59
+ :business_phones=>[],
60
+ :job_title=>nil,
61
+ :mail=>nil,
62
+ :mobile_phone=>nil,
63
+ :office_location=>nil,
64
+ :preferred_language=>nil
65
+ }
66
+ ```
67
+
68
+ **Get my calendars**
69
+
70
+ ```ruby
71
+ irb(main):005:0> client.calendars
72
+ irb(main):005:0> client.calendars[:results]
73
+ irb(main):005:0> client.calendars[:next_link]
74
+ ```
75
+
76
+ **Get my mails**
77
+
78
+ ```ruby
79
+ irb(main):005:0> client.messages
80
+ irb(main):005:0> client.messages[:results]
81
+ irb(main):005:0> client.messages({ filter: "createdDateTime lt 2022-01-01" })
82
+ irb(main):005:0> client.messages({ filter: "createdDateTime lt 2022-01-01", next_link: 'https://....' })
83
+ ```
84
+
85
+ **Get my contacts**
86
+
87
+ ```ruby
88
+ irb(main):018:0> response = client.contacts
89
+ irb(main):020:0> client.contacts[:results][0].display_name
90
+ => "Encore S."
91
+ irb(main):018:0> response[:results][0].as_json
92
+ => {
93
+ :odata_etag=>"W/\"EQAAABYAAACbUc86NQthQ7+Mvj19ecwVAABjabQj\"",
94
+ :id=>"AQMkADAwATM3ZmYAZS00ZTU5LWY3NwBjLTAwAi0wMAoARgAAA4QFHqPHk4JJj7ZVaRPCKk4HAJtRzzo1C2FDv4y_PX15zBUAAAIBDgAAAJtRzzo1C2FDv4y_PX15zBUAAABja1I_AAAA",
95
+ :created_date_time=>"2022-10-24T02:48:56Z",
96
+ :last_modified_date_time=>"2022-10-24T02:48:57Z",
97
+ :change_key=>"EQAAABYAAACbUc86NQthQ7+Mvj19ecwVAABjabQj",
98
+ :categories=>[],
99
+ :parent_folder_id=>"AQMkADAwATM3ZmYAZS00ZTU5LWY3NwBjLTAwAi0wMAoALgAAA4QFHqPHk4JJj7ZVaRPCKk4BAJtRzzo1C2FDv4y_PX15zBUAAAIBDgAAAA==",
100
+ :birthday=>nil,
101
+ :file_as=>"",
102
+ :display_name=>"Name S.",
103
+ :given_name=>"Name",
104
+ :initials=>nil,
105
+ :middle_name=>nil,
106
+ :nick_name=>nil,
107
+ :surname=>"S.",
108
+ :title=>nil,
109
+ :yomi_given_name=>nil,
110
+ :yomi_surname=>nil,
111
+ :yomi_company_name=>"",
112
+ :generation=>nil,
113
+ :im_addresses=>[],
114
+ :job_title=>"",
115
+ :company_name=>nil,
116
+ :department=>"",
117
+ :office_location=>"",
118
+ :profession=>nil,
119
+ :business_home_page=>"",
120
+ :assistant_name=>"",
121
+ :manager=>"",
122
+ :home_phones=>[],
123
+ :mobile_phone=>"",
124
+ :business_phones=>[],
125
+ :spouse_name=>"",
126
+ :personal_notes=>"",
127
+ :children=>[],
128
+ :email_addresses=>[{"name"=>"name@google.com", "address"=>"name@google.com"}],
129
+ :home_address=>{},
130
+ :business_address=>{},
131
+ :other_address=>{}
132
+ }
133
+ ```
134
+
135
+ ## Copyright
136
+
137
+ Copyright (c) 2022 Encore Shao. See LICENSE for details.
26
138
 
27
139
  ## Contributing
28
140
 
@@ -2,6 +2,43 @@
2
2
 
3
3
  module Office365
4
4
  class Client
5
- autoload :Mailbox, "office365/requests/mailbox"
5
+ attr_accessor :client_id, :client_secret, :access_token, :refresh_token, :redirect_uri, :tenant_id, :debug
6
+
7
+ # Initializes a new Client object
8
+ #
9
+ # @param options [Hash]
10
+ # @return [Office365::Client]
11
+ def initialize(options = {})
12
+ options.each do |key, value|
13
+ instance_variable_set("@#{key}", value)
14
+ end
15
+ yield(self) if block_given?
16
+ end
17
+
18
+ # @return [Boolean]
19
+ def user_token?
20
+ !(blank_string?(access_token) || blank_string?(refresh_token))
21
+ end
22
+
23
+ # @return [Hash]
24
+ def credentials
25
+ {
26
+ client_id: client_id,
27
+ client_secret: client_secret,
28
+ access_token: access_token,
29
+ refresh_token: refresh_token
30
+ }
31
+ end
32
+
33
+ # @return [Boolean]
34
+ def credentials?
35
+ credentials.values.none? { |v| blank_string?(v) }
36
+ end
37
+
38
+ private
39
+
40
+ def blank_string?(string)
41
+ string.respond_to?(:empty?) ? string.empty? : !string
42
+ end
6
43
  end
7
44
  end
@@ -2,7 +2,10 @@
2
2
 
3
3
  module Office365
4
4
  module Models
5
- class Calendar
5
+ class Calendar < Base
6
+ # attr_accessor :id, :name, :color, :hex_color, :is_default_calendar, :change_key, :can_share, :can_view_private_items,
7
+ # :can_edit, :allowed_online_meeting_providers, :default_online_meeting_provider, :is_tallying_responses,
8
+ # :is_removable, :owner
6
9
  end
7
10
  end
8
11
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ostruct"
4
+
5
+ module Office365
6
+ module Models
7
+ class Base < OpenStruct
8
+ def initialize(response = {})
9
+ super(response.transform_keys(&:o_underscore))
10
+ end
11
+
12
+ def as_json
13
+ to_h
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Office365
4
- module Requests
5
- class Mailbox
4
+ module Models
5
+ class Contact < Base
6
6
  end
7
7
  end
8
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Office365
4
4
  module Models
5
- class Directory
5
+ class Directory < Base
6
6
  end
7
7
  end
8
8
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Office365
4
+ module Models
5
+ class EmailAddress < Base
6
+ # attr_accessor :name, :address
7
+ end
8
+ end
9
+ end
@@ -2,7 +2,13 @@
2
2
 
3
3
  module Office365
4
4
  module Models
5
- class Mailbox
5
+ class Mailbox < Base
6
+ # attr_accessor :id, :createdDateTime, :lastModifiedDateTime, :categories, :changeKey,
7
+ # :receivedDateTime, :sentDateTime, :hasAttachments, :internetMessageId,
8
+ # :subject, :importance, :parentFolderId, :conversationId, :conversationIndex,
9
+ # :isDeliveryReceiptRequested, :isReadReceiptRequested, :isRead, :isDraft,
10
+ # :webLink, :inferenceClassification, :sender, :from, :toRecipients, :ccRecipients,
11
+ # :bccRecipients, :replyTo, :flag
6
12
  end
7
13
  end
8
14
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Office365
4
+ module Models
5
+ class Owner < Base
6
+ # attr_accessor :name, :address
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Office365
4
+ module Models
5
+ class User < Base
6
+ # attr_accessor :display_name, :surname, :given_name, :id, :user_principal_name, :business_phones, :job_title, :mail,
7
+ # :mobile_phone, :office_location, :preferred_language
8
+ end
9
+ end
10
+ end
@@ -2,8 +2,13 @@
2
2
 
3
3
  module Office365
4
4
  module Models
5
- autoload :Directory, "office365/models/directory"
6
- autoload :Mailbox, "office365/models/mailbox"
7
- autoload :Calendar, "office365/models/calendar"
5
+ autoload :Base, "office365/models/concerns/base"
6
+ autoload :Directory, "office365/models/directory"
7
+ autoload :Mailbox, "office365/models/mailbox"
8
+ autoload :Calendar, "office365/models/calendar"
9
+ autoload :User, "office365/models/user"
10
+ autoload :Owner, "office365/models/owner"
11
+ autoload :EmailAddress, "office365/models/email_address"
12
+ autoload :Contact, "office365/models/contact"
8
13
  end
9
14
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./user"
4
+ require_relative "./mailbox"
5
+ require_relative "./calendar"
6
+ require_relative "./contact"
7
+ require_relative "./token"
8
+
9
+ module Office365
10
+ module REST
11
+ module API
12
+ include Office365::REST::User
13
+ include Office365::REST::Mailbox
14
+ include Office365::REST::Calendar
15
+ include Office365::REST::Contact
16
+ include Office365::REST::Token
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./concerns/base"
4
+
5
+ module Office365
6
+ module REST
7
+ module Calendar
8
+ include Concerns::Base
9
+
10
+ # params: args => { next_link: (nil / next_page_url) }
11
+ # response { results: [], next_link: '...' }
12
+ def calendars(args = {})
13
+ response = message_response(args: args.merge(base_uri: "/me/calendars"))
14
+
15
+ {
16
+ results: response["value"].map { |v| Models::Calendar.new(v) },
17
+ next_link: response["@odata.nextLink"]
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "faraday_middleware"
5
+ require "logger"
6
+ require "json"
7
+
8
+ require_relative "./api"
9
+
10
+ module Office365
11
+ module REST
12
+ class Client < Office365::Client
13
+ include Office365::REST::API
14
+ attr_accessor :bearer_token
15
+
16
+ # @return [Boolean]
17
+ def bearer_token?
18
+ !!bearer_token
19
+ end
20
+
21
+ # @return [Boolean]
22
+ def credentials?
23
+ super || bearer_token?
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Office365
4
+ module REST
5
+ module Concerns
6
+ module Base
7
+ private
8
+
9
+ def message_response(args: {})
10
+ next_link = args.delete(:next_link)
11
+
12
+ request_uri = if next_link
13
+ next_link
14
+ else
15
+ base_uri = args.delete(:base_uri)
16
+
17
+ req_uri = ["/", Office365::API_VERSION, base_uri].join
18
+ req_uri += ["?", args.to_query].join if args.any?
19
+ req_uri
20
+ end
21
+
22
+ Request.new(access_token, debug: debug).get(request_uri)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./concerns/base"
4
+
5
+ module Office365
6
+ module REST
7
+ module Contact
8
+ include Concerns::Base
9
+
10
+ # params: args => { next_link: (nil / next_page_url) }
11
+ # response { results: [], next_link: '...' }
12
+ def contacts(args = {})
13
+ response = message_response(args: args.merge(base_uri: "/me/contacts"))
14
+
15
+ {
16
+ results: response["value"].map { |v| Models::Contact.new(v) },
17
+ next_link: response["@odata.nextLink"]
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./concerns/base"
4
+
5
+ module Office365
6
+ module REST
7
+ module Mailbox
8
+ include Concerns::Base
9
+
10
+ # params: args => { next_link: (nil / next_page_url) }
11
+ # response { results: [], next_link: '...' }
12
+ def messages(args = {})
13
+ response = message_response(args: args.merge(base_uri: "/me/messages"))
14
+
15
+ {
16
+ results: response["value"].map { |v| Models::Mailbox.new(v) },
17
+ next_link: response["@odata.nextLink"]
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "faraday_middleware"
5
+ require "logger"
6
+ require "json"
7
+
8
+ module Office365
9
+ module REST
10
+ class Request
11
+ attr_accessor :access_token, :debug
12
+
13
+ def initialize(access_token, debug: false)
14
+ @access_token = access_token
15
+ @debug = debug
16
+ end
17
+
18
+ def get(uri, args: {})
19
+ r_uri = URI(uri.start_with?("https") ? uri : (Office365::API_HOST + uri))
20
+
21
+ response = Faraday.new(url: [r_uri.scheme, "://", r_uri.hostname].join, headers: headers) do |faraday|
22
+ faraday.adapter Faraday.default_adapter
23
+ faraday.response :json
24
+ faraday.response :logger, ::Logger.new($stdout), bodies: true if dev_developement?
25
+ end.get(r_uri.request_uri, *args)
26
+
27
+ resp_body = response.body
28
+ return resp_body if response.status == 200
29
+ raise InvalidAuthenticationTokenError, resp_body.dig("error", "message") if response.status == 401
30
+
31
+ raise Error, resp_body["error"]
32
+ end
33
+
34
+ def post(uri, args)
35
+ response = Faraday.new(url: Office365::API_HOST, headers: headers) do |faraday|
36
+ faraday.adapter Faraday.default_adapter
37
+ faraday.response :json
38
+ faraday.response :logger, ::Logger.new($stdout), bodies: true if dev_developement?
39
+ end.post(uri, args)
40
+
41
+ resp_body = response.body
42
+ return resp_body if response.status == 200
43
+ raise InvalidAuthenticationTokenError, resp_body.dig("error", "message") if response.status == 401
44
+
45
+ raise Error, resp_body["error"]
46
+ end
47
+
48
+ private
49
+
50
+ def headers
51
+ {
52
+ "Content-Type" => "application/json",
53
+ "Authorization" => "Bearer #{access_token}"
54
+ }
55
+ end
56
+
57
+ def dev_developement?
58
+ debug
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Office365
4
+ module REST
5
+ module Token
6
+ def token_refresh
7
+ args = {
8
+ refresh_token: refresh_token,
9
+ client_id: client_id,
10
+ client_secret: client_secret,
11
+ grant_type: "refresh_token"
12
+ }
13
+
14
+ post(oauth_client.token_url, args)
15
+ end
16
+
17
+ private
18
+
19
+ def oauth_client
20
+ @oauth_client ||= OAuth2::Client.new(
21
+ client_id,
22
+ client_secret,
23
+ authorize_url: AUTHORIZE_URL,
24
+ site: LOGIN_HOST,
25
+ token_url: TOKEN_URL,
26
+ redirect_uri: redirect_uri
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "request"
4
+
5
+ module Office365
6
+ module REST
7
+ module User
8
+ def me
9
+ profile_uri = ["/", Office365::API_VERSION, "/me"].join
10
+ Models::User.new(Request.new(access_token, debug: debug).get(profile_uri))
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Office365
4
+ module REST
5
+ autoload :Client, "office365/rest/client"
6
+ autoload :Request, "office365/rest/request"
7
+ end
8
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class String
4
+ def o_underscore
5
+ gsub(/::/, "/")
6
+ .gsub(/@/, "")
7
+ .gsub(/\./, "_")
8
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
9
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
10
+ .tr("-", "_")
11
+ .downcase
12
+ end
13
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cgi"
4
+
5
+ class Object
6
+ # Alias of <tt>to_s</tt>.
7
+ def to_param
8
+ to_s
9
+ end
10
+
11
+ # Converts an object into a string suitable for use as a URL query string,
12
+ # using the given <tt>key</tt> as the param name.
13
+ def to_query(key)
14
+ "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
15
+ end
16
+ end
17
+
18
+ class NilClass
19
+ # Returns +self+.
20
+ def to_param
21
+ self
22
+ end
23
+ end
24
+
25
+ class TrueClass
26
+ # Returns +self+.
27
+ def to_param
28
+ self
29
+ end
30
+ end
31
+
32
+ class FalseClass
33
+ # Returns +self+.
34
+ def to_param
35
+ self
36
+ end
37
+ end
38
+
39
+ class Array
40
+ # Calls <tt>to_param</tt> on all its elements and joins the result with
41
+ # slashes. This is used by <tt>url_for</tt> in Action Pack.
42
+ def to_param
43
+ collect(&:to_param).join "/"
44
+ end
45
+
46
+ # Converts an array into a string suitable for use as a URL query string,
47
+ # using the given +key+ as the param name.
48
+ #
49
+ # ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
50
+ def to_query(key)
51
+ prefix = "#{key}[]"
52
+
53
+ if empty?
54
+ nil.to_query(prefix)
55
+ else
56
+ collect { |value| value.to_query(prefix) }.join "&"
57
+ end
58
+ end
59
+ end
60
+
61
+ class Hash
62
+ # Returns a string representation of the receiver suitable for use as a URL
63
+ # query string:
64
+ #
65
+ # {name: 'David', nationality: 'Danish'}.to_query
66
+ # # => "name=David&nationality=Danish"
67
+ #
68
+ # An optional namespace can be passed to enclose key names:
69
+ #
70
+ # {name: 'David', nationality: 'Danish'}.to_query('user')
71
+ # # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
72
+ #
73
+ # The string pairs "key=value" that conform the query string
74
+ # are sorted lexicographically in ascending order.
75
+ #
76
+ # This method is also aliased as +to_param+.
77
+ def to_query(namespace = nil)
78
+ query = collect do |key, value|
79
+ unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
80
+ value.to_query(namespace ? "#{namespace}[#{key}]" : key)
81
+ end
82
+ end.compact
83
+
84
+ query.sort! unless namespace.to_s.include?("[]")
85
+ query.join("&")
86
+ end
87
+
88
+ alias to_param to_query
89
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "office365/utils/string"
4
+ require "office365/utils/to_query"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Office365
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.3"
5
5
  end
data/lib/office365.rb CHANGED
@@ -2,15 +2,21 @@
2
2
 
3
3
  require_relative "office365/version"
4
4
 
5
- require "office365/config"
5
+ require "office365/utils"
6
6
  require "office365/client"
7
+ require "office365/rest"
7
8
  require "office365/models"
8
9
 
9
10
  module Office365
10
- API_DOMAIN = "https://graph.microsoft.com"
11
+ API_HOST = "https://graph.microsoft.com"
12
+ LOGIN_HOST = "https://login.microsoftonline.com/"
13
+
14
+ AUTHORIZE_URL = "common/oauth2/authorize"
15
+ TOKEN_URL = "common/oauth2/token"
11
16
  API_VERSION = "v1.0"
12
- BASE_URI = "#{API_DOMAIN}/#{API_VERSION}/"
17
+ SCOPE = "User.read Calendars.read Mail.ReadBasic Contacts.Read"
13
18
 
14
19
  class Error < StandardError; end
20
+ class InvalidAuthenticationTokenError < StandardError; end
15
21
  # Your code goes here...
16
22
  end
@@ -12,6 +12,8 @@ Gem::Specification.new do |spec|
12
12
  spec.description = "A simple ruby library to interact with Microsoft Graph and Office 365 API."
13
13
  spec.homepage = "https://github.com/ekohe/ruby-office365"
14
14
  spec.required_ruby_version = ">= 2.5.0"
15
+ spec.license = "MIT"
16
+ spec.post_install_message = "Thanks for installing!"
15
17
 
16
18
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
17
19
 
@@ -32,7 +34,16 @@ Gem::Specification.new do |spec|
32
34
 
33
35
  # Uncomment to register a new dependency of your gem
34
36
  # spec.add_dependency "example-gem", "~> 1.0"
35
-
37
+ spec.add_dependency "faraday"
38
+ spec.add_dependency "faraday_middleware"
39
+
40
+ # VCR for testing APIs
41
+ spec.add_development_dependency "vcr"
42
+ spec.add_development_dependency "webmock"
43
+ # Rubocop
44
+ spec.add_development_dependency "rubocop"
45
+ # For debug binding.pry
46
+ spec.add_development_dependency "pry"
36
47
  # For more information and examples about making a new gem, check out our
37
48
  # guide at: https://bundler.io/guides/creating_gem.html
38
49
  end
metadata CHANGED
@@ -1,15 +1,99 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-office365
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Encore Shao
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-19 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2022-10-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday_middleware
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: vcr
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
13
97
  description: A simple ruby library to interact with Microsoft Graph and Office 365
14
98
  API.
15
99
  email:
@@ -23,27 +107,45 @@ files:
23
107
  - CHANGELOG.md
24
108
  - Gemfile
25
109
  - Gemfile.lock
110
+ - LICENSE.md
26
111
  - README.md
27
112
  - Rakefile
28
113
  - lib/office365.rb
29
114
  - lib/office365/client.rb
30
- - lib/office365/config.rb
31
115
  - lib/office365/models.rb
32
116
  - lib/office365/models/calendar.rb
117
+ - lib/office365/models/concerns/base.rb
118
+ - lib/office365/models/contact.rb
33
119
  - lib/office365/models/directory.rb
120
+ - lib/office365/models/email_address.rb
34
121
  - lib/office365/models/mailbox.rb
35
- - lib/office365/requests/mailbox.rb
122
+ - lib/office365/models/owner.rb
123
+ - lib/office365/models/user.rb
124
+ - lib/office365/rest.rb
125
+ - lib/office365/rest/api.rb
126
+ - lib/office365/rest/calendar.rb
127
+ - lib/office365/rest/client.rb
128
+ - lib/office365/rest/concerns/base.rb
129
+ - lib/office365/rest/contact.rb
130
+ - lib/office365/rest/mailbox.rb
131
+ - lib/office365/rest/request.rb
132
+ - lib/office365/rest/token.rb
133
+ - lib/office365/rest/user.rb
134
+ - lib/office365/utils.rb
135
+ - lib/office365/utils/string.rb
136
+ - lib/office365/utils/to_query.rb
36
137
  - lib/office365/version.rb
37
138
  - ruby-office365.gemspec
38
139
  - sig/office365.rbs
39
140
  homepage: https://github.com/ekohe/ruby-office365
40
- licenses: []
141
+ licenses:
142
+ - MIT
41
143
  metadata:
42
144
  allowed_push_host: https://rubygems.org
43
145
  homepage_uri: https://github.com/ekohe/ruby-office365
44
146
  source_code_uri: https://github.com/ekohe/ruby-office365
45
147
  changelog_uri: https://github.com/ekohe/ruby-office365/blob/main/CHANGELOG.md
46
- post_install_message:
148
+ post_install_message: Thanks for installing!
47
149
  rdoc_options: []
48
150
  require_paths:
49
151
  - lib
@@ -58,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
160
  - !ruby/object:Gem::Version
59
161
  version: '0'
60
162
  requirements: []
61
- rubygems_version: 3.2.15
163
+ rubygems_version: 3.1.6
62
164
  signing_key:
63
165
  specification_version: 4
64
166
  summary: A simple ruby library to interact with Microsoft Graph and Office 365 API.
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "singleton"
4
-
5
- # Should be config the client and secret first
6
- module Office365
7
- class Config
8
- include Singleton
9
-
10
- attr_accessor :client, :secret
11
- end
12
-
13
- def self.config
14
- yield Config.instance if block_given?
15
-
16
- Config.instance
17
- end
18
- end