DEV: Introduce plugin API to contribute user api key scopes
This commit is contained in:
parent
23e5c605f6
commit
b7c680853d
|
@ -17,7 +17,11 @@ class UserApiKeyScope < ActiveRecord::Base
|
|||
}
|
||||
|
||||
def self.all_scopes
|
||||
SCOPES
|
||||
scopes = SCOPES
|
||||
DiscoursePluginRegistry.user_api_key_scope_mappings.each do |mapping|
|
||||
scopes = scopes.merge!(mapping)
|
||||
end
|
||||
scopes
|
||||
end
|
||||
|
||||
def permits?(env)
|
||||
|
|
|
@ -81,6 +81,7 @@ class DiscoursePluginRegistry
|
|||
|
||||
define_filtered_register :api_parameter_routes
|
||||
define_filtered_register :api_key_scope_mappings
|
||||
define_filtered_register :user_api_key_scope_mappings
|
||||
|
||||
define_filtered_register :permitted_bulk_action_parameters
|
||||
|
||||
|
|
|
@ -793,6 +793,35 @@ class Plugin::Instance
|
|||
DiscoursePluginRegistry.register_api_key_scope_mapping({ resource => action }, self)
|
||||
end
|
||||
|
||||
# Register a new UserApiKey scope, and its allowed routes. Scope will be prefixed
|
||||
# with the (parametetized) plugin name followed by a colon.
|
||||
#
|
||||
# For example, if discourse-awesome-plugin registered this:
|
||||
#
|
||||
# add_user_api_key_scope(:read_my_route,
|
||||
# methods: :get,
|
||||
# actions: "mycontroller#myaction",
|
||||
# formats: :ics,
|
||||
# parameters: :testparam
|
||||
# )
|
||||
#
|
||||
# The scope registered would be `discourse-awesome-plugin:read_my_route`
|
||||
#
|
||||
# Multiple matchers can be attached by supplying an array of parameter hashes
|
||||
#
|
||||
# See UserApiKeyScope::SCOPES for more examples
|
||||
# And lib/route_matcher.rb for the route matching logic
|
||||
def add_user_api_key_scope(scope_name, matcher_parameters)
|
||||
raise ArgumentError.new("scope_name must be a symbol") if !scope_name.is_a?(Symbol)
|
||||
matcher_parameters = [matcher_parameters] if !matcher_parameters.is_a?(Array)
|
||||
|
||||
prefixed_scope_name = :"#{(name || directory_name).parameterize}:#{scope_name}"
|
||||
DiscoursePluginRegistry.register_user_api_key_scope_mapping(
|
||||
{
|
||||
prefixed_scope_name => matcher_parameters&.map { |m| RouteMatcher.new(**m) }
|
||||
}, self)
|
||||
end
|
||||
|
||||
# Register a route which can be authenticated using an api key or user api key
|
||||
# in a query parameter rather than a header. For example:
|
||||
#
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Fabricator(:user_api_key) do
|
||||
user
|
||||
client_id { SecureRandom.hex }
|
||||
application_name 'some app'
|
||||
end
|
||||
|
||||
Fabricator(:user_api_key_scope)
|
||||
|
||||
Fabricator(:readonly_user_api_key, from: :user_api_key) do
|
||||
user
|
||||
scopes { [Fabricate.build(:user_api_key_scope, name: 'read')] }
|
||||
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
|
||||
|
|
|
@ -128,4 +128,24 @@ describe 'user api keys' do
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue