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 +4 -4
- data/.github/workflows/ci.yml +54 -0
- data/.gitignore +0 -2
- data/CHANGELOG.md +11 -6
- data/README.md +13 -1
- data/discourse_api.gemspec +2 -2
- data/lib/discourse_api/api/api_key.rb +0 -8
- data/lib/discourse_api/api/sso.rb +1 -18
- data/lib/discourse_api/client.rb +16 -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
- metadata +7 -9
- 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: e8e19227c879502b171c001c16ecef5ba35e1aa97db19430c30bf35cc7fe6bf0
|
4
|
+
data.tar.gz: 94571b5d801c0c89e18768bee1182f5d37114bb2e3b06e6665ace17e9acb001e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
data/CHANGELOG.md
CHANGED
@@ -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
|
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'
|
@@ -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.
|
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
|
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
|
@@ -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.
|
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
|
-
|
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
|
@@ -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
|
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.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-
|
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
|
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
|
@@ -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
|
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
|
-
}
|