discourse_api 0.40.0 → 0.41.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f12aa5327c6d59b3d258745ef391b3ce97da58367cd0056b7513735a6a530d42
4
- data.tar.gz: f8b5f8eca097239993c8553bb0de9f3a1ec70348d511c16304e8586a0eda2e9e
3
+ metadata.gz: e8e19227c879502b171c001c16ecef5ba35e1aa97db19430c30bf35cc7fe6bf0
4
+ data.tar.gz: 94571b5d801c0c89e18768bee1182f5d37114bb2e3b06e6665ace17e9acb001e
5
5
  SHA512:
6
- metadata.gz: 31f454b2b7b8ea518a03298fbcd179b5ecd7d4463a68ca574f081c7f6b261093bb2ffa10ea01ab752d281f33e2c028d56a639342e30481c9227dc7603467d840
7
- data.tar.gz: 852e2a8aa5082f3850fbfd6e404d71a5d3a074c613305d0018c6d1b3c735182a45295043784954a8fd0a9d25caea585c87092971c9c5db730d6f60f67b3b67fc
6
+ metadata.gz: 32a0f6371f096dff33f1a71ab200d36824ca4a22f49500f7e06c5f245b53073215f3ae11b2410d11ca0a0a94c8d23546bb66faf48727c0bc241c689fd41795a6
7
+ data.tar.gz: 857e1f6535a4d1a49369101e351950f4c393b5f502f2dd7499874347b326b7731a761a97a6f0301b2b97cb64017bc5908bd7505642cb1c6e3524597299ab43fa
@@ -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
@@ -2,6 +2,16 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
+ ## [0.41.0] - 2020-06-17
6
+ ### Added
7
+ - Add basic auth support
8
+
9
+ ### Fixed
10
+ - Fix SSO custom field prefixes
11
+
12
+ ### Removed
13
+ - Obsolete api key endpoints
14
+
5
15
  ## [0.40.0] - 2020-05-07
6
16
  ### Fixed
7
17
  - Add missing attributes to `sync_sso`
@@ -224,7 +234,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
224
234
  ## [0.8.1] - 2016-03-03
225
235
  ### Fixed
226
236
  - enable use of discourse_api to make unauthenticated requests to discourse
227
- endpoints like /categories and /topics
237
+ endpoints like /categories and /topics
228
238
 
229
239
  ## [0.8.0] - 2016-02-28
230
240
  ### Added
@@ -281,8 +291,3 @@ This project adheres to [Semantic Versioning](http://semver.org/).
281
291
  ## [0.1.2] - 2014-05-11
282
292
 
283
293
  - Release
284
-
285
-
286
-
287
-
288
-
data/README.md CHANGED
@@ -52,7 +52,10 @@ client.sync_sso( #=> Synchronizes the SSO record
52
52
  name: "Test Name",
53
53
  username: "test_name",
54
54
  email: "name@example.com",
55
- external_id: "2"
55
+ external_id: "2",
56
+ custom_fields: {
57
+ field_1: 'potato'
58
+ }
56
59
  )
57
60
 
58
61
  # Private messages
@@ -80,6 +83,15 @@ end
80
83
 
81
84
  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
85
 
86
+ If your forum has a basic HTTP authentication enabled, set user and password:
87
+
88
+ ```ruby
89
+ client.basic_auth = {
90
+ user: "test",
91
+ password: "secret"
92
+ }
93
+ ```
94
+
83
95
  ## Contributing
84
96
 
85
97
  1. Fork it
@@ -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.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'
@@ -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
@@ -3,24 +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.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
@@ -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
@@ -112,19 +113,30 @@ module DiscourseApi
112
113
 
113
114
  def connection
114
115
  @connection ||= Faraday.new connection_options do |conn|
115
- # Follow redirects
116
- conn.use FaradayMiddleware::FollowRedirects, limit: 5
117
116
  # Allow uploading of files
118
117
  conn.request :multipart
118
+
119
119
  # Convert request params to "www-form-encoded"
120
120
  conn.request :url_encoded
121
+
122
+ # Allow to interact with forums behind basic HTTP authentication
123
+ if basic_auth
124
+ conn.request :basic_auth, basic_auth[:user], basic_auth[:password]
125
+ end
126
+
127
+ # Follow redirects
128
+ conn.response :follow_redirects, limit: 5
129
+
121
130
  # Parse responses as JSON
122
- conn.use FaradayMiddleware::ParseJson, content_type: 'application/json'
131
+ conn.response :json, content_type: 'application/json'
132
+
123
133
  # For HTTP debugging, uncomment
124
134
  # conn.response :logger
135
+
125
136
  # Use Faraday's default HTTP adapter
126
137
  conn.adapter Faraday.default_adapter
127
- #pass api_key and api_username on every request
138
+
139
+ # Pass api_key and api_username on every request
128
140
  unless api_username.nil?
129
141
  conn.headers['Api-Key'] = api_key
130
142
  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
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module DiscourseApi
3
- VERSION = "0.40.0"
3
+ VERSION = "0.41.0"
4
4
  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(body: fixture("user.json"), headers: { content_type: "application/json" })
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
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.40.0
4
+ version: 0.41.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-05-07 00:00:00.000000000 Z
14
+ date: 2020-06-17 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.9'
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.9'
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.10'
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.10'
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
@@ -279,7 +279,6 @@ files:
279
279
  - spec/fixtures/category_topics.json
280
280
  - spec/fixtures/email_list_all.json
281
281
  - spec/fixtures/email_settings.json
282
- - spec/fixtures/generate_api_key.json
283
282
  - spec/fixtures/generate_master_key.json
284
283
  - spec/fixtures/group.json
285
284
  - spec/fixtures/groups.json
@@ -373,7 +372,6 @@ test_files:
373
372
  - spec/fixtures/category_topics.json
374
373
  - spec/fixtures/email_list_all.json
375
374
  - spec/fixtures/email_settings.json
376
- - spec/fixtures/generate_api_key.json
377
375
  - spec/fixtures/generate_master_key.json
378
376
  - spec/fixtures/group.json
379
377
  - spec/fixtures/groups.json
@@ -1,11 +0,0 @@
1
- language: 'ruby'
2
-
3
- before_install:
4
- - 'gem update --system'
5
- - 'gem install bundler'
6
-
7
- rvm:
8
- - '2.5.5'
9
- - '2.6.2'
10
-
11
- script: 'bundle exec rake'
@@ -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
- }