discourse_api 0.40.0 → 0.41.0

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