]> git.openstreetmap.org Git - rails.git/commitdiff
Introduce privileged scopes that only an administrator can enable
authorTom Hughes <tom@compton.nu>
Fri, 30 Jul 2021 21:24:51 +0000 (22:24 +0100)
committerTom Hughes <tom@compton.nu>
Thu, 26 Aug 2021 16:22:24 +0000 (17:22 +0100)
app/controllers/oauth2_applications_controller.rb
app/models/oauth2_application.rb [new file with mode: 0644]
app/views/oauth2_applications/_form.html.erb
config/initializers/doorkeeper.rb
lib/oauth.rb
test/controllers/oauth2_applications_controller_test.rb
test/factories/oauth_applications.rb

index 63b77be4bce8f53b8495df2468dff236941db940..97d84b1737eb5d7b86c434f65c97f7328eacd251 100644 (file)
@@ -20,8 +20,8 @@ class Oauth2ApplicationsController < Doorkeeper::ApplicationsController
   end
 
   def application_params
-    params[:doorkeeper_application][:scopes]&.delete("")
-    params.require(:doorkeeper_application)
+    params[:oauth2_application][:scopes]&.delete("")
+    params.require(:oauth2_application)
           .permit(:name, :redirect_uri, :confidential, :scopes => [])
           .merge(:owner => current_resource_owner)
   end
diff --git a/app/models/oauth2_application.rb b/app/models/oauth2_application.rb
new file mode 100644 (file)
index 0000000..1657615
--- /dev/null
@@ -0,0 +1,13 @@
+class Oauth2Application < Doorkeeper::Application
+  belongs_to :owner, :polymorphic => true
+
+  validate :allowed_scopes
+
+  private
+
+  def allowed_scopes
+    return if owner.administrator?
+
+    errors.add(:scopes) if scopes.any? { |scope| Oauth::PRIVILEGED_SCOPES.include?(scope) }
+  end
+end
index d69536c6b3ca38ee3e78b1d2bccda01cfd493dfb..7fde3e0e7f19d57aa0ca9b2a4ca0d7a43e49e3b4 100644 (file)
@@ -3,5 +3,5 @@
 <%= f.form_group :confidential do %>
   <%= f.check_box :confidential %>
 <% end %>
-<%= f.collection_check_boxes :scopes, Oauth.scopes, :name, :description %>
+<%= f.collection_check_boxes :scopes, Oauth.scopes(:privileged => current_user.administrator?), :name, :description %>
 <%= f.primary %>
index 549138b3377cee55a7f71dc6bce30a9af451ce17..32156b8217e723f63dcdc439d229d33cef5f8c72 100644 (file)
@@ -48,6 +48,8 @@ Doorkeeper.configure do
   #   end
   # end
 
+  application_class "Oauth2Application"
+
   # Enables polymorphic Resource Owner association for Access Tokens and Access Grants.
   # By default this option is disabled.
   #
@@ -221,7 +223,7 @@ Doorkeeper.configure do
   # https://doorkeeper.gitbook.io/guides/ruby-on-rails/scopes
 
   # default_scopes  :public
-  optional_scopes(*Oauth::SCOPES)
+  optional_scopes(*Oauth::SCOPES, *Oauth::PRIVILEGED_SCOPES)
 
   # Allows to restrict only certain scopes for grant_type.
   # By default, all the scopes will be available for all the grant types.
index 8f45a3b4b3b438fa6eeffd4df4459f994a91dbdf..6980447f914d27338e5b09b6a36a775ae9357e42 100644 (file)
@@ -1,5 +1,6 @@
 module Oauth
   SCOPES = %w[read_prefs write_prefs write_diary write_api read_gpx write_gpx write_notes].freeze
+  PRIVILEGED_SCOPES = %w[].freeze
 
   class Scope
     attr_reader :name
@@ -13,7 +14,9 @@ module Oauth
     end
   end
 
-  def self.scopes
-    SCOPES.collect { |s| Scope.new(s) }
+  def self.scopes(privileged: false)
+    scopes = SCOPES
+    scopes += PRIVILEGED_SCOPES if privileged
+    scopes.collect { |s| Scope.new(s) }
   end
 end
index eec5e02ec926d46dd64a4eea1e3d7670427f35d6..338144a95d95e643c9b720e07f459845b29e7ea7 100644 (file)
@@ -67,11 +67,11 @@ class Oauth2ApplicationsControllerTest < ActionDispatch::IntegrationTest
     assert_response :success
     assert_template "oauth2_applications/new"
     assert_select "form", 1 do
-      assert_select "input#doorkeeper_application_name", 1
-      assert_select "textarea#doorkeeper_application_redirect_uri", 1
-      assert_select "input#doorkeeper_application_confidential", 1
+      assert_select "input#oauth2_application_name", 1
+      assert_select "textarea#oauth2_application_redirect_uri", 1
+      assert_select "input#oauth2_application_confidential", 1
       Oauth.scopes.each do |scope|
-        assert_select "input#doorkeeper_application_scopes_#{scope.name}", 1
+        assert_select "input#oauth2_application_scopes_#{scope.name}", 1
       end
     end
   end
@@ -87,7 +87,7 @@ class Oauth2ApplicationsControllerTest < ActionDispatch::IntegrationTest
     session_for(user)
 
     assert_difference "Doorkeeper::Application.count", 0 do
-      post oauth_applications_path(:doorkeeper_application => {
+      post oauth_applications_path(:oauth2_application => {
                                      :name => "Test Application"
                                    })
     end
@@ -95,7 +95,7 @@ class Oauth2ApplicationsControllerTest < ActionDispatch::IntegrationTest
     assert_template "oauth2_applications/new"
 
     assert_difference "Doorkeeper::Application.count", 0 do
-      post oauth_applications_path(:doorkeeper_application => {
+      post oauth_applications_path(:oauth2_application => {
                                      :name => "Test Application",
                                      :redirect_uri => "https://test.example.com/",
                                      :scopes => ["bad_scope"]
@@ -105,7 +105,7 @@ class Oauth2ApplicationsControllerTest < ActionDispatch::IntegrationTest
     assert_template "oauth2_applications/new"
 
     assert_difference "Doorkeeper::Application.count", 1 do
-      post oauth_applications_path(:doorkeeper_application => {
+      post oauth_applications_path(:oauth2_application => {
                                      :name => "Test Application",
                                      :redirect_uri => "https://test.example.com/",
                                      :scopes => ["read_prefs"]
@@ -154,11 +154,11 @@ class Oauth2ApplicationsControllerTest < ActionDispatch::IntegrationTest
     assert_response :success
     assert_template "oauth2_applications/edit"
     assert_select "form", 1 do
-      assert_select "input#doorkeeper_application_name", 1
-      assert_select "textarea#doorkeeper_application_redirect_uri", 1
-      assert_select "input#doorkeeper_application_confidential", 1
+      assert_select "input#oauth2_application_name", 1
+      assert_select "textarea#oauth2_application_redirect_uri", 1
+      assert_select "input#oauth2_application_confidential", 1
       Oauth.scopes.each do |scope|
-        assert_select "input#doorkeeper_application_scopes_#{scope.name}", 1
+        assert_select "input#oauth2_application_scopes_#{scope.name}", 1
       end
     end
   end
@@ -178,7 +178,7 @@ class Oauth2ApplicationsControllerTest < ActionDispatch::IntegrationTest
     assert_template "oauth2_applications/not_found"
 
     put oauth_application_path(:id => client,
-                               :doorkeeper_application => {
+                               :oauth2_application => {
                                  :name => "New Name",
                                  :redirect_uri => nil
                                })
@@ -186,7 +186,7 @@ class Oauth2ApplicationsControllerTest < ActionDispatch::IntegrationTest
     assert_template "oauth2_applications/edit"
 
     put oauth_application_path(:id => client,
-                               :doorkeeper_application => {
+                               :oauth2_application => {
                                  :name => "New Name",
                                  :redirect_uri => "https://new.example.com/url"
                                })
index a9b3b875da7b003ff912b879aae2b9fce2547934..1e62d2c973eaff522ae26cc26aba99cad5b5add3 100644 (file)
@@ -1,5 +1,5 @@
 FactoryBot.define do
-  factory :oauth_application, :class => "Doorkeeper::Application" do
+  factory :oauth_application, :class => "Oauth2Application" do
     sequence(:name) { |n| "OAuth application #{n}" }
     sequence(:redirect_uri) { |n| "https://example.com/app/#{n}" }