discourse_api 0.39.3 → 0.43.1

Sign up to get free protection for your applications and to get access to all the features.
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