discourse_api 0.40.0 → 0.44.0
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 +4 -4
- data/.github/workflows/ci.yml +54 -0
- data/.gitignore +0 -2
- data/CHANGELOG.md +40 -8
- data/README.md +13 -2
- data/discourse_api.gemspec +3 -3
- data/examples/change_topic_status.rb +3 -4
- data/examples/create_topic.rb +10 -0
- data/lib/discourse_api/api/api_key.rb +0 -8
- data/lib/discourse_api/api/groups.rb +10 -2
- data/lib/discourse_api/api/sso.rb +1 -18
- data/lib/discourse_api/api/tags.rb +1 -1
- data/lib/discourse_api/api/topics.rb +8 -2
- data/lib/discourse_api/client.rb +20 -4
- data/lib/discourse_api/single_sign_on.rb +31 -2
- data/lib/discourse_api/version.rb +1 -1
- data/spec/discourse_api/api/api_key_spec.rb +0 -27
- data/spec/discourse_api/api/sso_spec.rb +43 -1
- data/spec/discourse_api/api/topics_spec.rb +19 -1
- data/spec/fixtures/create_topic_with_tags.json +65 -0
- metadata +10 -10
- data/.travis.yml +0 -11
- data/spec/fixtures/generate_api_key.json +0 -12
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 13cfa5b25dbe59e809cdcdb924406f9e680f1e029a5666fff9a0febbd75d5bf0
         | 
| 4 | 
            +
              data.tar.gz: d68c096a8ae91dea4a70b60f9d412954712297544e49b891fc228f11d63ca4d6
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: c942a353d95a144daa1939d448c949ad56a00e0999a0166c112e403e0ce5529941e8883d7456b029a173cdc79ebf7ffc08e84cc7e2e63956434ab00a6a60abf0
         | 
| 7 | 
            +
              data.tar.gz: 909bb8f30f2ae412c93d1e0a9777786b8cae01c4bd15474f5ea980c0485bb91ca82f5eb62a81773f76a05b8eeb97bde076411a0dbe61e4407c0ca2204ac5484e
         | 
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            name: CI
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            on:
         | 
| 4 | 
            +
              pull_request:
         | 
| 5 | 
            +
              push:
         | 
| 6 | 
            +
                branches:
         | 
| 7 | 
            +
                  - master
         | 
| 8 | 
            +
                tags:
         | 
| 9 | 
            +
                  - v*
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            jobs:
         | 
| 12 | 
            +
              build:
         | 
| 13 | 
            +
                runs-on: ubuntu-latest
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                strategy:
         | 
| 16 | 
            +
                  matrix:
         | 
| 17 | 
            +
                    ruby:
         | 
| 18 | 
            +
                      - 2.5
         | 
| 19 | 
            +
                      - 2.6
         | 
| 20 | 
            +
                      - 2.7
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                steps:
         | 
| 23 | 
            +
                  - uses: actions/checkout@v1
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  - name: Setup ruby
         | 
| 26 | 
            +
                    uses: actions/setup-ruby@v1
         | 
| 27 | 
            +
                    with:
         | 
| 28 | 
            +
                      ruby-version: ${{ matrix.ruby }}
         | 
| 29 | 
            +
                      architecture: 'x64'
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  - name: Setup bundler
         | 
| 32 | 
            +
                    run: gem install bundler
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  - name: Setup gems
         | 
| 35 | 
            +
                    run: bundle install
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  - name: Rubocop
         | 
| 38 | 
            +
                    run: bundle exec rubocop
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  - name: RSpec
         | 
| 41 | 
            +
                    run: bundle exec rspec
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              publish:
         | 
| 44 | 
            +
                if: contains(github.ref, 'refs/tags/v')
         | 
| 45 | 
            +
                needs: build
         | 
| 46 | 
            +
                runs-on: ubuntu-latest
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                steps:
         | 
| 49 | 
            +
                  - uses: actions/checkout@v2
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  - name: Release Gem
         | 
| 52 | 
            +
                    uses: CvX/publish-rubygems-action@master
         | 
| 53 | 
            +
                    env:
         | 
| 54 | 
            +
                      RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_API_KEY}}
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,6 +1,43 @@ | |
| 1 | 
            -
            #  | 
| 1 | 
            +
            # Changelog
         | 
| 2 2 | 
             
            All notable changes to this project will be documented in this file.
         | 
| 3 | 
            -
             | 
| 3 | 
            +
             | 
| 4 | 
            +
            The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
         | 
| 5 | 
            +
            and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            ## [Unreleased]
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ## [0.44.0] - 2020-11-13
         | 
| 10 | 
            +
            ### Fixed
         | 
| 11 | 
            +
            - Updated `show_tag` method to use new route
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            ### Removed
         | 
| 14 | 
            +
            - Support for Ruby 2.3 and 2.4
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            ## [0.43.1] - 2020-11-04
         | 
| 17 | 
            +
            ### Fixed
         | 
| 18 | 
            +
            - tagged verion 0.43.0 got pushed without commmit due to new master branch
         | 
| 19 | 
            +
              protections in github. No, code changes here just making sure tags align with
         | 
| 20 | 
            +
              commits.
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            ## [0.43.0] - 2020-11-04
         | 
| 23 | 
            +
            ### Added
         | 
| 24 | 
            +
            - Add pagination to list groups endpoint
         | 
| 25 | 
            +
            ### Deprecated
         | 
| 26 | 
            +
            - `change_topic_status` has been deprecated, use `update_topic_status` instead.
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            ## [0.42.0] - 2020-07-09
         | 
| 29 | 
            +
            ### Added
         | 
| 30 | 
            +
            - Create topics with tags
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            ## [0.41.0] - 2020-06-17
         | 
| 33 | 
            +
            ### Added
         | 
| 34 | 
            +
            - Add basic auth support
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            ### Fixed
         | 
| 37 | 
            +
            - Fix SSO custom field prefixes
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            ### Removed
         | 
| 40 | 
            +
            - Obsolete api key endpoints
         | 
| 4 41 |  | 
| 5 42 | 
             
            ## [0.40.0] - 2020-05-07
         | 
| 6 43 | 
             
            ### Fixed
         | 
| @@ -224,7 +261,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). | |
| 224 261 | 
             
            ## [0.8.1] - 2016-03-03
         | 
| 225 262 | 
             
            ### Fixed
         | 
| 226 263 | 
             
            - enable use of discourse_api to make unauthenticated requests to discourse
         | 
| 227 | 
            -
              endpoints like /categories and /topics | 
| 264 | 
            +
              endpoints like /categories and /topics
         | 
| 228 265 |  | 
| 229 266 | 
             
            ## [0.8.0] - 2016-02-28
         | 
| 230 267 | 
             
            ### Added
         | 
| @@ -281,8 +318,3 @@ This project adheres to [Semantic Versioning](http://semver.org/). | |
| 281 318 | 
             
            ## [0.1.2] - 2014-05-11
         | 
| 282 319 |  | 
| 283 320 | 
             
            - Release
         | 
| 284 | 
            -
             | 
| 285 | 
            -
             | 
| 286 | 
            -
             | 
| 287 | 
            -
             | 
| 288 | 
            -
             | 
    
        data/README.md
    CHANGED
    
    | @@ -34,7 +34,6 @@ client.ssl(...)                                 #=> specify SSL connection setti | |
| 34 34 |  | 
| 35 35 | 
             
            # Topic endpoints
         | 
| 36 36 | 
             
            client.latest_topics                            #=> Gets a list of the latest topics
         | 
| 37 | 
            -
            client.hot_topics                               #=> Gets a list of hot topics
         | 
| 38 37 | 
             
            client.new_topics                               #=> Gets a list of new topics
         | 
| 39 38 | 
             
            client.topics_by("sam")                         #=> Gets a list of topics created by user "sam"
         | 
| 40 39 | 
             
            client.topic(57)                                #=> Gets the topic with id 57
         | 
| @@ -52,7 +51,10 @@ client.sync_sso(                                #=> Synchronizes the SSO record | |
| 52 51 | 
             
              name: "Test Name",
         | 
| 53 52 | 
             
              username: "test_name",
         | 
| 54 53 | 
             
              email: "name@example.com",
         | 
| 55 | 
            -
              external_id: "2"
         | 
| 54 | 
            +
              external_id: "2",
         | 
| 55 | 
            +
              custom_fields: {
         | 
| 56 | 
            +
                field_1: 'potato'
         | 
| 57 | 
            +
              }
         | 
| 56 58 | 
             
            )
         | 
| 57 59 |  | 
| 58 60 | 
             
            # Private messages
         | 
| @@ -80,6 +82,15 @@ end | |
| 80 82 |  | 
| 81 83 | 
             
            Check out [lib/discourse_api/error.rb](lib/discourse_api/error.rb) and [lib/discourse_api/client.rb](lib/discourse_api/client.rb)'s `handle_error` method for the types of errors raised by the API.
         | 
| 82 84 |  | 
| 85 | 
            +
            If your forum has a basic HTTP authentication enabled, set user and password:
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            ```ruby
         | 
| 88 | 
            +
            client.basic_auth = {
         | 
| 89 | 
            +
              user: "test",
         | 
| 90 | 
            +
              password: "secret"
         | 
| 91 | 
            +
            }
         | 
| 92 | 
            +
            ```
         | 
| 93 | 
            +
             | 
| 83 94 | 
             
            ## Contributing
         | 
| 84 95 |  | 
| 85 96 | 
             
            1. Fork it
         | 
    
        data/discourse_api.gemspec
    CHANGED
    
    | @@ -18,8 +18,8 @@ Gem::Specification.new do |spec| | |
| 18 18 | 
             
              spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
         | 
| 19 19 | 
             
              spec.require_paths = ['lib']
         | 
| 20 20 |  | 
| 21 | 
            -
              spec.add_dependency 'faraday', '~> 0 | 
| 22 | 
            -
              spec.add_dependency 'faraday_middleware', '~> 0 | 
| 21 | 
            +
              spec.add_dependency 'faraday', '~> 1.0'
         | 
| 22 | 
            +
              spec.add_dependency 'faraday_middleware', '~> 1.0'
         | 
| 23 23 | 
             
              spec.add_dependency 'rack', '>= 1.6'
         | 
| 24 24 |  | 
| 25 25 | 
             
              spec.add_development_dependency 'bundler', '~> 2.0'
         | 
| @@ -32,5 +32,5 @@ Gem::Specification.new do |spec| | |
| 32 32 | 
             
              spec.add_development_dependency 'webmock', '~> 2.0'
         | 
| 33 33 | 
             
              spec.add_development_dependency 'rubocop-discourse'
         | 
| 34 34 |  | 
| 35 | 
            -
              spec.required_ruby_version = '>= 2. | 
| 35 | 
            +
              spec.required_ruby_version = '>= 2.5.0'
         | 
| 36 36 | 
             
            end
         | 
| @@ -16,9 +16,8 @@ response = client.create_topic( | |
| 16 16 | 
             
                raw: "This is the raw markdown for my post"
         | 
| 17 17 | 
             
            )
         | 
| 18 18 |  | 
| 19 | 
            -
            # get topic_id  | 
| 19 | 
            +
            # get topic_id from response
         | 
| 20 20 | 
             
            topic_id = response['topic_id']
         | 
| 21 | 
            -
            topic_slug = response['topic_slug']
         | 
| 22 21 |  | 
| 23 22 | 
             
            ##
         | 
| 24 23 | 
             
            # available options (guessing from reading discourse source)
         | 
| @@ -28,8 +27,8 @@ topic_slug = response['topic_slug'] | |
| 28 27 |  | 
| 29 28 | 
             
            # lock topic (note: api_username determines user that is performing action)
         | 
| 30 29 | 
             
            params = { status: 'closed', enabled: true, api_username: "YOUR USERNAME/USERS USERNAME" }
         | 
| 31 | 
            -
            client.change_topic_status( | 
| 30 | 
            +
            client.change_topic_status(topic_id, params)
         | 
| 32 31 |  | 
| 33 32 | 
             
            # unlock topic (note: api_username determines user that is performing action)
         | 
| 34 33 | 
             
            params = { status: 'closed', enabled: false, api_username: "YOUR USERNAME/USERS USERNAME" }
         | 
| 35 | 
            -
            client.change_topic_status( | 
| 34 | 
            +
            client.change_topic_status(topic_id, params)
         | 
    
        data/examples/create_topic.rb
    CHANGED
    
    | @@ -24,3 +24,13 @@ client.create_topic( | |
| 24 24 | 
             
              title: "Your Favorite Color?",
         | 
| 25 25 | 
             
              raw: "[poll name=color]\n- Green\n- Blue\n- Red\n[/poll]"
         | 
| 26 26 | 
             
            )
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            # Create Topic with Tags
         | 
| 29 | 
            +
            client.create_topic(
         | 
| 30 | 
            +
              category: 1,
         | 
| 31 | 
            +
              skip_validations: true,
         | 
| 32 | 
            +
              auto_track: false,
         | 
| 33 | 
            +
              title: "Concert Master: A new way to choose",
         | 
| 34 | 
            +
              raw: "This is the raw markdown for my post"
         | 
| 35 | 
            +
              tags: ['asdf', 'fdsa']
         | 
| 36 | 
            +
            )
         | 
| @@ -7,14 +7,6 @@ module DiscourseApi | |
| 7 7 | 
             
                    response.body
         | 
| 8 8 | 
             
                  end
         | 
| 9 9 |  | 
| 10 | 
            -
                  def generate_user_api_key(user_id)
         | 
| 11 | 
            -
                    response = post("/admin/users/#{user_id}/generate_api_key.json")
         | 
| 12 | 
            -
                  end
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                  def revoke_user_api_key(user_id)
         | 
| 15 | 
            -
                    response = delete("/admin/users/#{user_id}/revoke_api_key.json")
         | 
| 16 | 
            -
                  end
         | 
| 17 | 
            -
             | 
| 18 10 | 
             
                  def generate_master_key
         | 
| 19 11 | 
             
                    response = post("/admin/api/key")
         | 
| 20 12 | 
             
                  end
         | 
| @@ -60,8 +60,16 @@ module DiscourseApi | |
| 60 60 | 
             
                    put("/groups/#{group_id}", group: args)
         | 
| 61 61 | 
             
                  end
         | 
| 62 62 |  | 
| 63 | 
            -
                  def groups
         | 
| 64 | 
            -
                     | 
| 63 | 
            +
                  def groups(args = {})
         | 
| 64 | 
            +
                    params = API.params(args)
         | 
| 65 | 
            +
                      .optional(:page)
         | 
| 66 | 
            +
                      .to_h
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    url = "/groups.json"
         | 
| 69 | 
            +
                    if params.include?(:page)
         | 
| 70 | 
            +
                      url += "?page=#{params[:page]}"
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
                    response = get(url)
         | 
| 65 73 | 
             
                    response.body
         | 
| 66 74 | 
             
                  end
         | 
| 67 75 |  | 
| @@ -3,24 +3,7 @@ module DiscourseApi | |
| 3 3 | 
             
              module API
         | 
| 4 4 | 
             
                module SSO
         | 
| 5 5 | 
             
                  def sync_sso(params = {})
         | 
| 6 | 
            -
                    sso = DiscourseApi::SingleSignOn. | 
| 7 | 
            -
                    sso.sso_secret = params[:sso_secret]
         | 
| 8 | 
            -
                    sso.name = params[:name]
         | 
| 9 | 
            -
                    sso.username = params[:username]
         | 
| 10 | 
            -
                    sso.email = params[:email]
         | 
| 11 | 
            -
                    sso.external_id = params[:external_id]
         | 
| 12 | 
            -
                    sso.suppress_welcome_message = params[:suppress_welcome_message] === true
         | 
| 13 | 
            -
                    sso.avatar_url = params[:avatar_url]
         | 
| 14 | 
            -
                    sso.profile_background_url = params[:profile_background_url]
         | 
| 15 | 
            -
                    sso.card_background_url = params[:card_background_url]
         | 
| 16 | 
            -
                    sso.bio = params[:bio]
         | 
| 17 | 
            -
                    sso.title = params[:title]
         | 
| 18 | 
            -
                    sso.avatar_force_update = params[:avatar_force_update] === true
         | 
| 19 | 
            -
                    sso.add_groups = params[:add_groups]
         | 
| 20 | 
            -
                    sso.remove_groups = params[:remove_groups]
         | 
| 21 | 
            -
                    params.keys.select { |key| key.to_s.start_with?("custom") }.each do |custom_key|
         | 
| 22 | 
            -
                      sso.custom_fields[custom_key] = params[custom_key]
         | 
| 23 | 
            -
                    end
         | 
| 6 | 
            +
                    sso = DiscourseApi::SingleSignOn.parse_hash(params)
         | 
| 24 7 |  | 
| 25 8 | 
             
                    post("/admin/users/sync_sso", sso.payload)
         | 
| 26 9 | 
             
                  end
         | 
| @@ -9,7 +9,7 @@ module DiscourseApi | |
| 9 9 | 
             
                  def create_topic(args = {})
         | 
| 10 10 | 
             
                    args = API.params(args)
         | 
| 11 11 | 
             
                      .required(:title, :raw)
         | 
| 12 | 
            -
                      .optional(:skip_validations, :category, :auto_track, :created_at, :api_username)
         | 
| 12 | 
            +
                      .optional(:skip_validations, :category, :auto_track, :created_at, :api_username, :tags)
         | 
| 13 13 | 
             
                    post("/posts", args.to_h)
         | 
| 14 14 | 
             
                  end
         | 
| 15 15 |  | 
| @@ -42,11 +42,17 @@ module DiscourseApi | |
| 42 42 | 
             
                    put("/t/#{topic_id}.json", topic_id: topic_id, category_id: category_id)
         | 
| 43 43 | 
             
                  end
         | 
| 44 44 |  | 
| 45 | 
            +
                  # TODO: Deprecated. Remove after 20201231
         | 
| 45 46 | 
             
                  def change_topic_status(topic_slug, topic_id, params = {})
         | 
| 47 | 
            +
                    deprecated(__method__, 'update_topic_status')
         | 
| 48 | 
            +
                    update_topic_status(topic_id, params)
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  def update_topic_status(topic_id, params = {})
         | 
| 46 52 | 
             
                    params = API.params(params)
         | 
| 47 53 | 
             
                      .required(:status, :enabled)
         | 
| 48 54 | 
             
                      .optional(:api_username)
         | 
| 49 | 
            -
                    put("/t/#{topic_id}/status", params | 
| 55 | 
            +
                    put("/t/#{topic_id}/status", params)
         | 
| 50 56 | 
             
                  end
         | 
| 51 57 |  | 
| 52 58 | 
             
                  def topic(id, params = {})
         | 
    
        data/lib/discourse_api/client.rb
    CHANGED
    
    | @@ -28,6 +28,7 @@ require 'discourse_api/api/site_settings' | |
| 28 28 | 
             
            module DiscourseApi
         | 
| 29 29 | 
             
              class Client
         | 
| 30 30 | 
             
                attr_accessor :api_key
         | 
| 31 | 
            +
                attr_accessor :basic_auth
         | 
| 31 32 | 
             
                attr_reader :host, :api_username
         | 
| 32 33 |  | 
| 33 34 | 
             
                include DiscourseApi::API::Categories
         | 
| @@ -108,23 +109,38 @@ module DiscourseApi | |
| 108 109 | 
             
                  @user_agent ||= "DiscourseAPI Ruby Gem #{DiscourseApi::VERSION}"
         | 
| 109 110 | 
             
                end
         | 
| 110 111 |  | 
| 112 | 
            +
                def deprecated(old, new)
         | 
| 113 | 
            +
                  warn "[DEPRECATED]: `#{old}` is deprecated. Please use `#{new}` instead."
         | 
| 114 | 
            +
                end
         | 
| 115 | 
            +
             | 
| 111 116 | 
             
                private
         | 
| 112 117 |  | 
| 113 118 | 
             
                def connection
         | 
| 114 119 | 
             
                  @connection ||= Faraday.new connection_options do |conn|
         | 
| 115 | 
            -
                    # Follow redirects
         | 
| 116 | 
            -
                    conn.use FaradayMiddleware::FollowRedirects, limit: 5
         | 
| 117 120 | 
             
                    # Allow uploading of files
         | 
| 118 121 | 
             
                    conn.request :multipart
         | 
| 122 | 
            +
             | 
| 119 123 | 
             
                    # Convert request params to "www-form-encoded"
         | 
| 120 124 | 
             
                    conn.request :url_encoded
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                    # Allow to interact with forums behind basic HTTP authentication
         | 
| 127 | 
            +
                    if basic_auth
         | 
| 128 | 
            +
                      conn.request :basic_auth, basic_auth[:user], basic_auth[:password]
         | 
| 129 | 
            +
                    end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                    # Follow redirects
         | 
| 132 | 
            +
                    conn.response :follow_redirects, limit: 5
         | 
| 133 | 
            +
             | 
| 121 134 | 
             
                    # Parse responses as JSON
         | 
| 122 | 
            -
                    conn. | 
| 135 | 
            +
                    conn.response :json, content_type: 'application/json'
         | 
| 136 | 
            +
             | 
| 123 137 | 
             
                    # For HTTP debugging, uncomment
         | 
| 124 138 | 
             
                    # conn.response :logger
         | 
| 139 | 
            +
             | 
| 125 140 | 
             
                    # Use Faraday's default HTTP adapter
         | 
| 126 141 | 
             
                    conn.adapter Faraday.default_adapter
         | 
| 127 | 
            -
             | 
| 142 | 
            +
             | 
| 143 | 
            +
                    # Pass api_key and api_username on every request
         | 
| 128 144 | 
             
                    unless api_username.nil?
         | 
| 129 145 | 
             
                      conn.headers['Api-Key'] = api_key
         | 
| 130 146 | 
             
                      conn.headers['Api-Username'] = api_username
         | 
| @@ -15,6 +15,7 @@ module DiscourseApi | |
| 15 15 | 
             
                #NONCE_EXPIRY_TIME = 10.minutes # minutes is a rails method and is causing an error. Is this needed in the api?
         | 
| 16 16 |  | 
| 17 17 | 
             
                attr_accessor(*ACCESSORS)
         | 
| 18 | 
            +
                attr_accessor :custom_fields
         | 
| 18 19 | 
             
                attr_writer :sso_secret, :sso_url
         | 
| 19 20 |  | 
| 20 21 | 
             
                def self.sso_secret
         | 
| @@ -25,6 +26,36 @@ module DiscourseApi | |
| 25 26 | 
             
                  raise RuntimeError, "sso_url not implemented on class, be sure to set it on instance"
         | 
| 26 27 | 
             
                end
         | 
| 27 28 |  | 
| 29 | 
            +
                def self.parse_hash(payload)
         | 
| 30 | 
            +
                  payload
         | 
| 31 | 
            +
                  sso = new
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  sso.sso_secret = payload.delete(:sso_secret)
         | 
| 34 | 
            +
                  sso.sso_url = payload.delete(:sso_url)
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  ACCESSORS.each do |k|
         | 
| 37 | 
            +
                    val = payload[k]
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    val = val.to_i if FIXNUMS.include? k
         | 
| 40 | 
            +
                    if BOOLS.include? k
         | 
| 41 | 
            +
                      val = ["true", "false"].include?(val) ? val == "true" : nil
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
                    val = Array(val) if ARRAYS.include?(k) && !val.nil?
         | 
| 44 | 
            +
                    sso.send("#{k}=", val)
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                  # Set custom_fields
         | 
| 47 | 
            +
                  sso.custom_fields = payload[:custom_fields]
         | 
| 48 | 
            +
                  # Add custom_fields (old format)
         | 
| 49 | 
            +
                  payload.each do |k, v|
         | 
| 50 | 
            +
                    if field = k[/^custom\.(.+)$/, 1]
         | 
| 51 | 
            +
                      # Maintain adding of .custom bug
         | 
| 52 | 
            +
                      sso.custom_fields["custom.#{field}"] = v
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  sso
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 28 59 | 
             
                def self.parse(payload, sso_secret = nil)
         | 
| 29 60 | 
             
                  sso = new
         | 
| 30 61 | 
             
                  sso.sso_secret = sso_secret if sso_secret
         | 
| @@ -107,7 +138,5 @@ module DiscourseApi | |
| 107 138 |  | 
| 108 139 | 
             
                  Rack::Utils.build_query(payload)
         | 
| 109 140 | 
             
                end
         | 
| 110 | 
            -
             | 
| 111 141 | 
             
              end
         | 
| 112 | 
            -
             | 
| 113 142 | 
             
            end
         | 
| @@ -31,33 +31,6 @@ describe DiscourseApi::API::ApiKey do | |
| 31 31 | 
             
                end
         | 
| 32 32 | 
             
              end
         | 
| 33 33 |  | 
| 34 | 
            -
              describe "#generate_user_api_key" do
         | 
| 35 | 
            -
                before do
         | 
| 36 | 
            -
                  url = "#{host}/admin/users/2/generate_api_key.json"
         | 
| 37 | 
            -
                  stub_post(url).to_return(body: fixture("generate_api_key.json"),
         | 
| 38 | 
            -
                                           headers: { content_type: "application/json" })
         | 
| 39 | 
            -
                end
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                it "returns the generated api key" do
         | 
| 42 | 
            -
                  api_key = subject.generate_user_api_key(2)
         | 
| 43 | 
            -
                  expect(api_key).to be_a Hash
         | 
| 44 | 
            -
                  expect(api_key['api_key']).to have_key('key')
         | 
| 45 | 
            -
                end
         | 
| 46 | 
            -
              end
         | 
| 47 | 
            -
             | 
| 48 | 
            -
              describe "#revoke_user_api_key" do
         | 
| 49 | 
            -
                before do
         | 
| 50 | 
            -
                  url = "#{host}/admin/users/2/revoke_api_key.json"
         | 
| 51 | 
            -
                  stub_delete(url).to_return(body: "",
         | 
| 52 | 
            -
                                             headers: { content_type: "application/json" })
         | 
| 53 | 
            -
                end
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                it "returns 200" do
         | 
| 56 | 
            -
                  response = subject.revoke_user_api_key(2)
         | 
| 57 | 
            -
                  expect(response['status']).to eq(200)
         | 
| 58 | 
            -
                end
         | 
| 59 | 
            -
              end
         | 
| 60 | 
            -
             | 
| 61 34 | 
             
              describe "#generate_master_key" do
         | 
| 62 35 | 
             
                before do
         | 
| 63 36 | 
             
                  url = "#{host}/admin/api/key"
         | 
| @@ -4,9 +4,51 @@ require 'spec_helper' | |
| 4 4 | 
             
            describe DiscourseApi::API::SSO do
         | 
| 5 5 | 
             
              subject { DiscourseApi::Client.new("#{host}", "test_d7fd0429940", "test_user") }
         | 
| 6 6 |  | 
| 7 | 
            +
              let(:params) do
         | 
| 8 | 
            +
                {
         | 
| 9 | 
            +
                  sso_secret: 'abc',
         | 
| 10 | 
            +
                  sso_url: 'www.google.com',
         | 
| 11 | 
            +
                  name: 'Some User',
         | 
| 12 | 
            +
                  username: 'some_user',
         | 
| 13 | 
            +
                  email: 'some@email.com',
         | 
| 14 | 
            +
                  external_id: 'abc',
         | 
| 15 | 
            +
                  suppress_welcome_message: false,
         | 
| 16 | 
            +
                  avatar_url: 'https://www.website.com',
         | 
| 17 | 
            +
                  title: 'ruby',
         | 
| 18 | 
            +
                  avatar_force_update: false,
         | 
| 19 | 
            +
                  add_groups: ['a', 'b'],
         | 
| 20 | 
            +
                  remove_groups: ['c', 'd'],
         | 
| 21 | 
            +
                  # old format (which results in custom.custom.field_1 in unsigned_payload)
         | 
| 22 | 
            +
                  'custom.field_1' => 'tomato',
         | 
| 23 | 
            +
                  # new format
         | 
| 24 | 
            +
                  custom_fields: {
         | 
| 25 | 
            +
                    field_2: 'potato'
         | 
| 26 | 
            +
                  }
         | 
| 27 | 
            +
                }
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
              let(:expected_unsigned_payload) do
         | 
| 30 | 
            +
                'name=Some+User&username=some_user&email=some%40email.com&'\
         | 
| 31 | 
            +
                'avatar_url=https%3A%2F%2Fwww.website.com&external_id=abc&title=ruby'\
         | 
| 32 | 
            +
                '&add_groups=a&add_groups=b&remove_groups=c&remove_groups=d&custom.field_2=potato&'\
         | 
| 33 | 
            +
                'custom.custom.field_1=tomato'
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
              let(:sso_double) { DiscourseApi::SingleSignOn.parse_hash(params) }
         | 
| 36 | 
            +
             | 
| 7 37 | 
             
              describe "#sync_sso" do
         | 
| 8 38 | 
             
                before do
         | 
| 9 | 
            -
                  stub_post(/.*sync_sso.*/).to_return( | 
| 39 | 
            +
                  stub_post(/.*sync_sso.*/).to_return(
         | 
| 40 | 
            +
                    body: fixture("user.json"),
         | 
| 41 | 
            +
                    headers: { content_type: "application/json" }
         | 
| 42 | 
            +
                  )
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                it 'assigns params to sso instance' do
         | 
| 46 | 
            +
                  allow(DiscourseApi::SingleSignOn).to(receive(:parse_hash).with(params).and_return(sso_double))
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  subject.sync_sso(params)
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  expect(sso_double.custom_fields).to eql({ 'custom.field_1' => 'tomato', :field_2 => 'potato' })
         | 
| 51 | 
            +
                  expect(sso_double.unsigned_payload).to eql(expected_unsigned_payload)
         | 
| 10 52 | 
             
                end
         | 
| 11 53 |  | 
| 12 54 | 
             
                it "requests the correct resource" do
         | 
| @@ -10,7 +10,7 @@ describe DiscourseApi::API::Topics do | |
| 10 10 | 
             
                end
         | 
| 11 11 |  | 
| 12 12 | 
             
                it "changes the topic status" do
         | 
| 13 | 
            -
                  subject. | 
| 13 | 
            +
                  subject.update_topic_status(57, { status: 'visible', enabled: false })
         | 
| 14 14 | 
             
                  expect(a_put("#{host}/t/57/status")).to have_been_made
         | 
| 15 15 | 
             
                end
         | 
| 16 16 | 
             
              end
         | 
| @@ -148,4 +148,22 @@ describe DiscourseApi::API::Topics do | |
| 148 148 | 
             
                  expect(body['post_stream']['posts'].first).to be_a Hash
         | 
| 149 149 | 
             
                end
         | 
| 150 150 | 
             
              end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
              describe "#create_topic_with_tags" do
         | 
| 153 | 
            +
                before do
         | 
| 154 | 
            +
                  stub_post("#{host}/posts").to_return(body: fixture("create_topic_with_tags.json"), headers: { content_type: "application/json" })
         | 
| 155 | 
            +
                end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                it "makes the post request" do
         | 
| 158 | 
            +
                  subject.create_topic title: "Sample Topic Title", raw: "Sample topic content body", tags: ["asdf", "fdsa"]
         | 
| 159 | 
            +
                  expect(a_post("#{host}/posts")).to have_been_made
         | 
| 160 | 
            +
                end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                it "returns success" do
         | 
| 163 | 
            +
                  response = subject.create_topic title: "Sample Topic Title", raw: "Sample topic content body", tags: ["asdf", "fdsa"]
         | 
| 164 | 
            +
                  expect(response).to be_a Hash
         | 
| 165 | 
            +
                  expect(response['topic_id']).to eq 21
         | 
| 166 | 
            +
                end
         | 
| 167 | 
            +
              end
         | 
| 168 | 
            +
             | 
| 151 169 | 
             
            end
         | 
| @@ -0,0 +1,65 @@ | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
              "id": 29,
         | 
| 3 | 
            +
              "name": null,
         | 
| 4 | 
            +
              "username": "blake",
         | 
| 5 | 
            +
              "avatar_template": "/user_avatar/localhost/blake/{size}/3_2.png",
         | 
| 6 | 
            +
              "created_at": "2020-07-09T15:52:43.802Z",
         | 
| 7 | 
            +
              "cooked": "<p>cb8ee24eb3c5a81139958cf2b6bee9bd 2a7f7ea218e24c9ee6528cd383527f99 5a3006b92918946230385393a83b6005</p>",
         | 
| 8 | 
            +
              "post_number": 1,
         | 
| 9 | 
            +
              "post_type": 1,
         | 
| 10 | 
            +
              "updated_at": "2020-07-09T15:52:43.802Z",
         | 
| 11 | 
            +
              "reply_count": 0,
         | 
| 12 | 
            +
              "reply_to_post_number": null,
         | 
| 13 | 
            +
              "quote_count": 0,
         | 
| 14 | 
            +
              "incoming_link_count": 0,
         | 
| 15 | 
            +
              "reads": 0,
         | 
| 16 | 
            +
              "readers_count": 0,
         | 
| 17 | 
            +
              "score": 0,
         | 
| 18 | 
            +
              "yours": true,
         | 
| 19 | 
            +
              "topic_id": 21,
         | 
| 20 | 
            +
              "topic_slug": "1412a036bfe-6480718525e-9f71f98ef46",
         | 
| 21 | 
            +
              "display_username": null,
         | 
| 22 | 
            +
              "primary_group_name": null,
         | 
| 23 | 
            +
              "primary_group_flair_url": null,
         | 
| 24 | 
            +
              "primary_group_flair_bg_color": null,
         | 
| 25 | 
            +
              "primary_group_flair_color": null,
         | 
| 26 | 
            +
              "version": 1,
         | 
| 27 | 
            +
              "can_edit": true,
         | 
| 28 | 
            +
              "can_delete": false,
         | 
| 29 | 
            +
              "can_recover": false,
         | 
| 30 | 
            +
              "can_wiki": true,
         | 
| 31 | 
            +
              "user_title": null,
         | 
| 32 | 
            +
              "actions_summary": [
         | 
| 33 | 
            +
                {
         | 
| 34 | 
            +
                  "id": 3,
         | 
| 35 | 
            +
                  "can_act": true
         | 
| 36 | 
            +
                },
         | 
| 37 | 
            +
                {
         | 
| 38 | 
            +
                  "id": 4,
         | 
| 39 | 
            +
                  "can_act": true
         | 
| 40 | 
            +
                },
         | 
| 41 | 
            +
                {
         | 
| 42 | 
            +
                  "id": 8,
         | 
| 43 | 
            +
                  "can_act": true
         | 
| 44 | 
            +
                },
         | 
| 45 | 
            +
                {
         | 
| 46 | 
            +
                  "id": 7,
         | 
| 47 | 
            +
                  "can_act": true
         | 
| 48 | 
            +
                }
         | 
| 49 | 
            +
              ],
         | 
| 50 | 
            +
              "moderator": false,
         | 
| 51 | 
            +
              "admin": true,
         | 
| 52 | 
            +
              "staff": true,
         | 
| 53 | 
            +
              "user_id": 1,
         | 
| 54 | 
            +
              "draft_sequence": 0,
         | 
| 55 | 
            +
              "hidden": false,
         | 
| 56 | 
            +
              "trust_level": 1,
         | 
| 57 | 
            +
              "deleted_at": null,
         | 
| 58 | 
            +
              "user_deleted": false,
         | 
| 59 | 
            +
              "edit_reason": null,
         | 
| 60 | 
            +
              "can_view_edit_history": true,
         | 
| 61 | 
            +
              "wiki": false,
         | 
| 62 | 
            +
              "reviewable_id": null,
         | 
| 63 | 
            +
              "reviewable_score_count": 0,
         | 
| 64 | 
            +
              "reviewable_score_pending_count": 0
         | 
| 65 | 
            +
            }
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: discourse_api
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.44.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Sam Saffron
         | 
| @@ -11,7 +11,7 @@ authors: | |
| 11 11 | 
             
            autorequire: 
         | 
| 12 12 | 
             
            bindir: bin
         | 
| 13 13 | 
             
            cert_chain: []
         | 
| 14 | 
            -
            date: 2020- | 
| 14 | 
            +
            date: 2020-11-13 00:00:00.000000000 Z
         | 
| 15 15 | 
             
            dependencies:
         | 
| 16 16 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 17 17 | 
             
              name: faraday
         | 
| @@ -19,28 +19,28 @@ dependencies: | |
| 19 19 | 
             
                requirements:
         | 
| 20 20 | 
             
                - - "~>"
         | 
| 21 21 | 
             
                  - !ruby/object:Gem::Version
         | 
| 22 | 
            -
                    version: '0 | 
| 22 | 
            +
                    version: '1.0'
         | 
| 23 23 | 
             
              type: :runtime
         | 
| 24 24 | 
             
              prerelease: false
         | 
| 25 25 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 26 26 | 
             
                requirements:
         | 
| 27 27 | 
             
                - - "~>"
         | 
| 28 28 | 
             
                  - !ruby/object:Gem::Version
         | 
| 29 | 
            -
                    version: '0 | 
| 29 | 
            +
                    version: '1.0'
         | 
| 30 30 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 31 31 | 
             
              name: faraday_middleware
         | 
| 32 32 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 33 33 | 
             
                requirements:
         | 
| 34 34 | 
             
                - - "~>"
         | 
| 35 35 | 
             
                  - !ruby/object:Gem::Version
         | 
| 36 | 
            -
                    version: '0 | 
| 36 | 
            +
                    version: '1.0'
         | 
| 37 37 | 
             
              type: :runtime
         | 
| 38 38 | 
             
              prerelease: false
         | 
| 39 39 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 40 40 | 
             
                requirements:
         | 
| 41 41 | 
             
                - - "~>"
         | 
| 42 42 | 
             
                  - !ruby/object:Gem::Version
         | 
| 43 | 
            -
                    version: '0 | 
| 43 | 
            +
                    version: '1.0'
         | 
| 44 44 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 45 45 | 
             
              name: rack
         | 
| 46 46 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -191,9 +191,9 @@ executables: [] | |
| 191 191 | 
             
            extensions: []
         | 
| 192 192 | 
             
            extra_rdoc_files: []
         | 
| 193 193 | 
             
            files:
         | 
| 194 | 
            +
            - ".github/workflows/ci.yml"
         | 
| 194 195 | 
             
            - ".gitignore"
         | 
| 195 196 | 
             
            - ".rubocop.yml"
         | 
| 196 | 
            -
            - ".travis.yml"
         | 
| 197 197 | 
             
            - CHANGELOG.md
         | 
| 198 198 | 
             
            - Gemfile
         | 
| 199 199 | 
             
            - Guardfile
         | 
| @@ -277,9 +277,9 @@ files: | |
| 277 277 | 
             
            - spec/fixtures/categories.json
         | 
| 278 278 | 
             
            - spec/fixtures/category_latest_topics.json
         | 
| 279 279 | 
             
            - spec/fixtures/category_topics.json
         | 
| 280 | 
            +
            - spec/fixtures/create_topic_with_tags.json
         | 
| 280 281 | 
             
            - spec/fixtures/email_list_all.json
         | 
| 281 282 | 
             
            - spec/fixtures/email_settings.json
         | 
| 282 | 
            -
            - spec/fixtures/generate_api_key.json
         | 
| 283 283 | 
             
            - spec/fixtures/generate_master_key.json
         | 
| 284 284 | 
             
            - spec/fixtures/group.json
         | 
| 285 285 | 
             
            - spec/fixtures/groups.json
         | 
| @@ -333,7 +333,7 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 333 333 | 
             
              requirements:
         | 
| 334 334 | 
             
              - - ">="
         | 
| 335 335 | 
             
                - !ruby/object:Gem::Version
         | 
| 336 | 
            -
                  version: 2. | 
| 336 | 
            +
                  version: 2.5.0
         | 
| 337 337 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 338 338 | 
             
              requirements:
         | 
| 339 339 | 
             
              - - ">="
         | 
| @@ -371,9 +371,9 @@ test_files: | |
| 371 371 | 
             
            - spec/fixtures/categories.json
         | 
| 372 372 | 
             
            - spec/fixtures/category_latest_topics.json
         | 
| 373 373 | 
             
            - spec/fixtures/category_topics.json
         | 
| 374 | 
            +
            - spec/fixtures/create_topic_with_tags.json
         | 
| 374 375 | 
             
            - spec/fixtures/email_list_all.json
         | 
| 375 376 | 
             
            - spec/fixtures/email_settings.json
         | 
| 376 | 
            -
            - spec/fixtures/generate_api_key.json
         | 
| 377 377 | 
             
            - spec/fixtures/generate_master_key.json
         | 
| 378 378 | 
             
            - spec/fixtures/group.json
         | 
| 379 379 | 
             
            - spec/fixtures/groups.json
         | 
    
        data/.travis.yml
    DELETED
    
    
| @@ -1,12 +0,0 @@ | |
| 1 | 
            -
            {
         | 
| 2 | 
            -
              "api_key": {
         | 
| 3 | 
            -
                "id": 5,
         | 
| 4 | 
            -
                "key": "e722e04df8cf6d097d565ca04eea1ff8e9e8f09beb405bae6f0c79852916f334",
         | 
| 5 | 
            -
                "user": {
         | 
| 6 | 
            -
                  "id": 2,
         | 
| 7 | 
            -
                  "username": "robin",
         | 
| 8 | 
            -
                  "uploaded_avatar_id": 3,
         | 
| 9 | 
            -
                  "avatar_template": "/user_avatar/localhost/robin/{size}/3.png"
         | 
| 10 | 
            -
                }
         | 
| 11 | 
            -
              }
         | 
| 12 | 
            -
            }
         |