discourse_api 0.39.3 → 0.43.1

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +54 -0
  3. data/.gitignore +0 -2
  4. data/.rubocop.yml +2 -6
  5. data/CHANGELOG.md +40 -8
  6. data/README.md +13 -2
  7. data/discourse_api.gemspec +4 -6
  8. data/examples/change_topic_status.rb +3 -4
  9. data/examples/create_topic.rb +10 -0
  10. data/lib/discourse_api/api/api_key.rb +0 -8
  11. data/lib/discourse_api/api/categories.rb +5 -0
  12. data/lib/discourse_api/api/groups.rb +10 -2
  13. data/lib/discourse_api/api/sso.rb +1 -15
  14. data/lib/discourse_api/api/topics.rb +8 -2
  15. data/lib/discourse_api/client.rb +20 -4
  16. data/lib/discourse_api/single_sign_on.rb +32 -3
  17. data/lib/discourse_api/version.rb +1 -1
  18. data/spec/discourse_api/api/api_key_spec.rb +2 -28
  19. data/spec/discourse_api/api/backups_spec.rb +2 -1
  20. data/spec/discourse_api/api/badges_spec.rb +2 -1
  21. data/spec/discourse_api/api/categories_spec.rb +9 -8
  22. data/spec/discourse_api/api/email_spec.rb +2 -1
  23. data/spec/discourse_api/api/groups_spec.rb +7 -6
  24. data/spec/discourse_api/api/notifications_spec.rb +1 -0
  25. data/spec/discourse_api/api/params_spec.rb +8 -7
  26. data/spec/discourse_api/api/polls_spec.rb +7 -6
  27. data/spec/discourse_api/api/posts_spec.rb +1 -0
  28. data/spec/discourse_api/api/private_messages_spec.rb +1 -0
  29. data/spec/discourse_api/api/search_spec.rb +4 -3
  30. data/spec/discourse_api/api/site_settings_spec.rb +2 -1
  31. data/spec/discourse_api/api/sso_spec.rb +46 -3
  32. data/spec/discourse_api/api/topics_spec.rb +20 -1
  33. data/spec/discourse_api/api/uploads_spec.rb +1 -0
  34. data/spec/discourse_api/api/user_actions_spec.rb +1 -0
  35. data/spec/discourse_api/api/users_spec.rb +4 -3
  36. data/spec/discourse_api/client_spec.rb +11 -10
  37. data/spec/fixtures/create_topic_with_tags.json +65 -0
  38. data/spec/spec_helper.rb +2 -1
  39. metadata +17 -45
  40. data/.travis.yml +0 -11
  41. data/spec/fixtures/generate_api_key.json +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 63578af46fcacce36a692c7ce114e8cdb4b2afda23a0a6cef310b87c44518b84
4
- data.tar.gz: 11fcf8ac8482d0b06fba04c7adad7567d5ea2e111d9b8a7d6a19eddfb289b1b4
3
+ metadata.gz: a5b33f1f16a6fe2c48d58ec9b08ed6146789653b4a6c055a1ec7e61d3ec7fee0
4
+ data.tar.gz: e483916abc304970ac78192ecb0cc1c1ca2b58f1fdac0ea06eec4cdaa624e4ba
5
5
  SHA512:
6
- metadata.gz: 004cc6e682e7bf6851565716884448a4a107e8fd6722573f6410ef75b512e13957c1a5226c96b2de53a15ee984335eb774897e9461912d7d095173310a3bfd17
7
- data.tar.gz: 06abab5f8ac458c2ef607e4bac26bb46fc17a689a0a32b108ffe293c92bf59851f19e6937d7a2dc3e9351923dd96e54016032bda492660f60c8d995ae499748b
6
+ metadata.gz: 118c45cb081fa47d0fd3120c6dfa10b35b169d6620ea3875481a3f4c390ae269cc82b6b234fbe1ef1e7250dd2e7d9a7ab5023e2b3046b22a41de8249fb04607d
7
+ data.tar.gz: 1ba2f1ee7853b5a65406863bd404d04ef4866a3e7e5164c393f91ef1a7e02a9e1828fc7606957eb18b13db6f58ea3fff59e4e23cf89d44d8c7c7c590ba90a3fd
@@ -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
@@ -20,5 +20,3 @@ bin/
20
20
  .ruby-version
21
21
  .env
22
22
  /config.yml
23
-
24
- .rubocop-https---raw-githubusercontent-com-discourse-discourse-master--rubocop-yml
@@ -1,6 +1,2 @@
1
- inherit_from: https://raw.githubusercontent.com/discourse/discourse/master/.rubocop.yml
2
- AllCops:
3
- TargetRubyVersion: 2.4
4
- DisabledByDefault: true
5
- Exclude:
6
- - 'spec/**/**/*.rb'
1
+ inherit_gem:
2
+ rubocop-discourse: default.yml
@@ -1,6 +1,43 @@
1
- # Change Log
1
+ # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
- This project adheres to [Semantic Versioning](http://semver.org/).
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.43.1] - 2020-11-04
10
+ ### Fixed
11
+ - tagged verion 0.43.0 got pushed without commmit due to new master branch
12
+ protections in github. No, code changes here just making sure tags align with
13
+ commits.
14
+
15
+ ## [0.43.0] - 2020-11-04
16
+ ### Added
17
+ - Add pagination to list groups endpoint
18
+ ### Deprecated
19
+ - `change_topic_status` has been deprecated, use `update_topic_status` instead.
20
+
21
+ ## [0.42.0] - 2020-07-09
22
+ ### Added
23
+ - Create topics with tags
24
+
25
+ ## [0.41.0] - 2020-06-17
26
+ ### Added
27
+ - Add basic auth support
28
+
29
+ ### Fixed
30
+ - Fix SSO custom field prefixes
31
+
32
+ ### Removed
33
+ - Obsolete api key endpoints
34
+
35
+ ## [0.40.0] - 2020-05-07
36
+ ### Fixed
37
+ - Add missing attributes to `sync_sso`
38
+
39
+ ### Added
40
+ - Add delete category method
4
41
 
5
42
  ## [0.39.3] - 2020-04-30
6
43
  ### Fixed
@@ -217,7 +254,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
217
254
  ## [0.8.1] - 2016-03-03
218
255
  ### Fixed
219
256
  - enable use of discourse_api to make unauthenticated requests to discourse
220
- endpoints like /categories and /topics
257
+ endpoints like /categories and /topics
221
258
 
222
259
  ## [0.8.0] - 2016-02-28
223
260
  ### Added
@@ -274,8 +311,3 @@ This project adheres to [Semantic Versioning](http://semver.org/).
274
311
  ## [0.1.2] - 2014-05-11
275
312
 
276
313
  - Release
277
-
278
-
279
-
280
-
281
-
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
@@ -18,21 +18,19 @@ 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.9'
22
- spec.add_dependency 'faraday_middleware', '~> 0.10'
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'
26
26
  spec.add_development_dependency 'guard', '~> 2.14'
27
27
  spec.add_development_dependency 'guard-rspec', '~> 4.7'
28
- spec.add_development_dependency 'rake', '~> 11.1'
28
+ spec.add_development_dependency 'rake', '>= 12.3.3'
29
29
  spec.add_development_dependency 'rb-inotify', '~> 0.9'
30
30
  spec.add_development_dependency 'rspec', '~> 3.4'
31
- spec.add_development_dependency 'rubocop', '~> 0.69'
32
31
  spec.add_development_dependency 'simplecov', '~> 0.11'
33
32
  spec.add_development_dependency 'webmock', '~> 2.0'
34
- spec.add_development_dependency 'rubocop-discourse', '~> 1.0'
35
- spec.add_development_dependency 'rubocop-rspec', '~> 1.0'
33
+ spec.add_development_dependency 'rubocop-discourse'
36
34
 
37
35
  spec.required_ruby_version = '>= 2.2.3'
38
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 and topic_slug from response
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(topic_slug, topic_id, params)
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(topic_slug, topic_id, params)
34
+ client.change_topic_status(topic_id, params)
@@ -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
@@ -28,6 +28,11 @@ module DiscourseApi
28
28
  response['body']['category'] if response['body']
29
29
  end
30
30
 
31
+ def delete_category(id)
32
+ response = delete("/categories/#{id}")
33
+ response[:body]['success']
34
+ end
35
+
31
36
  def categories(params = {})
32
37
  response = get('/categories.json', params)
33
38
  response[:body]['category_list']['categories']
@@ -60,8 +60,16 @@ module DiscourseApi
60
60
  put("/groups/#{group_id}", group: args)
61
61
  end
62
62
 
63
- def groups
64
- response = get("/groups.json")
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,21 +3,7 @@ module DiscourseApi
3
3
  module API
4
4
  module SSO
5
5
  def sync_sso(params = {})
6
- sso = DiscourseApi::SingleSignOn.new
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.title = params[:title]
15
- sso.avatar_force_update = params[:avatar_force_update] === true
16
- sso.add_groups = params[:add_groups]
17
- sso.remove_groups = params[:remove_groups]
18
- params.keys.select { |key| key.to_s.start_with?("custom") }.each do |custom_key|
19
- sso.custom_fields[custom_key] = params[custom_key]
20
- end
6
+ sso = DiscourseApi::SingleSignOn.parse_hash(params)
21
7
 
22
8
  post("/admin/users/sync_sso", sso.payload)
23
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.to_h)
55
+ put("/t/#{topic_id}/status", params)
50
56
  end
51
57
 
52
58
  def topic(id, params = {})
@@ -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.use FaradayMiddleware::ParseJson, content_type: 'application/json'
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
- #pass api_key and api_username on every request
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
@@ -5,7 +5,7 @@ require 'openssl'
5
5
 
6
6
  module DiscourseApi
7
7
  class SingleSignOn
8
- ACCESSORS = [:nonce, :name, :username, :email, :avatar_url, :avatar_force_update, :require_activation,
8
+ ACCESSORS = [:nonce, :name, :username, :email, :avatar_url, :profile_background_url, :card_background_url, :avatar_force_update, :require_activation,
9
9
  :bio, :external_id, :return_sso_url, :admin, :moderator, :suppress_welcome_message, :title,
10
10
  :add_groups, :remove_groups, :groups, :locale, :locale_force_update]
11
11
  FIXNUMS = []
@@ -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