camper 0.0.5
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 +7 -0
 - data/.editorconfig +8 -0
 - data/.github/dependabot.yml +6 -0
 - data/.github/workflows/ci.yml +43 -0
 - data/.github/workflows/ci_changelog.yml +29 -0
 - data/.github/workflows/release.yml +91 -0
 - data/.gitignore +60 -0
 - data/.rspec +3 -0
 - data/.rubocop.yml +47 -0
 - data/.rubocop_todo.yml +249 -0
 - data/.ruby-version +1 -0
 - data/CHANGELOG.md +69 -0
 - data/CONTRIBUTING.md +183 -0
 - data/Gemfile +10 -0
 - data/Gemfile.lock +103 -0
 - data/LICENSE +21 -0
 - data/README.md +113 -0
 - data/Rakefile +11 -0
 - data/bin/console +14 -0
 - data/bin/setup +8 -0
 - data/camper.gemspec +34 -0
 - data/examples/comments.rb +35 -0
 - data/examples/messages.rb +24 -0
 - data/examples/oauth.rb +22 -0
 - data/examples/obtain_acces_token.rb +13 -0
 - data/examples/todos.rb +27 -0
 - data/lib/camper.rb +32 -0
 - data/lib/camper/api/comment.rb +13 -0
 - data/lib/camper/api/message.rb +9 -0
 - data/lib/camper/api/project.rb +20 -0
 - data/lib/camper/api/resource.rb +11 -0
 - data/lib/camper/api/todo.rb +14 -0
 - data/lib/camper/authorization.rb +64 -0
 - data/lib/camper/client.rb +86 -0
 - data/lib/camper/configuration.rb +75 -0
 - data/lib/camper/error.rb +146 -0
 - data/lib/camper/logging.rb +28 -0
 - data/lib/camper/paginated_response.rb +67 -0
 - data/lib/camper/pagination_data.rb +47 -0
 - data/lib/camper/request.rb +116 -0
 - data/lib/camper/resource.rb +83 -0
 - data/lib/camper/resources/project.rb +14 -0
 - data/lib/camper/version.rb +5 -0
 - metadata +143 -0
 
    
        data/Rakefile
    ADDED
    
    
    
        data/bin/console
    ADDED
    
    | 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "bundler/setup"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "camper"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            # You can add fixtures and/or initialization code here to make experimenting
         
     | 
| 
      
 7 
     | 
    
         
            +
            # with your gem easier. You can also use a different console, if you like.
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            # (If you use this, don't forget to add pry to your Gemfile!)
         
     | 
| 
      
 10 
     | 
    
         
            +
            # require "pry"
         
     | 
| 
      
 11 
     | 
    
         
            +
            # Pry.start
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            require "irb"
         
     | 
| 
      
 14 
     | 
    
         
            +
            IRB.start(__FILE__)
         
     | 
    
        data/bin/setup
    ADDED
    
    
    
        data/camper.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative 'lib/camper/version'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Gem::Specification.new do |spec|
         
     | 
| 
      
 6 
     | 
    
         
            +
              spec.name          = 'camper'
         
     | 
| 
      
 7 
     | 
    
         
            +
              spec.version       = Camper::VERSION
         
     | 
| 
      
 8 
     | 
    
         
            +
              spec.authors       = ['renehernandez']
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              spec.summary       = 'Ruby client for Basecamp 3 API'
         
     | 
| 
      
 11 
     | 
    
         
            +
              spec.homepage      = 'https://github.com/renehernandez/camper'
         
     | 
| 
      
 12 
     | 
    
         
            +
              spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
         
     | 
| 
      
 13 
     | 
    
         
            +
              spec.license       = 'MIT'
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              spec.metadata['allowed_push_host'] = 'https://rubygems.org'
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              spec.metadata['homepage_uri'] = spec.homepage
         
     | 
| 
      
 18 
     | 
    
         
            +
              spec.metadata['source_code_uri'] = spec.homepage
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              # Specify which files should be added to the gem when it is released.
         
     | 
| 
      
 21 
     | 
    
         
            +
              # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
         
     | 
| 
      
 22 
     | 
    
         
            +
              spec.files         = Dir.chdir(File.expand_path('..', __FILE__)) do
         
     | 
| 
      
 23 
     | 
    
         
            +
                `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
              spec.bindir        = 'exe'
         
     | 
| 
      
 26 
     | 
    
         
            +
              spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
         
     | 
| 
      
 27 
     | 
    
         
            +
              spec.require_paths = ['lib']
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              spec.add_dependency 'httparty', '~> 0.18'
         
     | 
| 
      
 30 
     | 
    
         
            +
              spec.add_dependency 'rack-oauth2', '~> 1.14'
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              spec.add_development_dependency 'rake', '~> 13.0'
         
     | 
| 
      
 33 
     | 
    
         
            +
              spec.add_development_dependency 'rspec', '~> 3.9'
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'camper'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            client = Camper.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.auto_paginate 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 
     | 
    
         
            +
              idx = 0
         
     | 
| 
      
 31 
     | 
    
         
            +
              comments.auto_paginate do |c|
         
     | 
| 
      
 32 
     | 
    
         
            +
                puts "Comment #{idx} content: #{c.content}"
         
     | 
| 
      
 33 
     | 
    
         
            +
                idx += 1
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'camper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            client = Camper.configure do |config|
         
     | 
| 
      
 4 
     | 
    
         
            +
              config.client_id = ENV['BASECAMP3_CLIENT_ID']
         
     | 
| 
      
 5 
     | 
    
         
            +
              config.client_secret = ENV['BASECAMP3_CLIENT_SECRET']
         
     | 
| 
      
 6 
     | 
    
         
            +
              config.account_number = ENV['BASECAMP3_ACCOUNT_NUMBER']
         
     | 
| 
      
 7 
     | 
    
         
            +
              config.refresh_token = ENV['BASECAMP3_REFRESH_TOKEN']
         
     | 
| 
      
 8 
     | 
    
         
            +
              config.access_token = ENV['BASECAMP3_ACCESS_TOKEN']
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            projects = client.projects
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            projects.auto_paginate do |p|
         
     | 
| 
      
 14 
     | 
    
         
            +
              puts "Project: #{p.name}"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              message_board = client.message_board(p)
         
     | 
| 
      
 17 
     | 
    
         
            +
              puts "Message Board: #{message_board.title}"
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              messages = client.messages(message_board)
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              messages.auto_paginate do |msg|
         
     | 
| 
      
 22 
     | 
    
         
            +
                puts msg.inspect
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
    
        data/examples/oauth.rb
    ADDED
    
    | 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'camper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            client = Camper.configure do |config|
         
     | 
| 
      
 4 
     | 
    
         
            +
                config.client_id = ENV['BASECAMP3_CLIENT_ID']
         
     | 
| 
      
 5 
     | 
    
         
            +
                config.client_secret = ENV['BASECAMP3_CLIENT_SECRET']
         
     | 
| 
      
 6 
     | 
    
         
            +
                config.redirect_uri = ENV['BASECAMP3_REDIRECT_URI']
         
     | 
| 
      
 7 
     | 
    
         
            +
            end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            # Get the authorization uri
         
     | 
| 
      
 10 
     | 
    
         
            +
            puts client.authorization_uri
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            # Once you have received the auth code from basecamp, you can proceed with the following step
         
     | 
| 
      
 13 
     | 
    
         
            +
            # This will update the configuration with the corresponding tokens
         
     | 
| 
      
 14 
     | 
    
         
            +
            # Store the tokens in a safe place
         
     | 
| 
      
 15 
     | 
    
         
            +
            token = client.authorize! ENV['BASECAMP3_ACCESS_CODE']
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            # Print refresh token
         
     | 
| 
      
 18 
     | 
    
         
            +
            puts token.refresh_token
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            # Print access token
         
     | 
| 
      
 21 
     | 
    
         
            +
            puts token.access_token
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'camper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            client = Camper.configure do |config|
         
     | 
| 
      
 4 
     | 
    
         
            +
              config.client_id = ENV['BASECAMP3_CLIENT_ID']
         
     | 
| 
      
 5 
     | 
    
         
            +
              config.client_secret = ENV['BASECAMP3_CLIENT_SECRET']
         
     | 
| 
      
 6 
     | 
    
         
            +
              config.account_number = ENV['BASECAMP3_ACCOUNT_NUMBER']
         
     | 
| 
      
 7 
     | 
    
         
            +
              config.refresh_token = ENV['BASECAMP3_REFRESH_TOKEN']
         
     | 
| 
      
 8 
     | 
    
         
            +
            end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            tokens = client.update_access_token!
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            # Prints the new access token
         
     | 
| 
      
 13 
     | 
    
         
            +
            puts tokens.access_token
         
     | 
    
        data/examples/todos.rb
    ADDED
    
    | 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'camper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            client = Camper.configure do |config|
         
     | 
| 
      
 4 
     | 
    
         
            +
              config.client_id = ENV['BASECAMP3_CLIENT_ID']
         
     | 
| 
      
 5 
     | 
    
         
            +
              config.client_secret = ENV['BASECAMP3_CLIENT_SECRET']
         
     | 
| 
      
 6 
     | 
    
         
            +
              config.account_number = ENV['BASECAMP3_ACCOUNT_NUMBER']
         
     | 
| 
      
 7 
     | 
    
         
            +
              config.refresh_token = ENV['BASECAMP3_REFRESH_TOKEN']
         
     | 
| 
      
 8 
     | 
    
         
            +
              config.access_token = ENV['BASECAMP3_ACCESS_TOKEN']
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            projects = client.projects
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            projects.auto_paginate do |p|
         
     | 
| 
      
 14 
     | 
    
         
            +
              puts "Project: #{p.inspect}"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              puts "Todo set: #{p.todoset.inspect}"
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              todoset = client.todoset(p)
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              client.todolists(todoset).auto_paginate(5) do |list|
         
     | 
| 
      
 21 
     | 
    
         
            +
                puts "Todolist: #{list.title}"
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                client.todos(list).auto_paginate do |todo|
         
     | 
| 
      
 24 
     | 
    
         
            +
                  puts todo.inspect
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/camper.rb
    ADDED
    
    | 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'forwardable'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rack/oauth2'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            require 'camper/version'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'camper/logging'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'camper/error'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'camper/configuration'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'camper/authorization'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require 'camper/resource'
         
     | 
| 
      
 12 
     | 
    
         
            +
            require 'camper/pagination_data'
         
     | 
| 
      
 13 
     | 
    
         
            +
            require 'camper/paginated_response'
         
     | 
| 
      
 14 
     | 
    
         
            +
            require 'camper/request'
         
     | 
| 
      
 15 
     | 
    
         
            +
            require 'camper/client'
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            module Camper
         
     | 
| 
      
 18 
     | 
    
         
            +
              # Alias for Camper::Client.new
         
     | 
| 
      
 19 
     | 
    
         
            +
              #
         
     | 
| 
      
 20 
     | 
    
         
            +
              # @return [Camper::Client]
         
     | 
| 
      
 21 
     | 
    
         
            +
              def self.client(options = {})
         
     | 
| 
      
 22 
     | 
    
         
            +
                Camper::Client.new(options)
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              # Delegates to Camper::Client configure method
         
     | 
| 
      
 26 
     | 
    
         
            +
              #
         
     | 
| 
      
 27 
     | 
    
         
            +
              # @return [Camper::Client]
         
     | 
| 
      
 28 
     | 
    
         
            +
              def self.configure(&block)
         
     | 
| 
      
 29 
     | 
    
         
            +
                client.configure(&block)
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Camper::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
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Camper::Client
         
     | 
| 
      
 4 
     | 
    
         
            +
              module ProjectAPI
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def projects(options = {})
         
     | 
| 
      
 7 
     | 
    
         
            +
                  get("/projects", options)
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def message_board(project)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  board = project.message_board
         
     | 
| 
      
 12 
     | 
    
         
            +
                  get(board.url, override_path: true)
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def todoset(project)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  todoset = project.todoset
         
     | 
| 
      
 17 
     | 
    
         
            +
                  get(todoset.url, override_path: true)
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Camper::Client
         
     | 
| 
      
 4 
     | 
    
         
            +
              module TodoAPI
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def todolists(todoset)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  get(todoset.todolists_url, override_path: true)
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def todos(todolist, options={})
         
     | 
| 
      
 11 
     | 
    
         
            +
                  get(todolist.todos_url, options.merge(override_path: true))
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,64 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Camper
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Authorization
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def authorization_uri
         
     | 
| 
      
 7 
     | 
    
         
            +
                  client = authz_client
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  client.authorization_uri type: :web_server
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def authz_client
         
     | 
| 
      
 13 
     | 
    
         
            +
                  Rack::OAuth2::Client.new(
         
     | 
| 
      
 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 
     | 
    
         
            +
                  )
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def authorize!(auth_code)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  client = authz_client
         
     | 
| 
      
 24 
     | 
    
         
            +
                  client.authorization_code = auth_code
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  # Passing secrets as query string
         
     | 
| 
      
 27 
     | 
    
         
            +
                  token = client.access_token!(
         
     | 
| 
      
 28 
     | 
    
         
            +
                    client_auth_method: nil,
         
     | 
| 
      
 29 
     | 
    
         
            +
                    client_id: @config.client_id,
         
     | 
| 
      
 30 
     | 
    
         
            +
                    client_secret: @config.client_secret,
         
     | 
| 
      
 31 
     | 
    
         
            +
                    type: :web_server
         
     | 
| 
      
 32 
     | 
    
         
            +
                  )
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  store_tokens(token)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  token
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def update_access_token!
         
     | 
| 
      
 40 
     | 
    
         
            +
                  logger.debug "Update access token using refresh token"
         
     | 
| 
      
 41 
     | 
    
         
            +
                  
         
     | 
| 
      
 42 
     | 
    
         
            +
                  client = authz_client
         
     | 
| 
      
 43 
     | 
    
         
            +
                  client.refresh_token = @config.refresh_token
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  token = client.access_token!(
         
     | 
| 
      
 46 
     | 
    
         
            +
                    client_auth_method: nil,
         
     | 
| 
      
 47 
     | 
    
         
            +
                    client_id: @config.client_id,
         
     | 
| 
      
 48 
     | 
    
         
            +
                    client_secret: @config.client_secret,
         
     | 
| 
      
 49 
     | 
    
         
            +
                    type: :refresh
         
     | 
| 
      
 50 
     | 
    
         
            +
                  )
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  store_tokens(token)
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  token
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                private
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                def store_tokens(token)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  @config.access_token = token.access_token
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @config.refresh_token = token.refresh_token
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,86 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Camper
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Wrapper for the Camper REST API.
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Client
         
     | 
| 
      
 6 
     | 
    
         
            +
                Dir[File.expand_path('api/*.rb', __dir__)].each { |f| require f }
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                extend Forwardable
         
     | 
| 
      
 9 
     | 
    
         
            +
                
         
     | 
| 
      
 10 
     | 
    
         
            +
                def_delegators :@config, *(Configuration::VALID_OPTIONS_KEYS)
         
     | 
| 
      
 11 
     | 
    
         
            +
                def_delegators :@config, :authz_endpoint, :token_endpoint, :api_endpoint, :base_api_endpoint
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                # Keep in alphabetical order
         
     | 
| 
      
 14 
     | 
    
         
            +
                include Authorization
         
     | 
| 
      
 15 
     | 
    
         
            +
                include CommentAPI
         
     | 
| 
      
 16 
     | 
    
         
            +
                include Logging
         
     | 
| 
      
 17 
     | 
    
         
            +
                include MessageAPI
         
     | 
| 
      
 18 
     | 
    
         
            +
                include ProjectAPI
         
     | 
| 
      
 19 
     | 
    
         
            +
                include ResourceAPI
         
     | 
| 
      
 20 
     | 
    
         
            +
                include TodoAPI
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                # Creates a new API.
         
     | 
| 
      
 23 
     | 
    
         
            +
                # @raise [Error:MissingCredentials]
         
     | 
| 
      
 24 
     | 
    
         
            +
                def initialize(options = {})
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @config = Configuration.new(options)
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                %w[get post put delete].each do |method|
         
     | 
| 
      
 29 
     | 
    
         
            +
                  define_method method do |path, options = {}|
         
     | 
| 
      
 30 
     | 
    
         
            +
                    response, result = new_request.send(method, path, options)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    return response unless result == Request::Result::AccessTokenExpired
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    update_access_token!
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    response, = new_request.send(method, path, options)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    response
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 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 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                # Text representation of the client, masking private token.
         
     | 
| 
      
 49 
     | 
    
         
            +
                #
         
     | 
| 
      
 50 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 51 
     | 
    
         
            +
                def inspect
         
     | 
| 
      
 52 
     | 
    
         
            +
                  inspected = super
         
     | 
| 
      
 53 
     | 
    
         
            +
                  inspected.sub! @config.access_token, only_show_last_four_chars(@config.access_token) if @config.access_token
         
     | 
| 
      
 54 
     | 
    
         
            +
                  inspected
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                # Utility method for URL encoding of a string.
         
     | 
| 
      
 58 
     | 
    
         
            +
                # Copied from https://ruby-doc.org/stdlib-2.7.0/libdoc/erb/rdoc/ERB/Util.html
         
     | 
| 
      
 59 
     | 
    
         
            +
                #
         
     | 
| 
      
 60 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 61 
     | 
    
         
            +
                def url_encode(url)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  url.to_s.b.gsub(/[^a-zA-Z0-9_\-.~]/n) { |m| sprintf('%%%02X', m.unpack1('C')) } # rubocop:disable Style/FormatString, Style/FormatStringToken
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                private
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                def new_request
         
     | 
| 
      
 68 
     | 
    
         
            +
                  Request.new(@config.access_token, @config.user_agent, self)
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                def only_show_last_four_chars(token)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  "#{'*' * (token.size - 4)}#{token[-4..-1]}"
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                # Utility method for transforming Basecamp Web URLs into API URIs
         
     | 
| 
      
 76 
     | 
    
         
            +
                # e.g 'https://3.basecamp.com/1/buckets/2/todos/3' will be 
         
     | 
| 
      
 77 
     | 
    
         
            +
                # converted into 'https://3.basecampapi.com/1/buckets/2/todos/3.json'
         
     | 
| 
      
 78 
     | 
    
         
            +
                #
         
     | 
| 
      
 79 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 80 
     | 
    
         
            +
                def url_transform(url)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  api_uri = url.gsub('3.basecamp.com', '3.basecampapi.com')
         
     | 
| 
      
 82 
     | 
    
         
            +
                  api_uri += '.json' unless url.end_with? '.json'
         
     | 
| 
      
 83 
     | 
    
         
            +
                  api_uri
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
            end
         
     |