diff --git a/app/controllers/session_controller.rb b/app/controllers/session_controller.rb index beefb526e20..23556d7590c 100644 --- a/app/controllers/session_controller.rb +++ b/app/controllers/session_controller.rb @@ -598,6 +598,16 @@ class SessionController < ApplicationController } end + def scopes + if is_api? + key = request.env[Auth::DefaultCurrentUserProvider::HEADER_API_KEY] + api_key = ApiKey.active.with_key(key).first + render_serialized(api_key.api_key_scopes, ApiKeyScopeSerializer, root: 'scopes') + else + render body: nil, status: 404 + end + end + protected def normalized_login_param diff --git a/app/models/api_key.rb b/app/models/api_key.rb index 99f8e209ac4..1849f2cd398 100644 --- a/app/models/api_key.rb +++ b/app/models/api_key.rb @@ -64,6 +64,7 @@ class ApiKey < ActiveRecord::Base def request_allowed?(env) return false if allowed_ips.present? && allowed_ips.none? { |ip| ip.include?(Rack::Request.new(env).ip) } + return true if RouteMatcher.new(methods: :get, actions: "session#scopes").match?(env: env) api_key_scopes.blank? || api_key_scopes.any? { |s| s.permits?(env) } end diff --git a/app/models/api_key_scope.rb b/app/models/api_key_scope.rb index 07d532f22a9..6c157566a2c 100644 --- a/app/models/api_key_scope.rb +++ b/app/models/api_key_scope.rb @@ -30,8 +30,7 @@ class ApiKeyScope < ActiveRecord::Base read_lists: { actions: list_actions, params: %i[category_id], aliases: { category_id: :category_slug_path_with_id } - }, - wordpress: { actions: %w[topics#wordpress], params: %i[topic_id] } + } }, posts: { edit: { actions: %w[posts#update], params: %i[id] } @@ -75,6 +74,12 @@ class ApiKeyScope < ActiveRecord::Base list_user_badges: { actions: %w[user_badges#username], params: %i[username] }, assign_badge_to_user: { actions: %w[user_badges#create], params: %i[username] }, revoke_badge_from_user: { actions: %w[user_badges#destroy] }, + }, + wordpress: { + publishing: { actions: %w[site#site posts#create topics#update topics#status topics#show] }, + commenting: { actions: %w[topics#wordpress] }, + discourse_connect: { actions: %w[admin/users#sync_sso admin/users#log_out admin/users#index users#show] }, + utilities: { actions: %w[users#create groups#index] } } } diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 957d491793b..d9086c82d65 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -4265,7 +4265,6 @@ en: write: Create a new topic or post to an existing one. update: Update a topic. Change the title, category, tags, etc. read_lists: Read topic lists like top, new, latest, etc. RSS is also supported. - wordpress: Necessary for the WordPress wp-discourse plugin to work. posts: edit: Edit any post or a specific one. categories: @@ -4293,6 +4292,11 @@ en: list_user_badges: List user badges. assign_badge_to_user: Assign a badge to a user. revoke_badge_from_user: Revoke a badge from a user. + wordpress: + publishing: Necessary for the WP Discourse plugin publishing features (required). + commenting: Necessary for the WP Discourse plugin commenting features. + discourse_connect: Necessary for the WP Discourse plugin DiscourseConnect features. + utilities: Necessary if you use WP Discourse plugin Utilities. web_hooks: title: "Webhooks" diff --git a/config/routes.rb b/config/routes.rb index e7c73c0990f..32626b02a22 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -383,6 +383,7 @@ Discourse::Application.routes.draw do if Rails.env.test? post "session/2fa/test-action" => "session#test_second_factor_restricted_route" end + get "session/scopes" => "session#scopes" get "composer_messages" => "composer_messages#index" resources :static diff --git a/spec/requests/admin/api_controller_spec.rb b/spec/requests/admin/api_controller_spec.rb index a8b863ceff5..b9f0c202933 100644 --- a/spec/requests/admin/api_controller_spec.rb +++ b/spec/requests/admin/api_controller_spec.rb @@ -235,7 +235,7 @@ describe Admin::ApiController do scopes = response.parsed_body['scopes'] - expect(scopes.keys).to contain_exactly('topics', 'users', 'email', 'posts', 'uploads', 'global', 'badges', 'categories') + expect(scopes.keys).to contain_exactly('topics', 'users', 'email', 'posts', 'uploads', 'global', 'badges', 'categories', 'wordpress') end end end diff --git a/spec/requests/session_controller_spec.rb b/spec/requests/session_controller_spec.rb index f28919e5ed1..a9c41ebe1e0 100644 --- a/spec/requests/session_controller_spec.rb +++ b/spec/requests/session_controller_spec.rb @@ -2628,4 +2628,33 @@ describe SessionController do expect(response.status).to eq(401) end end + + describe '#scopes' do + context "when not a valid api request" do + it "returns 404" do + get "/session/scopes.json" + expect(response.status).to eq(404) + end + end + + context "when a valid api request" do + let(:admin) { Fabricate(:admin) } + let(:scope) { ApiKeyScope.new(resource: 'topics', action: 'read', allowed_parameters: { topic_id: '3' }) } + let(:api_key) { Fabricate(:api_key, user: admin, api_key_scopes: [scope]) } + + it "returns the scopes of the api key" do + get "/session/scopes.json", headers: { + "Api-Key": api_key.key, + "Api-Username": admin.username + } + expect(response.status).to eq(200) + + json = response.parsed_body + expect(json['scopes'].size).to eq(1) + expect(json['scopes'].first["resource"]).to eq("topics") + expect(json['scopes'].first["action"]).to eq("read") + expect(json['scopes'].first["allowed_parameters"]).to eq({ "topic_id": "3" }.as_json) + end + end + end end