DEV: Add support for allowed parameters in user api key scopes

Initially, this feature is only intended for use in core/plugins, so there is no API for requesting a parameter-scoped key. That may change in future.
This commit is contained in:
David Taylor 2020-10-08 17:38:54 +01:00
parent 1cec333f48
commit 23e5c605f6
5 changed files with 53 additions and 7 deletions

View File

@ -12,7 +12,8 @@ class UserApiKeyScope < ActiveRecord::Base
RouteMatcher.new(methods: :get, actions: 'notifications#index'),
RouteMatcher.new(methods: :put, actions: 'notifications#mark_read')
],
session_info: [ RouteMatcher.new(methods: :get, actions: 'session#current') ]
session_info: [ RouteMatcher.new(methods: :get, actions: 'session#current') ],
bookmarks_calendar: [ RouteMatcher.new(methods: :get, actions: 'users#bookmarks', formats: :ics, params: %i[username]) ]
}
def self.all_scopes
@ -20,7 +21,7 @@ class UserApiKeyScope < ActiveRecord::Base
end
def permits?(env)
matchers.any? { |m| m.match?(env: env) }
matchers.any? { |m| m.with_allowed_param_values(allowed_parameters).match?(env: env) }
end
private
@ -40,6 +41,7 @@ end
# name :string not null
# created_at :datetime not null
# updated_at :datetime not null
# allowed_parameters :jsonb
#
# Indexes
#

View File

@ -1049,6 +1049,7 @@ en:
read: "Read all"
write: "Write all"
one_time_password: "Create a one-time login token"
bookmarks_calendar: "Read bookmark reminders"
invalid_public_key: "Sorry, the public key is invalid."
invalid_auth_redirect: "Sorry, this auth_redirect host is not allowed."
invalid_token: "Missing, invalid or expired token."

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddAllowedParametersToUserApiKeyScope < ActiveRecord::Migration[6.0]
def change
add_column :user_api_key_scopes, :allowed_parameters, :jsonb
end
end

View File

@ -8,3 +8,10 @@ Fabricator(:readonly_user_api_key, from: :user_api_key) do
client_id { SecureRandom.hex }
application_name 'some app'
end
Fabricator(:bookmarks_calendar_user_api_key, from: :user_api_key) do
user
scopes { [Fabricate.build(:user_api_key_scope, name: 'bookmarks_calendar')] }
client_id { SecureRandom.hex }
application_name 'some app'
end

View File

@ -99,4 +99,33 @@ describe 'user api keys' do
expect(response.status).to eq(302)
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
end