Skip to content

Commit

Permalink
Update user access level via v1 API
Browse files Browse the repository at this point in the history
  • Loading branch information
colby-swandale committed Jul 11, 2024
1 parent 758245e commit eb41a17
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 4 deletions.
24 changes: 23 additions & 1 deletion app/controllers/api/v1/owners_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ class Api::V1::OwnersController < Api::BaseController
before_action :verify_api_key_gem_scope, except: %i[show gems]
before_action :verify_mfa_requirement, except: %i[show gems]
before_action :verify_with_otp, except: %i[show gems]
before_action :find_ownership_for_destroy, only: :destroy
before_action :find_ownership_for_destroy, only: %i[destroy]
before_action :find_ownership_for_update, only: %i[update]

def show
respond_to do |format|
Expand All @@ -31,6 +32,15 @@ def create
end
end

def update
if @ownership.present?
@ownership.update!(update_params)
render plain: response_with_mfa_warning("Owner updated successfully.") if @ownership.update(update_params)

Check warning on line 38 in app/controllers/api/v1/owners_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/api/v1/owners_controller.rb#L36-L38

Added lines #L36 - L38 were not covered by tests
else
render plain: response_with_mfa_warning("Unable to update owner."), status: :forbidden

Check warning on line 40 in app/controllers/api/v1/owners_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/api/v1/owners_controller.rb#L40

Added line #L40 was not covered by tests
end
end

def destroy
if @ownership.safe_destroy
OwnersMailer.owner_removed(@ownership.user_id, @api_key.user.id, @ownership.rubygem_id).deliver_later
Expand Down Expand Up @@ -58,6 +68,14 @@ def gems

protected

def find_ownership_for_update
authorize @rubygem, :update_owner?
@owner = @rubygem.owners_including_unconfirmed.find_by_name(email_param)
@ownership = @rubygem.ownerships_including_unconfirmed.find_by(user: @owner)
return render_owner_not_found unless @owner && @ownership
authorize @ownership

Check warning on line 76 in app/controllers/api/v1/owners_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/api/v1/owners_controller.rb#L73-L76

Added lines #L73 - L76 were not covered by tests
end

def find_ownership_for_destroy
authorize @rubygem, :remove_owner?
@owner = @rubygem.owners_including_unconfirmed.find_by_name(email_param)
Expand All @@ -73,4 +91,8 @@ def render_owner_not_found
def email_param
params.permit(:email).require(:email)
end

def update_params
params.permit(:access_level)

Check warning on line 96 in app/controllers/api/v1/owners_controller.rb

View check run for this annotation

Codecov / codecov/patch

app/controllers/api/v1/owners_controller.rb#L96

Added line #L96 was not covered by tests
end
end
4 changes: 2 additions & 2 deletions app/models/api_key.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
class ApiKey < ApplicationRecord
class ScopeError < RuntimeError; end

API_SCOPES = %i[show_dashboard index_rubygems push_rubygem yank_rubygem add_owner remove_owner access_webhooks
API_SCOPES = %i[show_dashboard index_rubygems push_rubygem yank_rubygem add_owner update_owner remove_owner access_webhooks
configure_trusted_publishers].freeze
APPLICABLE_GEM_API_SCOPES = %i[push_rubygem yank_rubygem add_owner remove_owner configure_trusted_publishers].freeze
APPLICABLE_GEM_API_SCOPES = %i[push_rubygem yank_rubygem add_owner update_owner remove_owner configure_trusted_publishers].freeze
EXCLUSIVE_SCOPES = %i[show_dashboard].freeze

self.ignored_columns += API_SCOPES
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
delete :yank, to: "deletions#create"
end
constraints rubygem_id: Patterns::ROUTE_PATTERN do
resource :owners, only: %i[show create destroy]
resource :owners, only: %i[show create destroy update]
resources :trusted_publishers, controller: 'oidc/rubygem_trusted_publishers', only: %i[index create destroy show]
end
end
Expand Down
27 changes: 27 additions & 0 deletions test/functional/api/v1/owners_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -965,4 +965,31 @@ def self.should_respond_to(format)

assert_equal "This rubygem could not be found.", @response.body
end

should "route PUT /api/v1/gems/rubygem/owners.yaml" do
route = { controller: "api/v1/owners",
action: "update",
rubygem_id: "rails",
format: "yaml" }

assert_recognizes(route, path: "/api/v1/gems/rails/owners.yaml", method: :put)
end

context "on PATCH to owner gem" do
setup do
@user = create(:user)
@maintainer = create(:user)
@rubygem = create(:rubygem, owners: [@user, @maintainer])

@api_key = create(:api_key, key: "12223", scopes: %i[update_owner], owner: @user, rubygem: @rubygem)
@request.env["HTTP_AUTHORIZATION"] = "12223"
end

should "set the maintainer to a lower access level" do
patch :update, params: { rubygem_id: @rubygem.slug, email: @maintainer.email, access_level: Access::MAINTAINER }

assert_response :success
assert_equal Access::MAINTAINER, @maintainer.reload.ownerships.find_by(rubygem: @rubygem).access_level
end
end
end

0 comments on commit eb41a17

Please sign in to comment.