camp3 0.0.3 → 0.0.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: c51061a5954cc07915e99c8e709dde954de59d976664b0fafc0f4e8029d28505
4
- data.tar.gz: 98cfe680d84287497ac4c0d8ab6bcdcde00fb9f41ab0b444e90a368cc2a472f4
3
+ metadata.gz: 66a193782f5b6d1b473d062b935cbbc6574326e73644551fbf7e12be3a2e3265
4
+ data.tar.gz: 9392604c669d445da80dc67b1d353f32120e6b42128c71e20ade043db8875810
5
5
  SHA512:
6
- metadata.gz: 4697b931b0e50fdd54e7345de1ebf552f4a5daad1dfb1472773890c5ac107a2a9c512d2dfdf0a852c40650212ea3d3fcff508f23be27c73686fbe2b83539b55f
7
- data.tar.gz: 736fe2af5f5eb1599920d9466f52ab60ab637e6356886115b1ff9b9b07822c6030359070e04f9bbc39f5a9eccae96c624be5e984f180f459883cd2178290dd43
6
+ metadata.gz: d62200e6002a4e01104c0f90d2b22c2f2f65fa3c8f4ef6dad676993e5313fb881ae8ae73aec58f2e3aec15838ce7ee274259049e41d50062eb166724cebaa14e
7
+ data.tar.gz: '08fac07805af79ea7e4f583c1c5c0a1245a25285e60364f530508a7c1392572cc97169d84291698a697370e102cc118b93e46d6a7d5a090a12833b8e8ded4313'
@@ -4,6 +4,14 @@
4
4
 
5
5
  **Implemented enhancements:**
6
6
 
7
+ - Add Comments API module [\#11](https://github.com/renehernandez/camp3/issues/11)
8
+ - Add Comment API Module [\#19](https://github.com/renehernandez/camp3/pull/19)
9
+ - Refactor usage around the client object [\#18](https://github.com/renehernandez/camp3/pull/18)
10
+
11
+ ## [v0.0.3](https://github.com/renehernandez/camp3/tree/v0.0.3) (2020-07-26)
12
+
13
+ **Implemented enhancements:**
14
+
7
15
  - Request a new access token once it expires [\#13](https://github.com/renehernandez/camp3/issues/13)
8
16
  - Retry for new access token [\#16](https://github.com/renehernandez/camp3/pull/16)
9
17
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- camp3 (0.0.2)
4
+ camp3 (0.0.3)
5
5
  httparty (~> 0.18)
6
6
  rack-oauth2 (~> 1.14)
7
7
 
data/README.md CHANGED
@@ -24,28 +24,46 @@ $ gem install camp3
24
24
 
25
25
  ## Usage
26
26
 
27
- Configuration example:
27
+ Getting a client and configuring it:
28
28
 
29
29
  ```ruby
30
30
  require 'camp3'
31
31
 
32
- Camp3.configure do |config|
32
+ client = Camp3.client
33
+
34
+ client.configure do |config|
33
35
  config.client_id = ENV['BASECAMP3_CLIENT_ID']
34
36
  config.client_secret = ENV['BASECAMP3_CLIENT_SECRET']
35
37
  config.account_number = ENV['BASECAMP3_ACCOUNT_NUMBER']
36
38
  config.refresh_token = ENV['BASECAMP3_REFRESH_TOKEN']
37
39
  config.access_token = ENV['BASECAMP3_ACCESS_TOKEN']
38
40
  end
41
+
42
+ projects = client.projects
39
43
  ```
40
44
 
41
- For more complex examples, we recommend using a client, instead of the top level `Camp3` wrapper. A `client` has a builtin mechanism to retry requests when the access token has expired and update its information (so it will use the new access token instead of the old one), as oppose to the top level `Camp3` which would request a new access token every time a request were to be made.
45
+ Alternatively, it is possible to invoke the top-level `#configure` method to get a client:
46
+
47
+ ```ruby
48
+ require 'camp3'
49
+
50
+ client = Camp3.configure do |config|
51
+ config.client_id = ENV['BASECAMP3_CLIENT_ID']
52
+ config.client_secret = ENV['BASECAMP3_CLIENT_SECRET']
53
+ config.account_number = ENV['BASECAMP3_ACCOUNT_NUMBER']
54
+ config.refresh_token = ENV['BASECAMP3_REFRESH_TOKEN']
55
+ config.access_token = ENV['BASECAMP3_ACCESS_TOKEN']
56
+ end
57
+
58
+ projects = client.projects
59
+ ```
42
60
 
43
61
  Example getting list of TODOs:
44
62
 
45
63
  ```ruby
46
64
  require 'camp3'
47
65
 
48
- Camp3.configure do |config|
66
+ client = Camp3.configure do |config|
49
67
  config.client_id = ENV['BASECAMP3_CLIENT_ID']
50
68
  config.client_secret = ENV['BASECAMP3_CLIENT_SECRET']
51
69
  config.account_number = ENV['BASECAMP3_ACCOUNT_NUMBER']
@@ -53,8 +71,6 @@ Camp3.configure do |config|
53
71
  config.access_token = ENV['BASECAMP3_ACCESS_TOKEN']
54
72
  end
55
73
 
56
- client = Camp3.client
57
-
58
74
  projects = client.projects
59
75
 
60
76
  projects.each do |p|
@@ -74,7 +90,7 @@ projects.each do |p|
74
90
  end
75
91
  ```
76
92
 
77
- For more examples, check the [examples](examples/) folder
93
+ For more examples, check out the [examples](examples/) folder
78
94
 
79
95
  ## Contributing
80
96
 
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'camp3'
4
+
5
+ client = Camp3.configure do |config|
6
+ config.client_id = ENV['BASECAMP3_CLIENT_ID']
7
+ config.client_secret = ENV['BASECAMP3_CLIENT_SECRET']
8
+ config.account_number = ENV['BASECAMP3_ACCOUNT_NUMBER']
9
+ config.refresh_token = ENV['BASECAMP3_REFRESH_TOKEN']
10
+ config.access_token = ENV['BASECAMP3_ACCESS_TOKEN']
11
+ end
12
+
13
+ projects = client.projects
14
+
15
+ projects.each do |p|
16
+ puts "Project: #{p.name}"
17
+
18
+ message_board = client.message_board(p)
19
+ todoset = client.todoset(p)
20
+
21
+ # Message board and Todo set are example resources that doesn't have comments
22
+ puts "Message Board: #{message_board.title}, can be commented on: #{message_board.can_be_commented?}"
23
+ puts "Todo set: #{todoset.title}, can be commented on: #{todoset.can_be_commented?}"
24
+
25
+ # Adds a comment on the first todolist
26
+ list = client.todolists(todoset).first
27
+ puts "Todolist: #{list.title}, can be commented on: #{list.can_be_commented?}"
28
+ client.add_comment(list, 'New <b>comment</b> with <i>HTML support</i>')
29
+ comments = client.comments(list)
30
+ comments.each do |c|
31
+ puts "Comment content: #{c.content}"
32
+ end
33
+ end
@@ -1,6 +1,6 @@
1
1
  require 'camp3'
2
2
 
3
- Camp3.configure do |config|
3
+ client = Camp3.configure do |config|
4
4
  config.client_id = ENV['BASECAMP3_CLIENT_ID']
5
5
  config.client_secret = ENV['BASECAMP3_CLIENT_SECRET']
6
6
  config.account_number = ENV['BASECAMP3_ACCOUNT_NUMBER']
@@ -8,8 +8,6 @@ Camp3.configure do |config|
8
8
  config.access_token = ENV['BASECAMP3_ACCESS_TOKEN']
9
9
  end
10
10
 
11
- client = Camp3.client
12
-
13
11
  projects = client.projects
14
12
 
15
13
  projects.each do |p|
@@ -1,13 +1,11 @@
1
1
  require 'camp3'
2
2
 
3
- Camp3.configure do |config|
3
+ client = Camp3.configure do |config|
4
4
  config.client_id = ENV['BASECAMP3_CLIENT_ID']
5
5
  config.client_secret = ENV['BASECAMP3_CLIENT_SECRET']
6
6
  config.redirect_uri = ENV['BASECAMP3_REDIRECT_URI']
7
7
  end
8
8
 
9
- client = Camp3.client
10
-
11
9
  # Get the authorization uri
12
10
  puts client.authorization_uri
13
11
 
@@ -1,13 +1,13 @@
1
1
  require 'camp3'
2
2
 
3
- Camp3.configure do |config|
3
+ client = Camp3.configure do |config|
4
4
  config.client_id = ENV['BASECAMP3_CLIENT_ID']
5
5
  config.client_secret = ENV['BASECAMP3_CLIENT_SECRET']
6
6
  config.account_number = ENV['BASECAMP3_ACCOUNT_NUMBER']
7
7
  config.refresh_token = ENV['BASECAMP3_REFRESH_TOKEN']
8
8
  end
9
9
 
10
- tokens = Camp3.update_access_token!
10
+ tokens = client.update_access_token!
11
11
 
12
12
  # Prints the new access token
13
13
  puts tokens.access_token
@@ -1,6 +1,6 @@
1
1
  require 'camp3'
2
2
 
3
- Camp3.configure do |config|
3
+ client = Camp3.configure do |config|
4
4
  config.client_id = ENV['BASECAMP3_CLIENT_ID']
5
5
  config.client_secret = ENV['BASECAMP3_CLIENT_SECRET']
6
6
  config.account_number = ENV['BASECAMP3_ACCOUNT_NUMBER']
@@ -8,8 +8,6 @@ Camp3.configure do |config|
8
8
  config.access_token = ENV['BASECAMP3_ACCESS_TOKEN']
9
9
  end
10
10
 
11
- client = Camp3.client
12
-
13
11
  projects = client.projects
14
12
 
15
13
  projects.each do |p|
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'forwardable'
3
4
  require 'rack/oauth2'
4
5
 
5
6
  require "camp3/version"
@@ -14,9 +15,6 @@ require "camp3/request"
14
15
  require "camp3/client"
15
16
 
16
17
  module Camp3
17
- extend Logging
18
- extend Configuration
19
-
20
18
  # Alias for Camp3::Client.new
21
19
  #
22
20
  # @return [Camp3::Client]
@@ -24,16 +22,11 @@ module Camp3
24
22
  Camp3::Client.new(options)
25
23
  end
26
24
 
27
- # Delegate to Camp3::Client
28
- def self.method_missing(method, *args, &block)
29
- return super unless client.respond_to?(method)
30
-
31
- client.send(method, *args, &block)
32
- end
33
-
34
- # Delegate to Camp3::Client
35
- def self.respond_to_missing?(method_name, include_private = false)
36
- client.respond_to?(method_name) || super
25
+ # Delegates to Camp3::Client configure method
26
+ #
27
+ # @return [Camp3::Client]
28
+ def self.configure(&block)
29
+ self.client.configure(&block)
37
30
  end
38
31
 
39
32
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Camp3::Client
4
+ module CommentAPI
5
+ def add_comment(resource, content)
6
+ post(resource.comments_url, override_path: true, body: { content: content }.to_json)
7
+ end
8
+
9
+ def comments(resource)
10
+ get(resource.comments_url, override_path: true)
11
+ end
12
+ end
13
+ end
@@ -11,11 +11,11 @@ module Camp3
11
11
 
12
12
  def authz_client
13
13
  Rack::OAuth2::Client.new(
14
- identifier: Camp3.client_id,
15
- secret: Camp3.client_secret,
16
- redirect_uri: Camp3.redirect_uri,
17
- authorization_endpoint: Camp3.authz_endpoint,
18
- token_endpoint: Camp3.token_endpoint,
14
+ identifier: @config.client_id,
15
+ secret: @config.client_secret,
16
+ redirect_uri: @config.redirect_uri,
17
+ authorization_endpoint: @config.authz_endpoint,
18
+ token_endpoint: @config.token_endpoint,
19
19
  )
20
20
  end
21
21
 
@@ -26,10 +26,9 @@ module Camp3
26
26
  # Passing secrets as query string
27
27
  token = client.access_token!(
28
28
  client_auth_method: nil,
29
- client_id: Camp3.client_id,
30
- client_secret: Camp3.client_secret,
29
+ client_id: @config.client_id,
30
+ client_secret: @config.client_secret,
31
31
  type: :web_server
32
- # code: auth_code
33
32
  )
34
33
 
35
34
  store_tokens(token)
@@ -37,17 +36,16 @@ module Camp3
37
36
  token
38
37
  end
39
38
 
40
- def update_access_token!(refresh_token = nil)
41
- Camp3.logger.debug "Update access token using refresh token"
39
+ def update_access_token!
40
+ logger.debug "Update access token using refresh token"
42
41
 
43
- refresh_token = Camp3.refresh_token unless refresh_token
44
42
  client = authz_client
45
- client.refresh_token = refresh_token
43
+ client.refresh_token = @config.refresh_token
46
44
 
47
45
  token = client.access_token!(
48
46
  client_auth_method: nil,
49
- client_id: Camp3.client_id,
50
- client_secret: Camp3.client_secret,
47
+ client_id: @config.client_id,
48
+ client_secret: @config.client_secret,
51
49
  type: :refresh
52
50
  )
53
51
 
@@ -59,8 +57,8 @@ module Camp3
59
57
  private
60
58
 
61
59
  def store_tokens(token)
62
- @access_token = token.access_token
63
- @refresh_token = token.refresh_token
60
+ @config.access_token = token.access_token
61
+ @config.refresh_token = token.refresh_token
64
62
  end
65
63
  end
66
64
  end
@@ -4,25 +4,25 @@ module Camp3
4
4
  # Wrapper for the Camp3 REST API.
5
5
  class Client
6
6
  Dir[File.expand_path('api/*.rb', __dir__)].each { |f| require f }
7
+
8
+ extend Forwardable
7
9
 
10
+ def_delegators :@config, *(Configuration::VALID_OPTIONS_KEYS)
11
+ def_delegators :@config, :authz_endpoint, :token_endpoint, :api_endpoint, :base_api_endpoint
12
+
8
13
  # Keep in alphabetical order
9
14
  include Authorization
15
+ include CommentAPI
16
+ include Logging
10
17
  include MessageAPI
11
18
  include ProjectAPI
12
19
  include ResourceAPI
13
20
  include TodoAPI
14
21
 
15
- # @private
16
- attr_accessor(*Configuration::VALID_OPTIONS_KEYS)
17
-
18
22
  # Creates a new API.
19
23
  # @raise [Error:MissingCredentials]
20
24
  def initialize(options = {})
21
- options = Camp3.options.merge(options)
22
-
23
- (Configuration::VALID_OPTIONS_KEYS).each do |key|
24
- send("#{key}=", options[key]) if options[key]
25
- end
25
+ @config = Configuration.new(options)
26
26
  end
27
27
 
28
28
  %w[get post put delete].each do |method|
@@ -37,12 +37,20 @@ module Camp3
37
37
  end
38
38
  end
39
39
 
40
+ # Allows setting configuration values for this client
41
+ # returns the client instance being configured
42
+ def configure
43
+ yield @config
44
+
45
+ self
46
+ end
47
+
40
48
  # Text representation of the client, masking private token.
41
49
  #
42
50
  # @return [String]
43
51
  def inspect
44
52
  inspected = super
45
- inspected.sub! @access_token, only_show_last_four_chars(@access_token) if @access_token
53
+ inspected.sub! @config.access_token, only_show_last_four_chars(@config.access_token) if @config.access_token
46
54
  inspected
47
55
  end
48
56
 
@@ -57,7 +65,7 @@ module Camp3
57
65
  private
58
66
 
59
67
  def new_request
60
- Request.new(@access_token, @user_agent)
68
+ Request.new(@config.access_token, @config.user_agent, self)
61
69
  end
62
70
 
63
71
  def only_show_last_four_chars(token)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Camp3
4
4
  # Defines constants and methods related to configuration.
5
- module Configuration
5
+ class Configuration
6
6
  include Logging
7
7
 
8
8
  # An array of valid keys in the options hash when configuring a Basecamp::API.
@@ -22,14 +22,11 @@ module Camp3
22
22
  # @private
23
23
  attr_accessor(*VALID_OPTIONS_KEYS)
24
24
 
25
- def configure
26
- yield self
27
- end
28
-
29
- # Sets all configuration options to their default values
30
- # when this module is extended.
31
- def self.extended(base)
32
- base.reset
25
+ def initialize(options = {})
26
+ options[:user_agent] ||= DEFAULT_USER_AGENT
27
+ VALID_OPTIONS_KEYS.each do |key|
28
+ send("#{key}=", options[key]) if options[key]
29
+ end
33
30
  end
34
31
 
35
32
  # Creates a hash of options and their values.
@@ -66,6 +63,10 @@ module Camp3
66
63
  end
67
64
 
68
65
  def base_api_endpoint
66
+ self.class.base_api_endpoint
67
+ end
68
+
69
+ def self.base_api_endpoint
69
70
  "https://3.basecampapi.com"
70
71
  end
71
72
  end
@@ -15,7 +15,6 @@ module Camp3
15
15
  @logger ||= default_logger
16
16
  end
17
17
 
18
-
19
18
  private
20
19
 
21
20
  # Create and configure a logger
@@ -6,8 +6,9 @@ module Camp3
6
6
  # @private
7
7
  class Request
8
8
  include HTTParty
9
+ include Logging
9
10
  format :json
10
- headers 'Accept' => 'application/json'
11
+ headers 'Accept' => 'application/json', 'Content-Type' => 'application/json'
11
12
  parser(proc { |body, _| parse(body) })
12
13
 
13
14
  module Result
@@ -16,8 +17,9 @@ module Camp3
16
17
  Valid = 'Valid'
17
18
  end
18
19
 
19
- def initialize(access_token, user_agent)
20
+ def initialize(access_token, user_agent, client)
20
21
  @access_token = access_token
22
+ @client = client
21
23
 
22
24
  self.class.headers 'User-Agent' => user_agent
23
25
  end
@@ -55,7 +57,7 @@ module Camp3
55
57
 
56
58
  params[:headers] ||= {}
57
59
 
58
- full_endpoint = override_path ? path : Camp3.api_endpoint + path
60
+ full_endpoint = override_path ? path : @client.api_endpoint + path
59
61
 
60
62
  execute_request(method, full_endpoint, params)
61
63
  end
@@ -65,9 +67,10 @@ module Camp3
65
67
 
66
68
  # Executes the request
67
69
  def execute_request(method, endpoint, params)
70
+ params[:headers].merge!(self.class.headers)
68
71
  params[:headers].merge!(authorization_header)
69
72
 
70
- Camp3.logger.debug("Method: #{method}; URL: #{endpoint}")
73
+ logger.debug("Method: #{method}; URL: #{endpoint}")
71
74
  response, result = validate self.class.send(method, endpoint, params)
72
75
 
73
76
  response = extract_parsed(response) if result == Result::Valid
@@ -83,7 +86,7 @@ module Camp3
83
86
  error_klass = Error::STATUS_MAPPINGS[response.code]
84
87
 
85
88
  if error_klass == Error::Unauthorized && response.parsed_response.error.include?("OAuth token expired (old age)")
86
- Camp3.logger.debug("Access token expired. Please obtain a new access token")
89
+ logger.debug("Access token expired. Please obtain a new access token")
87
90
  return response, Result::AccessTokenExpired
88
91
  end
89
92
 
@@ -95,7 +98,7 @@ module Camp3
95
98
  def extract_parsed(response)
96
99
  parsed = response.parsed_response
97
100
 
98
- parsed.client = self if parsed.respond_to?(:client=)
101
+ parsed.client = @client if parsed.respond_to?(:client=)
99
102
  parsed.parse_headers!(response.headers) if parsed.respond_to?(:parse_headers!)
100
103
 
101
104
  parsed
@@ -24,6 +24,14 @@ module Camp3
24
24
  data[key]
25
25
  end
26
26
 
27
+ # Check whether a resource can be commented on or not
28
+ # given the presences of `comments_count` and `comments_url` keys
29
+ #
30
+ # @return [Boolean]
31
+ def can_be_commented?
32
+ hash.key?('comments_url') && hash.key?('comments_count')
33
+ end
34
+
27
35
  private
28
36
 
29
37
  attr_reader :hash, :data
@@ -63,7 +71,7 @@ module Camp3
63
71
 
64
72
  def self.detect_type(url)
65
73
  case url
66
- when /#{Camp3.base_api_endpoint}\/\d+\/projects\/\d+\.json/
74
+ when /#{Configuration.base_api_endpoint}\/\d+\/projects\/\d+\.json/
67
75
  return Project
68
76
  else
69
77
  return Resource
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Camp3
4
- VERSION = "0.0.3"
4
+ VERSION = "0.0.4"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: camp3
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - renehernandez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-26 00:00:00.000000000 Z
11
+ date: 2020-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -92,11 +92,13 @@ files:
92
92
  - bin/console
93
93
  - bin/setup
94
94
  - camp3.gemspec
95
+ - examples/comments.rb
95
96
  - examples/messages.rb
96
97
  - examples/oauth.rb
97
98
  - examples/obtain_acces_token.rb
98
99
  - examples/todos.rb
99
100
  - lib/camp3.rb
101
+ - lib/camp3/api/comment.rb
100
102
  - lib/camp3/api/message.rb
101
103
  - lib/camp3/api/project.rb
102
104
  - lib/camp3/api/resource.rb