discourse_api 1.1.0 → 2.0.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +23 -10
- data/.rubocop.yml +1 -1
- data/.streerc +2 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -1
- data/README.md +0 -4
- data/discourse_api.gemspec +7 -4
- data/examples/backups.rb +5 -5
- data/examples/badges.rb +5 -5
- data/examples/bookmark_topic.rb +5 -5
- data/examples/category.rb +10 -6
- data/examples/change_topic_status.rb +12 -11
- data/examples/create_private_message.rb +6 -6
- data/examples/create_topic.rb +9 -9
- data/examples/create_update_category.rb +13 -16
- data/examples/create_user.rb +12 -11
- data/examples/dashboard.rb +5 -5
- data/examples/disposable_invite_tokens.rb +9 -10
- data/examples/example.rb +5 -5
- data/examples/group_set_user_notification_level.rb +18 -19
- data/examples/groups.rb +7 -7
- data/examples/invite_users.rb +5 -5
- data/examples/manage_api_keys.rb +6 -11
- data/examples/notifications.rb +6 -6
- data/examples/polls.rb +12 -12
- data/examples/post_action.rb +5 -5
- data/examples/search.rb +5 -5
- data/examples/sent_private_messages.rb +6 -6
- data/examples/sso.rb +6 -6
- data/examples/topic_lists.rb +5 -5
- data/examples/update_user.rb +15 -7
- data/examples/upload_file.rb +7 -7
- data/lib/discourse_api/api/api_key.rb +1 -3
- data/lib/discourse_api/api/backups.rb +1 -1
- data/lib/discourse_api/api/badges.rb +21 -6
- data/lib/discourse_api/api/categories.rb +69 -37
- data/lib/discourse_api/api/dashboard.rb +2 -6
- data/lib/discourse_api/api/groups.rb +68 -73
- data/lib/discourse_api/api/invite.rb +30 -30
- data/lib/discourse_api/api/notifications.rb +2 -3
- data/lib/discourse_api/api/params.rb +4 -14
- data/lib/discourse_api/api/polls.rb +9 -12
- data/lib/discourse_api/api/posts.rb +5 -8
- data/lib/discourse_api/api/private_messages.rb +9 -8
- data/lib/discourse_api/api/search.rb +2 -2
- data/lib/discourse_api/api/topics.rb +20 -22
- data/lib/discourse_api/api/uploads.rb +7 -5
- data/lib/discourse_api/api/user_actions.rb +2 -2
- data/lib/discourse_api/api/users.rb +31 -23
- data/lib/discourse_api/client.rb +58 -56
- data/lib/discourse_api/example_helper.rb +2 -4
- data/lib/discourse_api/single_sign_on.rb +53 -57
- data/lib/discourse_api/version.rb +1 -1
- data/spec/discourse_api/api/api_key_spec.rb +39 -25
- data/spec/discourse_api/api/backups_spec.rb +8 -3
- data/spec/discourse_api/api/badges_spec.rb +17 -7
- data/spec/discourse_api/api/categories_spec.rb +95 -53
- data/spec/discourse_api/api/email_spec.rb +17 -7
- data/spec/discourse_api/api/groups_spec.rb +71 -52
- data/spec/discourse_api/api/invite_spec.rb +41 -21
- data/spec/discourse_api/api/notifications_spec.rb +8 -4
- data/spec/discourse_api/api/params_spec.rb +5 -3
- data/spec/discourse_api/api/polls_spec.rb +53 -44
- data/spec/discourse_api/api/posts_spec.rb +33 -16
- data/spec/discourse_api/api/private_messages_spec.rb +25 -12
- data/spec/discourse_api/api/search_spec.rb +8 -3
- data/spec/discourse_api/api/site_settings_spec.rb +2 -3
- data/spec/discourse_api/api/sso_spec.rb +29 -25
- data/spec/discourse_api/api/topics_spec.rb +100 -31
- data/spec/discourse_api/api/uploads_spec.rb +16 -7
- data/spec/discourse_api/api/user_actions_spec.rb +13 -3
- data/spec/discourse_api/api/users_spec.rb +137 -55
- data/spec/discourse_api/client_spec.rb +32 -32
- data/spec/discourse_api/single_sign_on_spec.rb +15 -15
- data/spec/fixtures/categories.json +1 -1
- data/spec/spec_helper.rb +10 -15
- metadata +55 -12
@@ -8,21 +8,19 @@ module DiscourseApi
|
|
8
8
|
|
9
9
|
def user(username, params = {})
|
10
10
|
response = get("/users/#{username}.json", params)
|
11
|
-
response[:body][
|
11
|
+
response[:body]["user"]
|
12
12
|
end
|
13
13
|
|
14
14
|
def user_sso(user_id)
|
15
15
|
response = get("/admin/users/#{user_id}.json")
|
16
|
-
response[:body][
|
16
|
+
response[:body]["single_sign_on_record"]
|
17
17
|
end
|
18
18
|
|
19
19
|
def update_avatar(username, args)
|
20
|
-
args =
|
21
|
-
.optional(:file, :url)
|
22
|
-
.default(type: 'avatar', synchronous: true)
|
23
|
-
.to_h
|
20
|
+
args =
|
21
|
+
API.params(args).optional(:file, :url).default(type: "avatar", synchronous: true).to_h
|
24
22
|
upload_response = post("/uploads", args)
|
25
|
-
put("/u/#{username}/preferences/avatar/pick", upload_id: upload_response[
|
23
|
+
put("/u/#{username}/preferences/avatar/pick", upload_id: upload_response["id"])
|
26
24
|
end
|
27
25
|
|
28
26
|
def update_email(username, email)
|
@@ -30,10 +28,24 @@ module DiscourseApi
|
|
30
28
|
end
|
31
29
|
|
32
30
|
def update_user(username, args)
|
33
|
-
args =
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
args =
|
32
|
+
API
|
33
|
+
.params(args)
|
34
|
+
.optional(
|
35
|
+
:name,
|
36
|
+
:title,
|
37
|
+
:bio_raw,
|
38
|
+
:location,
|
39
|
+
:website,
|
40
|
+
:profile_background,
|
41
|
+
:card_background,
|
42
|
+
:email_messages_level,
|
43
|
+
:mailing_list_mode,
|
44
|
+
:homepage_id,
|
45
|
+
:theme_ids,
|
46
|
+
:user_fields,
|
47
|
+
)
|
48
|
+
.to_h
|
37
49
|
put("/u/#{username}", args)
|
38
50
|
end
|
39
51
|
|
@@ -42,18 +54,18 @@ module DiscourseApi
|
|
42
54
|
end
|
43
55
|
|
44
56
|
def update_trust_level(user_id, args)
|
45
|
-
args = API.params(args)
|
46
|
-
.required(:level)
|
47
|
-
.to_h
|
57
|
+
args = API.params(args).required(:level).to_h
|
48
58
|
response = put("/admin/users/#{user_id}/trust_level", args)
|
49
59
|
response[:body]
|
50
60
|
end
|
51
61
|
|
52
62
|
def create_user(args)
|
53
|
-
args =
|
54
|
-
|
55
|
-
|
56
|
-
|
63
|
+
args =
|
64
|
+
API
|
65
|
+
.params(args)
|
66
|
+
.required(:name, :email, :password, :username)
|
67
|
+
.optional(:active, :approved, :staged, :user_fields)
|
68
|
+
.to_h
|
57
69
|
post("/users", args)
|
58
70
|
end
|
59
71
|
|
@@ -61,10 +73,6 @@ module DiscourseApi
|
|
61
73
|
post("/admin/users/#{id}/log_out")
|
62
74
|
end
|
63
75
|
|
64
|
-
def invite_admin(args = {})
|
65
|
-
post("/admin/users/invite_admin", args)
|
66
|
-
end
|
67
|
-
|
68
76
|
def list_users(type, params = {})
|
69
77
|
response = get("admin/users/list/#{type}.json", params)
|
70
78
|
response[:body]
|
@@ -91,7 +99,7 @@ module DiscourseApi
|
|
91
99
|
|
92
100
|
def by_external_id(external_id)
|
93
101
|
response = get("/users/by-external/#{external_id}")
|
94
|
-
response[:body][
|
102
|
+
response[:body]["user"]
|
95
103
|
end
|
96
104
|
|
97
105
|
def suspend(user_id, suspend_until, reason)
|
data/lib/discourse_api/client.rb
CHANGED
@@ -1,29 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
23
|
-
require
|
24
|
-
require
|
25
|
-
require
|
26
|
-
require
|
2
|
+
require "faraday"
|
3
|
+
require "faraday/follow_redirects"
|
4
|
+
require "faraday/multipart"
|
5
|
+
require "json"
|
6
|
+
require "uri"
|
7
|
+
require "discourse_api/version"
|
8
|
+
require "discourse_api/api/categories"
|
9
|
+
require "discourse_api/api/search"
|
10
|
+
require "discourse_api/api/sso"
|
11
|
+
require "discourse_api/api/tags"
|
12
|
+
require "discourse_api/api/topics"
|
13
|
+
require "discourse_api/api/polls"
|
14
|
+
require "discourse_api/api/posts"
|
15
|
+
require "discourse_api/api/users"
|
16
|
+
require "discourse_api/api/groups"
|
17
|
+
require "discourse_api/api/invite"
|
18
|
+
require "discourse_api/api/private_messages"
|
19
|
+
require "discourse_api/api/notifications"
|
20
|
+
require "discourse_api/api/badges"
|
21
|
+
require "discourse_api/api/email"
|
22
|
+
require "discourse_api/api/api_key"
|
23
|
+
require "discourse_api/api/backups"
|
24
|
+
require "discourse_api/api/dashboard"
|
25
|
+
require "discourse_api/api/uploads"
|
26
|
+
require "discourse_api/api/user_actions"
|
27
|
+
require "discourse_api/api/site_settings"
|
27
28
|
|
28
29
|
module DiscourseApi
|
29
30
|
class Client
|
@@ -55,9 +56,9 @@ module DiscourseApi
|
|
55
56
|
include DiscourseApi::API::SiteSettings
|
56
57
|
|
57
58
|
def initialize(host, api_key = nil, api_username = nil)
|
58
|
-
raise ArgumentError,
|
59
|
-
@host
|
60
|
-
@api_key
|
59
|
+
raise ArgumentError, "host needs to be defined" if host.nil? || host.empty?
|
60
|
+
@host = host
|
61
|
+
@api_key = api_key
|
61
62
|
@api_username = api_username
|
62
63
|
@use_relative = check_subdirectory(host)
|
63
64
|
end
|
@@ -69,19 +70,19 @@ module DiscourseApi
|
|
69
70
|
|
70
71
|
def api_username=(api_username)
|
71
72
|
@api_username = api_username
|
72
|
-
@connection.headers[
|
73
|
+
@connection.headers["Api-Username"] = api_username unless @connection.nil?
|
73
74
|
end
|
74
75
|
|
75
76
|
def connection_options
|
76
77
|
@connection_options ||= {
|
77
78
|
url: @host,
|
78
79
|
request: {
|
79
|
-
timeout: @timeout || DEFAULT_TIMEOUT
|
80
|
+
timeout: @timeout || DEFAULT_TIMEOUT,
|
80
81
|
},
|
81
82
|
headers: {
|
82
|
-
accept:
|
83
|
+
accept: "application/json",
|
83
84
|
user_agent: user_agent,
|
84
|
-
}
|
85
|
+
},
|
85
86
|
}
|
86
87
|
end
|
87
88
|
|
@@ -126,43 +127,44 @@ module DiscourseApi
|
|
126
127
|
private
|
127
128
|
|
128
129
|
def connection
|
129
|
-
@connection ||=
|
130
|
-
|
131
|
-
|
130
|
+
@connection ||=
|
131
|
+
Faraday.new connection_options do |conn|
|
132
|
+
# Allow uploading of files
|
133
|
+
conn.request :multipart
|
132
134
|
|
133
|
-
|
134
|
-
|
135
|
+
# Convert request params to "www-form-encoded"
|
136
|
+
conn.request :url_encoded
|
135
137
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
138
|
+
# Allow to interact with forums behind basic HTTP authentication
|
139
|
+
if basic_auth
|
140
|
+
conn.request :authorization, :basic, basic_auth[:user], basic_auth[:password]
|
141
|
+
end
|
140
142
|
|
141
|
-
|
142
|
-
|
143
|
+
# Follow redirects
|
144
|
+
conn.response :follow_redirects, limit: 5
|
143
145
|
|
144
|
-
|
145
|
-
|
146
|
+
# Parse responses as JSON
|
147
|
+
conn.response :json, content_type: "application/json"
|
146
148
|
|
147
|
-
|
148
|
-
|
149
|
+
# For HTTP debugging, uncomment
|
150
|
+
# conn.response :logger
|
149
151
|
|
150
|
-
|
151
|
-
|
152
|
+
# Use Faraday's default HTTP adapter
|
153
|
+
conn.adapter Faraday.default_adapter
|
152
154
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
155
|
+
# Pass api_key and api_username on every request
|
156
|
+
unless api_username.nil?
|
157
|
+
conn.headers["Api-Key"] = api_key
|
158
|
+
conn.headers["Api-Username"] = api_username
|
159
|
+
end
|
157
160
|
end
|
158
|
-
end
|
159
161
|
end
|
160
162
|
|
161
163
|
def request(method, path, params = {})
|
162
164
|
unless Hash === params
|
163
165
|
params = params.to_h if params.respond_to? :to_h
|
164
166
|
end
|
165
|
-
path = @use_relative ? path.sub(
|
167
|
+
path = @use_relative ? path.sub(%r{^/}, "") : path
|
166
168
|
response = connection.send(method.to_sym, path, params)
|
167
169
|
handle_error(response)
|
168
170
|
response.env
|
@@ -188,7 +190,7 @@ module DiscourseApi
|
|
188
190
|
end
|
189
191
|
|
190
192
|
def check_subdirectory(host)
|
191
|
-
URI(host).request_uri !=
|
193
|
+
URI(host).request_uri != "/"
|
192
194
|
end
|
193
195
|
end
|
194
196
|
end
|
@@ -1,11 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require
|
2
|
+
require "yaml"
|
3
3
|
|
4
4
|
module DiscourseApi
|
5
5
|
class ExampleHelper
|
6
|
-
|
7
6
|
def self.load_yml
|
8
|
-
config_yml = File.expand_path(
|
7
|
+
config_yml = File.expand_path("../../../config.yml", __FILE__)
|
9
8
|
puts config_yml
|
10
9
|
begin
|
11
10
|
config = YAML.load_file config_yml
|
@@ -14,6 +13,5 @@ module DiscourseApi
|
|
14
13
|
end
|
15
14
|
config
|
16
15
|
end
|
17
|
-
|
18
16
|
end
|
19
17
|
end
|
@@ -1,52 +1,54 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
2
|
+
require "base64"
|
3
|
+
require "rack"
|
4
|
+
require "openssl"
|
5
5
|
|
6
6
|
module DiscourseApi
|
7
7
|
class SingleSignOn
|
8
|
-
class ParseError < RuntimeError
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
8
|
+
class ParseError < RuntimeError
|
9
|
+
end
|
10
|
+
class MissingConfigError < RuntimeError
|
11
|
+
end
|
12
|
+
|
13
|
+
ACCESSORS = %i[
|
14
|
+
add_groups
|
15
|
+
admin
|
16
|
+
avatar_force_update
|
17
|
+
avatar_url
|
18
|
+
bio
|
19
|
+
card_background_url
|
20
|
+
confirmed_2fa
|
21
|
+
email
|
22
|
+
external_id
|
23
|
+
groups
|
24
|
+
locale
|
25
|
+
locale_force_update
|
26
|
+
moderator
|
27
|
+
name
|
28
|
+
no_2fa_methods
|
29
|
+
nonce
|
30
|
+
profile_background_url
|
31
|
+
remove_groups
|
32
|
+
require_2fa
|
33
|
+
require_activation
|
34
|
+
return_sso_url
|
35
|
+
suppress_welcome_message
|
36
|
+
title
|
37
|
+
username
|
36
38
|
]
|
37
39
|
|
38
40
|
FIXNUMS = []
|
39
41
|
|
40
|
-
BOOLS = [
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
BOOLS = %i[
|
43
|
+
admin
|
44
|
+
avatar_force_update
|
45
|
+
confirmed_2fa
|
46
|
+
locale_force_update
|
47
|
+
moderator
|
48
|
+
no_2fa_methods
|
49
|
+
require_2fa
|
50
|
+
require_activation
|
51
|
+
suppress_welcome_message
|
50
52
|
]
|
51
53
|
ARRAYS = [:groups]
|
52
54
|
#NONCE_EXPIRY_TIME = 10.minutes # minutes is a rails method and is causing an error. Is this needed in the api?
|
@@ -72,9 +74,7 @@ module DiscourseApi
|
|
72
74
|
val = payload[k]
|
73
75
|
|
74
76
|
val = val.to_i if FIXNUMS.include? k
|
75
|
-
if BOOLS.include? k
|
76
|
-
val = ["true", "false"].include?(val) ? val == "true" : nil
|
77
|
-
end
|
77
|
+
val = %w[true false].include?(val) ? val == "true" : nil if BOOLS.include? k
|
78
78
|
val = val.split(",") if ARRAYS.include?(k) && !val.nil?
|
79
79
|
sso.send("#{k}=", val)
|
80
80
|
end
|
@@ -99,9 +99,11 @@ module DiscourseApi
|
|
99
99
|
|
100
100
|
parsed = Rack::Utils.parse_query(payload)
|
101
101
|
if sso.sign(parsed["sso"]) != parsed["sig"]
|
102
|
-
diags =
|
103
|
-
|
104
|
-
|
102
|
+
diags =
|
103
|
+
"\n\nsso: #{parsed["sso"]}\n\nsig: #{parsed["sig"]}\n\nexpected sig: #{sso.sign(parsed["sso"])}"
|
104
|
+
if parsed["sso"] =~ %r{[^a-zA-Z0-9=\r\n/+]}m
|
105
|
+
raise ParseError,
|
106
|
+
"The SSO field should be Base64 encoded, using only A-Z, a-z, 0-9, +, /, and = characters. Your input contains characters we don't understand as Base64, see http://en.wikipedia.org/wiki/Base64 #{diags}"
|
105
107
|
else
|
106
108
|
raise ParseError, "Bad signature for payload #{diags}"
|
107
109
|
end
|
@@ -113,9 +115,7 @@ module DiscourseApi
|
|
113
115
|
ACCESSORS.each do |k|
|
114
116
|
val = decoded_hash[k.to_s]
|
115
117
|
val = val.to_i if FIXNUMS.include? k
|
116
|
-
if BOOLS.include? k
|
117
|
-
val = ["true", "false"].include?(val) ? val == "true" : nil
|
118
|
-
end
|
118
|
+
val = %w[true false].include?(val) ? val == "true" : nil if BOOLS.include? k
|
119
119
|
val = val.split(",") if ARRAYS.include?(k) && !val.nil?
|
120
120
|
sso.send("#{k}=", val)
|
121
121
|
end
|
@@ -151,12 +151,12 @@ module DiscourseApi
|
|
151
151
|
|
152
152
|
def to_url(base_url = nil)
|
153
153
|
base = "#{base_url || sso_url}"
|
154
|
-
"#{base}#{base.include?(
|
154
|
+
"#{base}#{base.include?("?") ? "&" : "?"}#{payload}"
|
155
155
|
end
|
156
156
|
|
157
157
|
def payload
|
158
158
|
payload = Base64.strict_encode64(unsigned_payload)
|
159
|
-
"sso=#{CGI
|
159
|
+
"sso=#{CGI.escape(payload)}&sig=#{sign(payload)}"
|
160
160
|
end
|
161
161
|
|
162
162
|
def unsigned_payload
|
@@ -167,11 +167,7 @@ module DiscourseApi
|
|
167
167
|
payload[k] = val
|
168
168
|
end
|
169
169
|
|
170
|
-
if @custom_fields
|
171
|
-
@custom_fields.each do |k, v|
|
172
|
-
payload["custom.#{k}"] = v.to_s
|
173
|
-
end
|
174
|
-
end
|
170
|
+
@custom_fields.each { |k, v| payload["custom.#{k}"] = v.to_s } if @custom_fields
|
175
171
|
|
176
172
|
Rack::Utils.build_query(payload)
|
177
173
|
end
|
@@ -1,20 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require
|
2
|
+
require "spec_helper"
|
3
3
|
|
4
4
|
describe DiscourseApi::API::ApiKey do
|
5
|
-
subject {
|
6
|
-
DiscourseApi::Client.new(
|
7
|
-
"#{host}",
|
8
|
-
"test_d7fd0429940",
|
9
|
-
"test_user"
|
10
|
-
)
|
11
|
-
}
|
5
|
+
subject { DiscourseApi::Client.new("#{host}", "test_d7fd0429940", "test_user") }
|
12
6
|
|
13
7
|
describe "#list_api_keys" do
|
14
8
|
before do
|
15
9
|
url = "#{host}/admin/api/keys"
|
16
|
-
stub_get(url).to_return(
|
17
|
-
|
10
|
+
stub_get(url).to_return(
|
11
|
+
body: fixture("list_api_keys.json"),
|
12
|
+
headers: {
|
13
|
+
content_type: "application/json",
|
14
|
+
},
|
15
|
+
)
|
18
16
|
end
|
19
17
|
|
20
18
|
it "requests the correct resource" do
|
@@ -27,35 +25,43 @@ describe DiscourseApi::API::ApiKey do
|
|
27
25
|
keys = subject.list_api_keys
|
28
26
|
expect(keys["keys"]).to be_an Array
|
29
27
|
expect(keys["keys"].first).to be_a Hash
|
30
|
-
expect(keys["keys"].first).to have_key(
|
28
|
+
expect(keys["keys"].first).to have_key("key")
|
31
29
|
end
|
32
30
|
end
|
33
31
|
|
34
32
|
describe "#create_api_key" do
|
35
33
|
before do
|
36
34
|
url = "#{host}/admin/api/keys"
|
37
|
-
stub_post(url).to_return(
|
38
|
-
|
35
|
+
stub_post(url).to_return(
|
36
|
+
body: fixture("api_key.json"),
|
37
|
+
headers: {
|
38
|
+
content_type: "application/json",
|
39
|
+
},
|
40
|
+
)
|
39
41
|
end
|
40
42
|
|
41
43
|
it "requests the correct resource" do
|
42
|
-
subject.create_api_key(key: { username:
|
44
|
+
subject.create_api_key(key: { username: "robin" })
|
43
45
|
url = "#{host}/admin/api/keys"
|
44
46
|
expect(a_post(url)).to have_been_made
|
45
47
|
end
|
46
48
|
|
47
49
|
it "returns the generated api key" do
|
48
|
-
api_key = subject.create_api_key(key: { username:
|
50
|
+
api_key = subject.create_api_key(key: { username: "robin" })
|
49
51
|
expect(api_key).to be_a Hash
|
50
|
-
expect(api_key[
|
52
|
+
expect(api_key["key"]).to have_key("key")
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
54
56
|
describe "#revoke_api_key" do
|
55
57
|
before do
|
56
58
|
url = "#{host}/admin/api/keys/10/revoke"
|
57
|
-
stub_post(url).to_return(
|
58
|
-
|
59
|
+
stub_post(url).to_return(
|
60
|
+
body: fixture("api_key.json"),
|
61
|
+
headers: {
|
62
|
+
content_type: "application/json",
|
63
|
+
},
|
64
|
+
)
|
59
65
|
end
|
60
66
|
|
61
67
|
it "requests the correct resource" do
|
@@ -66,15 +72,19 @@ describe DiscourseApi::API::ApiKey do
|
|
66
72
|
|
67
73
|
it "returns the api key" do
|
68
74
|
api_key = subject.revoke_api_key(10)
|
69
|
-
expect(api_key[
|
75
|
+
expect(api_key["key"]).to have_key("key")
|
70
76
|
end
|
71
77
|
end
|
72
78
|
|
73
79
|
describe "#undo_revoke_api_key" do
|
74
80
|
before do
|
75
81
|
url = "#{host}/admin/api/keys/10/undo-revoke"
|
76
|
-
stub_post(url).to_return(
|
77
|
-
|
82
|
+
stub_post(url).to_return(
|
83
|
+
body: fixture("api_key.json"),
|
84
|
+
headers: {
|
85
|
+
content_type: "application/json",
|
86
|
+
},
|
87
|
+
)
|
78
88
|
end
|
79
89
|
|
80
90
|
it "requests the correct resource" do
|
@@ -85,15 +95,19 @@ describe DiscourseApi::API::ApiKey do
|
|
85
95
|
|
86
96
|
it "returns the api key" do
|
87
97
|
api_key = subject.undo_revoke_api_key(10)
|
88
|
-
expect(api_key[
|
98
|
+
expect(api_key["key"]).to have_key("key")
|
89
99
|
end
|
90
100
|
end
|
91
101
|
|
92
102
|
describe "#delete_api_key" do
|
93
103
|
before do
|
94
104
|
url = "#{host}/admin/api/keys/10"
|
95
|
-
stub_delete(url).to_return(
|
96
|
-
|
105
|
+
stub_delete(url).to_return(
|
106
|
+
body: '{"success": "OK"}',
|
107
|
+
headers: {
|
108
|
+
content_type: "application/json",
|
109
|
+
},
|
110
|
+
)
|
97
111
|
end
|
98
112
|
|
99
113
|
it "requests the correct resource" do
|
@@ -104,7 +118,7 @@ describe DiscourseApi::API::ApiKey do
|
|
104
118
|
|
105
119
|
it "returns 200" do
|
106
120
|
response = subject.delete_api_key(10)
|
107
|
-
expect(response[
|
121
|
+
expect(response["status"]).to eq(200)
|
108
122
|
end
|
109
123
|
end
|
110
124
|
end
|
@@ -1,12 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require
|
2
|
+
require "spec_helper"
|
3
3
|
|
4
4
|
describe DiscourseApi::API::Backups do
|
5
5
|
subject { DiscourseApi::Client.new("#{host}", "test_d7fd0429940", "test_user") }
|
6
6
|
|
7
7
|
describe "#backups" do
|
8
8
|
before do
|
9
|
-
stub_get("#{host}/admin/backups.json").to_return(
|
9
|
+
stub_get("#{host}/admin/backups.json").to_return(
|
10
|
+
body: fixture("backups.json"),
|
11
|
+
headers: {
|
12
|
+
content_type: "application/json",
|
13
|
+
},
|
14
|
+
)
|
10
15
|
end
|
11
16
|
|
12
17
|
it "requests the correct resource" do
|
@@ -18,7 +23,7 @@ describe DiscourseApi::API::Backups do
|
|
18
23
|
backups = subject.backups
|
19
24
|
expect(backups).to be_an Array
|
20
25
|
expect(backups.first).to be_a Hash
|
21
|
-
expect(backups.first).to have_key(
|
26
|
+
expect(backups.first).to have_key("filename")
|
22
27
|
end
|
23
28
|
end
|
24
29
|
end
|