mirror of
https://github.com/discourse/discourse.git
synced 2026-08-06 13:08:40 +08:00
This ensures that the parameters stored include the method, that way there is no caching collision between different methods.
159 lines
5.4 KiB
Ruby
Vendored
159 lines
5.4 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe "api keys" do
|
|
let(:user) { Fabricate(:user) }
|
|
let(:api_key) { ApiKey.create!(user_id: user.id, created_by_id: Discourse.system_user) }
|
|
|
|
it "works in headers" do
|
|
get "/session/current.json", headers: { HTTP_API_KEY: api_key.key }
|
|
expect(response.status).to eq(200)
|
|
expect(response.parsed_body["current_user"]["username"]).to eq(user.username)
|
|
end
|
|
|
|
it "does not work in parameters" do
|
|
get "/session/current.json", params: { api_key: api_key.key }
|
|
expect(response.status).to eq(404)
|
|
end
|
|
|
|
it "does not allow overloaded requests to bypass granular API key scopes" do
|
|
global_setting :reject_anonymous_min_queue_seconds, 1.0
|
|
|
|
admin = Fabricate(:admin)
|
|
topic = Fabricate(:topic)
|
|
Fabricate(:post, topic: topic)
|
|
scoped_api_key =
|
|
Fabricate(
|
|
:api_key,
|
|
user: admin,
|
|
api_key_scopes: [Fabricate.build(:api_key_scope, resource: "topics", action: "read")],
|
|
)
|
|
|
|
put "/t/#{topic.id}.json",
|
|
params: {
|
|
title: "This is an unauthorized title change",
|
|
},
|
|
headers: {
|
|
HTTP_API_KEY: scoped_api_key.key,
|
|
HTTP_X_REQUEST_START: "t=0",
|
|
}
|
|
|
|
expect(response.status).to eq(503)
|
|
expect(response.body).to eq(
|
|
"Server is currently experiencing high load. Please try again later.",
|
|
)
|
|
expect(topic.reload.title).not_to eq("This is an unauthorized title change")
|
|
end
|
|
|
|
it "allows parameters on ics routes" do
|
|
get "/u/#{user.username}/bookmarks.ics?api_key=#{api_key.key}&api_username=#{user.username.downcase}"
|
|
expect(response.status).to eq(200)
|
|
|
|
# Confirm not for JSON
|
|
get "/u/#{user.username}/bookmarks.json?api_key=#{api_key.key}&api_username=#{user.username.downcase}"
|
|
expect(response.status).to eq(403)
|
|
end
|
|
|
|
it "allows parameters for handle mail" do
|
|
admin_api_key = ApiKey.create!(user: Fabricate(:admin), created_by_id: Discourse.system_user)
|
|
|
|
post "/admin/email/handle_mail.json?api_key=#{admin_api_key.key}", params: { email: "blah" }
|
|
expect(response.status).to eq(200)
|
|
end
|
|
|
|
it "allows parameters for rss feeds" do
|
|
SiteSetting.login_required = true
|
|
|
|
get "/latest.rss?api_key=#{api_key.key}&api_username=#{user.username.downcase}"
|
|
expect(response.status).to eq(200)
|
|
|
|
# Confirm not allowed for json
|
|
get "/latest.json?api_key=#{api_key.key}&api_username=#{user.username.downcase}"
|
|
expect(response.status).to eq(403)
|
|
end
|
|
|
|
context "with a plugin registered filter" do
|
|
before do
|
|
plugin = Plugin::Instance.new
|
|
plugin.add_api_parameter_route methods: [:get], actions: ["session#current"]
|
|
end
|
|
|
|
it "allows parameter access to the registered route" do
|
|
get "/session/current.json", params: { api_key: api_key.key }
|
|
expect(response.status).to eq(200)
|
|
end
|
|
end
|
|
end
|
|
|
|
RSpec.describe "user api keys" do
|
|
let(:user) { Fabricate(:user) }
|
|
let(:user_api_key) { Fabricate(:readonly_user_api_key, user: user) }
|
|
|
|
it "updates last used time on use" do
|
|
freeze_time
|
|
|
|
user_api_key.update_columns(last_used_at: 7.days.ago)
|
|
|
|
get "/session/current.json", headers: { HTTP_USER_API_KEY: user_api_key.key }
|
|
|
|
expect(user_api_key.reload.last_used_at).to eq_time(Time.zone.now)
|
|
end
|
|
|
|
it "allows parameters on ics routes" do
|
|
get "/u/#{user.username}/bookmarks.ics?user_api_key=#{user_api_key.key}"
|
|
expect(response.status).to eq(200)
|
|
|
|
# Confirm not for JSON
|
|
get "/u/#{user.username}/bookmarks.json?user_api_key=#{user_api_key.key}"
|
|
expect(response.status).to eq(403)
|
|
end
|
|
|
|
it "allows parameters for rss feeds" do
|
|
SiteSetting.login_required = true
|
|
|
|
get "/latest.rss?user_api_key=#{user_api_key.key}"
|
|
expect(response.status).to eq(200)
|
|
|
|
# Confirm not allowed for json
|
|
get "/latest.json?user_api_key=#{user_api_key.key}"
|
|
expect(response.status).to eq(403)
|
|
end
|
|
|
|
it "can restrict scopes by parameters" do
|
|
admin = Fabricate(:admin)
|
|
|
|
calendar_key = Fabricate(:bookmarks_calendar_user_api_key, user: admin)
|
|
|
|
get "/u/#{user.username}/bookmarks.json", headers: { HTTP_USER_API_KEY: calendar_key.key }
|
|
expect(response.status).to eq(403) # Does not allow json
|
|
|
|
get "/u/#{user.username}/bookmarks.ics", headers: { HTTP_USER_API_KEY: calendar_key.key }
|
|
expect(response.status).to eq(200) # Allows ICS
|
|
|
|
# Now restrict the key
|
|
calendar_key.scopes.first.update(allowed_parameters: { username: admin.username })
|
|
|
|
get "/u/#{user.username}/bookmarks.ics", headers: { HTTP_USER_API_KEY: calendar_key.key }
|
|
expect(response.status).to eq(403) # Cannot access another users calendar
|
|
|
|
get "/u/#{admin.username}/bookmarks.ics", headers: { HTTP_USER_API_KEY: calendar_key.key }
|
|
expect(response.status).to eq(200) # Can access own calendar
|
|
end
|
|
|
|
context "with a plugin registered user api key scope" do
|
|
let(:user_api_key) { Fabricate(:user_api_key) }
|
|
|
|
before do
|
|
metadata = Plugin::Metadata.new
|
|
metadata.name = "My Amazing Plugin"
|
|
plugin = Plugin::Instance.new metadata
|
|
plugin.add_user_api_key_scope :my_magic_scope, methods: :get, actions: "session#current"
|
|
user_api_key.scopes = [UserApiKeyScope.new(name: "my-amazing-plugin:my_magic_scope")]
|
|
user_api_key.save!
|
|
end
|
|
|
|
it "allows parameter access to the registered route" do
|
|
get "/session/current.json", headers: { HTTP_USER_API_KEY: user_api_key.key }
|
|
expect(response.status).to eq(200)
|
|
end
|
|
end
|
|
end
|