# 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 "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