ruby-office365 0.1.0 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3d07710145d0950ccf59cbb228b1ad453d4f157e7dfb941f912c76338e859548
4
- data.tar.gz: 7d62a6296186c5bb8813402890d911ff31e9c9f998e797932f1726a38b76751f
3
+ metadata.gz: '09f37ce4e6f4c9db6d9e1f12d1b53508fc7dcd9b5efa204582a7164764905796'
4
+ data.tar.gz: f5cdfb070ba62cfbd96e81f801e3e2dc8f5584115338ad85c92d9dae86710e6b
5
5
  SHA512:
6
- metadata.gz: 3fbea9fe5c09e3ea418f40dbb8fdb90126e0768cd47afd37a698aae0461fbf5d01efe885cd3cc96e55d220ef2067034b4e9cb1d1a1b54db041bd3aff794e20bf
7
- data.tar.gz: ff15f4d0b53888a343b2c39f3bfe060816b7317155b2908bb7d52f341bc0235a7c1ebfcea1cf93a1d6d1a0d4e824b1b1a975bfeae8e36f7bf8092e0c30927823
6
+ metadata.gz: 8bb8b810b6aa38e89b2e906e3e7dffcfc63291edd0687dade41f41e7e9a7d3e1ff0f546f5e63ec5339fbe439ed75a06cbc48b11bfc38d8eb7dd45ee4535d6ebb
7
+ data.tar.gz: 505e05289637208d656904933e93e8123f3fc0355988cc23edbab27830627f24bb894a441ad389405bccbd733cd91641138310c28eb80a54a26695e9ad1511f0
data/.rubocop.yml CHANGED
@@ -10,4 +10,16 @@ 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
23
+
24
+ Metrics/MethodLength:
25
+ Max: 50
data/CHANGELOG.md CHANGED
@@ -2,4 +2,30 @@
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'})`
25
+
26
+ ## [0.1.4] - (2022-10-26)
27
+
28
+ - Generate URLs for token and able to refresh token
29
+ - get authorize URL `client.authorize_url`
30
+ - get token URL `client.token_url`
31
+ - be able to refresh token `client.refresh_token!`
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.4)
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,133 @@ 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
+ **Refresh User Token**
136
+
137
+ ```ruby
138
+ irb(main):005:0> client.refresh_token!
139
+ ```
140
+
141
+ ## Copyright
142
+
143
+ Copyright (c) 2022 Encore Shao. See LICENSE for details.
26
144
 
27
145
  ## Contributing
28
146
 
@@ -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,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Office365
4
+ module REST
5
+ module Token
6
+ def authorize_url
7
+ base_uri = [LOGIN_HOST, "/#{tenant_id}/oauth2/v2.0/authorize"].join
8
+ azure_params = {
9
+ client_id: client_id,
10
+ client_secret: client_secret,
11
+ scope: Office365::SCOPE,
12
+ response_type: "code",
13
+ response_mode: "query",
14
+ redirect_uri: redirect_uri,
15
+ state: SecureRandom.hex
16
+ }.to_query
17
+
18
+ [base_uri, "?", azure_params].join
19
+ end
20
+
21
+ def token_url
22
+ [LOGIN_HOST, "/#{tenant_id}/oauth2/v2.0/token"].join
23
+ end
24
+
25
+ def refresh_token!
26
+ post(token_url, {
27
+ refresh_token: refresh_token,
28
+ client_id: client_id,
29
+ client_secret: client_secret,
30
+ grant_type: "refresh_token",
31
+ scope: Office365::SCOPE
32
+ })
33
+ end
34
+ end
35
+ end
36
+ 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.4"
5
5
  end
data/lib/office365.rb CHANGED
@@ -2,15 +2,19 @@
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"
11
12
  API_VERSION = "v1.0"
12
- BASE_URI = "#{API_DOMAIN}/#{API_VERSION}/"
13
+
14
+ LOGIN_HOST = "https://login.microsoftonline.com"
15
+ SCOPE = "User.read Calendars.read Mail.ReadBasic Contacts.Read"
13
16
 
14
17
  class Error < StandardError; end
18
+ class InvalidAuthenticationTokenError < StandardError; end
15
19
  # Your code goes here...
16
20
  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.4
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