mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
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
|
def self.all_scopes
|
||||||
SCOPES
|
scopes = SCOPES
|
||||||
|
DiscoursePluginRegistry.user_api_key_scope_mappings.each do |mapping|
|
||||||
|
scopes = scopes.merge!(mapping)
|
||||||
|
end
|
||||||
|
scopes
|
||||||
end
|
end
|
||||||
|
|
||||||
def permits?(env)
|
def permits?(env)
|
||||||
|
@ -81,6 +81,7 @@ class DiscoursePluginRegistry
|
|||||||
|
|
||||||
define_filtered_register :api_parameter_routes
|
define_filtered_register :api_parameter_routes
|
||||||
define_filtered_register :api_key_scope_mappings
|
define_filtered_register :api_key_scope_mappings
|
||||||
|
define_filtered_register :user_api_key_scope_mappings
|
||||||
|
|
||||||
define_filtered_register :permitted_bulk_action_parameters
|
define_filtered_register :permitted_bulk_action_parameters
|
||||||
|
|
||||||
|
@ -793,6 +793,35 @@ class Plugin::Instance
|
|||||||
DiscoursePluginRegistry.register_api_key_scope_mapping({ resource => action }, self)
|
DiscoursePluginRegistry.register_api_key_scope_mapping({ resource => action }, self)
|
||||||
end
|
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
|
# 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:
|
# in a query parameter rather than a header. For example:
|
||||||
#
|
#
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
# frozen_string_literal: true
|
# 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(:user_api_key_scope)
|
||||||
|
|
||||||
Fabricator(:readonly_user_api_key, from: :user_api_key) do
|
Fabricator(:readonly_user_api_key, from: :user_api_key) do
|
||||||
user
|
|
||||||
scopes { [Fabricate.build(:user_api_key_scope, name: 'read')] }
|
scopes { [Fabricate.build(:user_api_key_scope, name: 'read')] }
|
||||||
client_id { SecureRandom.hex }
|
|
||||||
application_name 'some app'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Fabricator(:bookmarks_calendar_user_api_key, from: :user_api_key) do
|
Fabricator(:bookmarks_calendar_user_api_key, from: :user_api_key) do
|
||||||
user
|
|
||||||
scopes { [Fabricate.build(:user_api_key_scope, name: 'bookmarks_calendar')] }
|
scopes { [Fabricate.build(:user_api_key_scope, name: 'bookmarks_calendar')] }
|
||||||
client_id { SecureRandom.hex }
|
|
||||||
application_name 'some app'
|
|
||||||
end
|
end
|
||||||
|
@ -128,4 +128,24 @@ describe 'user api keys' do
|
|||||||
expect(response.status).to eq(200) # Can access own calendar
|
expect(response.status).to eq(200) # Can access own calendar
|
||||||
end
|
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
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user